diff options
author | shennetsind <notind@gmail.com> | 2013-05-17 11:08:38 -0700 |
---|---|---|
committer | shennetsind <notind@gmail.com> | 2013-05-17 11:08:38 -0700 |
commit | 080f7a22740225df70a488849587b462a5d6b1a3 (patch) | |
tree | 0c1dc751af9f06e1ce3729d271de301f78a4e611 /src | |
parent | 754af15505f32237f8063e51ae9a1cb90788dff4 (diff) | |
parent | 25e848f1a0f9317d63106cae048a1ef838411cb2 (diff) | |
download | hercules-080f7a22740225df70a488849587b462a5d6b1a3.tar.gz hercules-080f7a22740225df70a488849587b462a5d6b1a3.tar.bz2 hercules-080f7a22740225df70a488849587b462a5d6b1a3.tar.xz hercules-080f7a22740225df70a488849587b462a5d6b1a3.zip |
Merge pull request #1 from Earisu/master
updating, with earisu's
Diffstat (limited to 'src')
127 files changed, 42316 insertions, 33286 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 94ccf4183..100958358 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -17,3 +17,4 @@ add_subdirectory( login ) add_subdirectory( char ) add_subdirectory( map ) add_subdirectory( tool ) +add_subdirectory( plugins )
\ No newline at end of file diff --git a/src/char/CMakeLists.txt b/src/char/CMakeLists.txt index 22b793bef..9413ff303 100644 --- a/src/char/CMakeLists.txt +++ b/src/char/CMakeLists.txt @@ -9,7 +9,7 @@ set( SQL_CHAR_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR} CACHE INTERNAL "" ) # char sql # if( BUILD_SQL_SERVERS ) -message( STATUS "Creating target char-server_sql" ) +message( STATUS "Creating target char-server" ) set( SQL_CHAR_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/char.h" "${CMAKE_CURRENT_SOURCE_DIR}/int_auction.h" @@ -23,6 +23,7 @@ set( SQL_CHAR_HEADERS "${CMAKE_CURRENT_SOURCE_DIR}/int_quest.h" "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.h" "${CMAKE_CURRENT_SOURCE_DIR}/inter.h" + "${CMAKE_CURRENT_SOURCE_DIR}/pincode.h" ) set( SQL_CHAR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/char.c" @@ -37,6 +38,7 @@ set( SQL_CHAR_SOURCES "${CMAKE_CURRENT_SOURCE_DIR}/int_quest.c" "${CMAKE_CURRENT_SOURCE_DIR}/int_storage.c" "${CMAKE_CURRENT_SOURCE_DIR}/inter.c" + "${CMAKE_CURRENT_SOURCE_DIR}/pincode.c" ) set( DEPENDENCIES common_sql ) set( LIBRARIES ${GLOBAL_LIBRARIES} ) @@ -46,15 +48,15 @@ set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_CHAR_HEADER source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ) source_group( char FILES ${SQL_CHAR_HEADERS} ${SQL_CHAR_SOURCES} ) include_directories( ${INCLUDE_DIRS} ) -add_executable( char-server_sql ${SOURCE_FILES} ) -add_dependencies( char-server_sql ${DEPENDENCIES} ) -target_link_libraries( char-server_sql ${LIBRARIES} ${DEPENDENCIES} ) -set_target_properties( char-server_sql PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) +add_executable( char-server ${SOURCE_FILES} ) +add_dependencies( char-server ${DEPENDENCIES} ) +target_link_libraries( char-server ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( char-server PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_charserver_sql DESCRIPTION "char-server (sql version)" DISPLAY_NAME "char-server_sql" GROUP Runtime ) - install( TARGETS char-server_sql + cpack_add_component( Runtime_charserver_sql DESCRIPTION "char-server (sql version)" DISPLAY_NAME "char-server" GROUP Runtime ) + install( TARGETS char-server DESTINATION "." COMPONENT Runtime_charserver_sql ) endif( INSTALL_COMPONENT_RUNTIME ) -message( STATUS "Creating target char-server_sql - done" ) +message( STATUS "Creating target char-server - done" ) endif( BUILD_SQL_SERVERS ) diff --git a/src/char/Makefile.in b/src/char/Makefile.in index bfe9d1585..a320579b5 100644 --- a/src/char/Makefile.in +++ b/src/char/Makefile.in @@ -16,8 +16,8 @@ COMMON_SQL_OBJ = ../common/obj_sql/sql.o COMMON_H = ../common/sql.h CHAR_OBJ = obj_sql/char.o obj_sql/inter.o obj_sql/int_party.o obj_sql/int_guild.o \ - obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o obj_sql/int_elemental.o -CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h + obj_sql/int_storage.o obj_sql/int_pet.o obj_sql/int_homun.o obj_sql/int_mail.o obj_sql/int_auction.o obj_sql/int_quest.o obj_sql/int_mercenary.o obj_sql/int_elemental.o obj_sql/pincode.o +CHAR_H = char.h inter.h int_party.h int_guild.h int_storage.h int_pet.h int_homun.h int_mail.h int_auction.h int_quest.h int_mercenary.h int_elemental.h pincode.h HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) @@ -29,21 +29,21 @@ endif @SET_MAKE@ ##################################################################### -.PHONY : all char-server_sql clean help +.PHONY : all char-server clean help -all: char-server_sql +all: char-server -char-server_sql: $(CHAR_SERVER_SQL_DEPENDS) +char-server: $(CHAR_SERVER_SQL_DEPENDS) @echo " LD $@" - @@CC@ @LDFLAGS@ -o ../../char-server_sql@EXEEXT@ $(CHAR_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ + @@CC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ clean: @echo " CLEAN char" - @rm -rf *.o obj_sql ../../char-server_sql@EXEEXT@ + @rm -rf *.o obj_sql ../../char-server@EXEEXT@ help: - @echo "possible targets are 'char-server_sql' 'all' 'clean' 'help'" - @echo "'char-server_sql' - char server (SQL version)" + @echo "possible targets are 'char-server' 'all' 'clean' 'help'" + @echo "'char-server' - char server (SQL version)" @echo "'all' - builds all above targets" @echo "'clean' - cleans builds and objects" @echo "'help' - outputs this message" diff --git a/src/char/char.c b/src/char/char.c index f21730d3b..00fc633df 100644 --- a/src/char/char.c +++ b/src/char/char.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/core.h" @@ -20,6 +21,7 @@ #include "int_storage.h" #include "char.h" #include "inter.h" +#include "pincode.h" #include <sys/types.h> #include <time.h> @@ -82,7 +84,7 @@ struct mmo_map_server { unsigned short map[MAX_MAP_PER_SERVER]; } server[MAX_MAP_SERVERS]; -int login_fd=-1, char_fd=-1; +int char_fd=-1; char userid[24]; char passwd[24]; char server_name[20]; @@ -105,7 +107,6 @@ char unknown_char_name[NAME_LENGTH] = "Unknown"; // Name to use when the request #define TRIM_CHARS "\255\xA0\032\t\x0A\x0D " //The following characters are trimmed regardless because they cause confusion and problems on the servers. [Skotlex] char char_name_letters[1024] = ""; // list of letters/symbols allowed (or not) in a character name. by [Yor] -int char_per_account = 0; //Maximum chars per account (default unlimited) [Sirius] int char_del_level = 0; //From which level u can delete character [Lupus] int char_del_delay = 86400; @@ -120,25 +121,11 @@ struct s_subnet { } subnet[16]; int subnet_count = 0; -struct char_session_data { - bool auth; // whether the session is authed or not - int account_id, login_id1, login_id2, sex; - int found_char[MAX_CHARS]; // ids of chars on this account - char email[40]; // e-mail (default: a@a.com) by [Yor] - time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) - int group_id; // permission - uint32 version; - uint8 clienttype; - char new_name[NAME_LENGTH]; - char birthdate[10+1]; // YYYY-MM-DD -}; - -int max_connect_user = 0; +int max_connect_user = -1; int gm_allow_group = -1; int autosave_interval = DEFAULT_AUTOSAVE_INTERVAL; int start_zeny = 0; -int start_weapon = 1201; -int start_armor = 2301; +int start_items[MAX_START_ITEMS*2]; int guild_exp_rate = 100; //Custom limits for the fame lists. [Skotlex] @@ -159,7 +146,7 @@ unsigned int save_flag = 0; // Initial position (it's possible to set it in conf file) struct point start_point = { 0, 53, 111 }; -int console = 0; +unsigned short skillid2idx[MAX_SKILL_ID]; //----------------------------------------------------- // Auth database @@ -184,15 +171,6 @@ static DBMap* auth_db; // int account_id -> struct auth_node* // Online User Database //----------------------------------------------------- -struct online_char_data { - int account_id; - int char_id; - int fd; - int waiting_disconnect; - short server; // -2: unknown server, -1: not connected, 0+: id of server -}; - -static DBMap* online_char_db; // int account_id -> struct online_char_data* static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_t data); int delete_char_sql(int char_id); @@ -206,9 +184,10 @@ static DBData create_online_char_data(DBKey key, va_list args) character->account_id = key.i; character->char_id = -1; character->server = -1; + character->pincode_enable = -1; character->fd = -1; character->waiting_disconnect = INVALID_TIMER; - return db_ptr2data(character); + return DB->ptr2data(character); } void set_char_charselect(int account_id) @@ -223,6 +202,8 @@ void set_char_charselect(int account_id) character->char_id = -1; character->server = -1; + if(character->pincode_enable == -1) + character->pincode_enable = *pincode->charselect + *pincode->enabled; if(character->waiting_disconnect != INVALID_TIMER) { delete_timer(character->waiting_disconnect, chardb_waiting_disconnect); @@ -245,7 +226,7 @@ void set_char_online(int map_id, int char_id, int account_id) struct mmo_charstatus *cp; //Update DB - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `online`='1' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) ) Sql_ShowDebug(sql_handle); //Check to see for online conflicts @@ -290,7 +271,7 @@ void set_char_offline(int char_id, int account_id) if ( char_id == -1 ) { - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `account_id`='%d'", char_db, account_id) ) Sql_ShowDebug(sql_handle); } else @@ -300,7 +281,7 @@ void set_char_offline(int char_id, int account_id) if (cp) idb_remove(char_db_,char_id); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `online`='0' WHERE `char_id`='%d' LIMIT 1", char_db, char_id) ) Sql_ShowDebug(sql_handle); } @@ -319,6 +300,7 @@ void set_char_offline(int char_id, int account_id) { character->char_id = -1; character->server = -1; + character->pincode_enable = -1; } //FIXME? Why Kevin free'd the online information when the char was effectively in the map-server? @@ -339,7 +321,7 @@ void set_char_offline(int char_id, int account_id) */ static int char_db_setoffline(DBKey key, DBData *data, va_list ap) { - struct online_char_data* character = (struct online_char_data*)db_data2ptr(data); + struct online_char_data* character = (struct online_char_data*)DB->data2ptr(data); int server = va_arg(ap, int); if (server == -1) { character->char_id = -1; @@ -358,7 +340,7 @@ static int char_db_setoffline(DBKey key, DBData *data, va_list ap) */ static int char_db_kickoffline(DBKey key, DBData *data, va_list ap) { - struct online_char_data* character = (struct online_char_data*)db_data2ptr(data); + struct online_char_data* character = (struct online_char_data*)DB->data2ptr(data); int server_id = va_arg(ap, int); if (server_id > -1 && character->server != server_id) @@ -394,11 +376,11 @@ void set_all_offline(int id) void set_all_offline_sql(void) { //Set all players to 'OFFLINE' - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", char_db) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `online` = '0'", char_db) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `online` = '0'", guild_member_db) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `online` = '0'", guild_member_db) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", guild_db) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `connect_member` = '0'", guild_db) ) Sql_ShowDebug(sql_handle); } @@ -410,7 +392,7 @@ static DBData create_charstatus(DBKey key, va_list args) struct mmo_charstatus *cp; cp = (struct mmo_charstatus *) aCalloc(1,sizeof(struct mmo_charstatus)); cp->char_id = key.i; - return db_ptr2data(cp); + return DB->ptr2data(cp); } int inventory_to_sql(const struct item items[], int max, int id); @@ -429,7 +411,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) cp = idb_ensure(char_db_, char_id, create_charstatus); - StringBuf_Init(&buf); + StrBuf->Init(&buf); memset(save_status, 0, sizeof(save_status)); //map inventory data @@ -455,7 +437,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) else errors++; } - + if ( (p->base_exp != cp->base_exp) || (p->base_level != cp->base_level) || (p->job_level != cp->job_level) || (p->job_exp != cp->job_exp) || @@ -472,17 +454,24 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) (p->pet_id != cp->pet_id) || (p->weapon != cp->weapon) || (p->hom_id != cp->hom_id) || (p->ele_id != cp->ele_id) || (p->shield != cp->shield) || (p->head_top != cp->head_top) || (p->head_mid != cp->head_mid) || (p->head_bottom != cp->head_bottom) || (p->delete_date != cp->delete_date) || - (p->rename != cp->rename) || (p->robe != cp->robe) - ) - { //Save status - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," + (p->rename != cp->rename) || (p->slotchange != cp->slotchange) || (p->robe != cp->robe) || + (p->show_equip != cp->show_equip) || (p->allow_party != cp->allow_party) + ) { //Save status + unsigned int opt = 0; + + if( p->allow_party ) + opt |= OPT_ALLOW_PARTY; + if( p->show_equip ) + opt |= OPT_SHOW_EQUIP; + + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `base_level`='%d', `job_level`='%d'," "`base_exp`='%u', `job_exp`='%u', `zeny`='%d'," "`max_hp`='%d',`hp`='%d',`max_sp`='%d',`sp`='%d',`status_point`='%d',`skill_point`='%d'," "`str`='%d',`agi`='%d',`vit`='%d',`int`='%d',`dex`='%d',`luk`='%d'," "`option`='%d',`party_id`='%d',`guild_id`='%d',`pet_id`='%d',`homun_id`='%d',`elemental_id`='%d'," "`weapon`='%d',`shield`='%d',`head_top`='%d',`head_mid`='%d',`head_bottom`='%d'," "`last_map`='%s',`last_x`='%d',`last_y`='%d',`save_map`='%s',`save_x`='%d',`save_y`='%d', `rename`='%d'," - "`delete_date`='%lu',`robe`='%d'" + "`delete_date`='%lu',`robe`='%d',`slotchange`='%d', `char_opt`='%u'" " WHERE `account_id`='%d' AND `char_id` = '%d'", char_db, p->base_level, p->job_level, p->base_exp, p->job_exp, p->zeny, @@ -493,7 +482,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) mapindex_id2name(p->last_point.map), p->last_point.x, p->last_point.y, mapindex_id2name(p->save_point.map), p->save_point.x, p->save_point.y, p->rename, (unsigned long)p->delete_date, // FIXME: platform-dependent size - p->robe, + p->robe,p->slotchange,opt, p->account_id, p->char_id) ) { Sql_ShowDebug(sql_handle); @@ -512,7 +501,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) (p->fame != cp->fame) ) { - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d'," + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `class`='%d'," "`hair`='%d',`hair_color`='%d',`clothes_color`='%d'," "`partner_id`='%d', `father`='%d', `mother`='%d', `child`='%d'," "`karma`='%d',`manner`='%d', `fame`='%d'" @@ -547,29 +536,29 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) char esc_mapname[NAME_LENGTH*2+1]; //`memo` (`memo_id`,`char_id`,`map`,`x`,`y`) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, p->char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, p->char_id) ) { Sql_ShowDebug(sql_handle); errors++; } //insert here. - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db); + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s`(`char_id`,`map`,`x`,`y`) VALUES ", memo_db); for( i = 0, count = 0; i < MAX_MEMOPOINTS; ++i ) { if( p->memo_point[i].map ) { if( count ) - StringBuf_AppendStr(&buf, ","); - Sql_EscapeString(sql_handle, esc_mapname, mapindex_id2name(p->memo_point[i].map)); - StringBuf_Printf(&buf, "('%d', '%s', '%d', '%d')", char_id, esc_mapname, p->memo_point[i].x, p->memo_point[i].y); + StrBuf->AppendStr(&buf, ","); + SQL->EscapeString(sql_handle, esc_mapname, mapindex_id2name(p->memo_point[i].map)); + StrBuf->Printf(&buf, "('%d', '%s', '%d', '%d')", char_id, esc_mapname, p->memo_point[i].x, p->memo_point[i].y); ++count; } } if( count ) { - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; @@ -578,42 +567,35 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) strcat(save_status, " memo"); } - //FIXME: is this neccessary? [ultramage] - for(i=0;i<MAX_SKILL;i++) - if ((p->skill[i].lv != 0) && (p->skill[i].id == 0)) - p->skill[i].id = i; // Fix skill tree - - //skills - if( memcmp(p->skill, cp->skill, sizeof(p->skill)) ) - { + if( memcmp(p->skill, cp->skill, sizeof(p->skill)) ) { //`skill` (`char_id`, `id`, `lv`) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) ) - { + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, p->char_id) ) { Sql_ShowDebug(sql_handle); errors++; } - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`) VALUES ", skill_db); + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s`(`char_id`,`id`,`lv`,`flag`) VALUES ", skill_db); //insert here. - for( i = 0, count = 0; i < MAX_SKILL; ++i ) - { - if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) - { - if( p->skill[i].flag == SKILL_FLAG_PERMANENT && p->skill[i].lv == 0 ) + for( i = 0, count = 0; i < MAX_SKILL; ++i ) { + if( p->skill[i].id != 0 && p->skill[i].flag != SKILL_FLAG_TEMPORARY ) { + + if( p->skill[i].lv == 0 && ( p->skill[i].flag == SKILL_FLAG_PERM_GRANTED || p->skill[i].flag == SKILL_FLAG_PERMANENT ) ) continue; - if( p->skill[i].flag != SKILL_FLAG_PERMANENT && (p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0) == 0 ) + if( p->skill[i].flag != SKILL_FLAG_PERMANENT && p->skill[i].flag != SKILL_FLAG_PERM_GRANTED && (p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0) == 0 ) continue; if( count ) - StringBuf_AppendStr(&buf, ","); - StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->skill[i].id, (p->skill[i].flag == SKILL_FLAG_PERMANENT ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0)); + StrBuf->AppendStr(&buf, ","); + StrBuf->Printf(&buf, "('%d','%d','%d','%d')", char_id, p->skill[i].id, + ( (p->skill[i].flag == SKILL_FLAG_PERMANENT || p->skill[i].flag == SKILL_FLAG_PERM_GRANTED) ? p->skill[i].lv : p->skill[i].flag - SKILL_FLAG_REPLACED_LV_0), + p->skill[i].flag == SKILL_FLAG_PERM_GRANTED ? p->skill[i].flag : 0);/* other flags do not need to be saved */ ++count; } } if( count ) { - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; @@ -634,27 +616,27 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) if(diff == 1) { //Save friends - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", friend_db, char_id) ) { Sql_ShowDebug(sql_handle); errors++; } - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db); + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s` (`char_id`, `friend_account`, `friend_id`) VALUES ", friend_db); for( i = 0, count = 0; i < MAX_FRIENDS; ++i ) { if( p->friends[i].char_id > 0 ) { if( count ) - StringBuf_AppendStr(&buf, ","); - StringBuf_Printf(&buf, "('%d','%d','%d')", char_id, p->friends[i].account_id, p->friends[i].char_id); + StrBuf->AppendStr(&buf, ","); + StrBuf->Printf(&buf, "('%d','%d','%d')", char_id, p->friends[i].account_id, p->friends[i].char_id); count++; } } if( count ) { - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; @@ -665,20 +647,20 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) #ifdef HOTKEY_SAVING // hotkeys - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db); + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "REPLACE INTO `%s` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`) VALUES ", hotkey_db); diff = 0; for(i = 0; i < ARRAYLENGTH(p->hotkeys); i++){ if(memcmp(&p->hotkeys[i], &cp->hotkeys[i], sizeof(struct hotkey))) { if( diff ) - StringBuf_AppendStr(&buf, ",");// not the first hotkey - StringBuf_Printf(&buf, "('%d','%u','%u','%u','%u')", char_id, (unsigned int)i, (unsigned int)p->hotkeys[i].type, p->hotkeys[i].id , (unsigned int)p->hotkeys[i].lv); + StrBuf->AppendStr(&buf, ",");// not the first hotkey + StrBuf->Printf(&buf, "('%d','%u','%u','%u','%u')", char_id, (unsigned int)i, (unsigned int)p->hotkeys[i].type, p->hotkeys[i].id , (unsigned int)p->hotkeys[i].lv); diff = 1; } } if(diff) { - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; @@ -686,7 +668,7 @@ int mmo_char_tosql(int char_id, struct mmo_charstatus* p) strcat(save_status, " hotkeys"); } #endif - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); if (save_status[0]!='\0' && save_log) ShowInfo("Saved char %d - %s:%s.\n", char_id, p->name, save_status); if (!errors) @@ -724,19 +706,19 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit // This approach is more complicated than a trivial delete&insert, but // it significantly reduces cpu load on the database server. - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`"); + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`"); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id); + StrBuf->Printf(&buf, ", `card%d`", j); + StrBuf->Printf(&buf, " FROM `%s` WHERE `%s`='%d'", tablename, selectoption, id); stmt = SqlStmt_Malloc(sql_handle); - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StrBuf->Value(&buf)) || SQL_ERROR == SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return 1; } @@ -781,14 +763,14 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit else { // update all fields. - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u'", + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u'", tablename, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); - StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); + StrBuf->Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); + StrBuf->Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; @@ -801,7 +783,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit } if( !found ) {// Item not present in inventory, remove it. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", tablename, item.id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", tablename, item.id) ) { Sql_ShowDebug(sql_handle); errors++; @@ -810,11 +792,11 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit } SqlStmt_Free(stmt); - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `unique_id`", tablename, selectoption); + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s`(`%s`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `unique_id`", tablename, selectoption); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_AppendStr(&buf, ") VALUES "); + StrBuf->Printf(&buf, ", `card%d`", j); + StrBuf->AppendStr(&buf, ") VALUES "); found = false; // insert non-matched items into the db as new items @@ -825,27 +807,27 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit continue; if( found ) - StringBuf_AppendStr(&buf, ","); + StrBuf->AppendStr(&buf, ","); else found = true; - StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%"PRIu64"'", + StrBuf->Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%"PRIu64"'", id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].unique_id); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", '%d'", items[i].card[j]); - StringBuf_AppendStr(&buf, ")"); + StrBuf->Printf(&buf, ", '%d'", items[i].card[j]); + StrBuf->AppendStr(&buf, ")"); updateLastUid(items[i].unique_id); // Unique Non Stackable Item ID } dbUpdateUid(sql_handle); // Unique Non Stackable Item ID - if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) + if( found && SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; } - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); aFree(flag); return errors; @@ -868,19 +850,19 @@ int inventory_to_sql(const struct item items[], int max, int id) { // This approach is more complicated than a trivial delete&insert, but // it significantly reduces cpu load on the database server. - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`"); + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`"); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id); + StrBuf->Printf(&buf, ", `card%d`", j); + StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`='%d'", inventory_db, id); stmt = SqlStmt_Malloc(sql_handle); - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StrBuf->Value(&buf)) || SQL_ERROR == SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return 1; } @@ -924,14 +906,14 @@ int inventory_to_sql(const struct item items[], int max, int id) { ; //Do nothing. else { // update all fields. - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d'", + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "UPDATE `%s` SET `amount`='%d', `equip`='%d', `identify`='%d', `refine`='%d',`attribute`='%d', `expire_time`='%u', `favorite`='%d'", inventory_db, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); - StringBuf_Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); + StrBuf->Printf(&buf, ", `card%d`=%d", j, items[i].card[j]); + StrBuf->Printf(&buf, " WHERE `id`='%d' LIMIT 1", item.id); - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; } @@ -942,7 +924,7 @@ int inventory_to_sql(const struct item items[], int max, int id) { } } if( !found ) {// Item not present in inventory, remove it. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", inventory_db, item.id) ) { + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE from `%s` where `id`='%d' LIMIT 1", inventory_db, item.id) ) { Sql_ShowDebug(sql_handle); errors++; } @@ -950,11 +932,11 @@ int inventory_to_sql(const struct item items[], int max, int id) { } SqlStmt_Free(stmt); - StringBuf_Clear(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `unique_id`", inventory_db); + StrBuf->Clear(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s` (`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `unique_id`", inventory_db); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_AppendStr(&buf, ") VALUES "); + StrBuf->Printf(&buf, ", `card%d`", j); + StrBuf->AppendStr(&buf, ") VALUES "); found = false; // insert non-matched items into the db as new items @@ -964,26 +946,26 @@ int inventory_to_sql(const struct item items[], int max, int id) { continue; if( found ) - StringBuf_AppendStr(&buf, ","); + StrBuf->AppendStr(&buf, ","); else found = true; - StringBuf_Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'", + StrBuf->Printf(&buf, "('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u', '%d', '%"PRIu64"'", id, items[i].nameid, items[i].amount, items[i].equip, items[i].identify, items[i].refine, items[i].attribute, items[i].expire_time, items[i].favorite, items[i].unique_id); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", '%d'", items[i].card[j]); - StringBuf_AppendStr(&buf, ")"); + StrBuf->Printf(&buf, ", '%d'", items[i].card[j]); + StrBuf->AppendStr(&buf, ")"); updateLastUid(items[i].unique_id);// Unique Non Stackable Item ID } dbUpdateUid(sql_handle); - if( found && SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { + if( found && SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); errors++; } - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); aFree(flag); return errors; @@ -1002,20 +984,22 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) char last_map[MAP_NAME_LENGTH_EXT]; stmt = SqlStmt_Malloc(sql_handle); - if( stmt == NULL ) - { + if( stmt == NULL ) { SqlStmt_ShowDebug(stmt); return 0; } memset(&p, 0, sizeof(p)); + for(i = 0 ; i < MAX_CHARS; i++ ) + sd->found_char[i] = -1; + // read char data if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT " "`char_id`,`char_num`,`name`,`class`,`base_level`,`job_level`,`base_exp`,`job_exp`,`zeny`," "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`hair`,`hair_color`," "`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`rename`,`delete_date`," - "`robe`" + "`robe`,`slotchange`" " FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL) @@ -1051,24 +1035,23 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf) || SQL_ERROR == SqlStmt_BindColumn(stmt, 30, SQLDT_SHORT, &p.head_mid, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 31, SQLDT_SHORT, &p.head_bottom, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 32, SQLDT_STRING, &last_map, sizeof(last_map), NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_SHORT, &p.rename, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 33, SQLDT_USHORT, &p.rename, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 34, SQLDT_UINT32, &p.delete_date, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 36, SQLDT_USHORT, &p.slotchange, 0, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); return 0; } - for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ ) - { + + for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SqlStmt_NextRow(stmt); i++ ) { p.last_point.map = mapindex_name2id(last_map); - sd->found_char[i] = p.char_id; + sd->found_char[p.slot] = p.char_id; j += mmo_char_tobuf(WBUFP(buf, j), &p); } - for( ; i < MAX_CHARS; i++ ) - sd->found_char[i] = -1; - + memset(sd->new_name,0,sizeof(sd->new_name)); SqlStmt_Free(stmt); @@ -1094,6 +1077,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything struct hotkey tmp_hotkey; int hotkey_num; #endif + unsigned int opt; memset(p, 0, sizeof(struct mmo_charstatus)); @@ -1112,7 +1096,8 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything "`str`,`agi`,`vit`,`int`,`dex`,`luk`,`max_hp`,`hp`,`max_sp`,`sp`," "`status_point`,`skill_point`,`option`,`karma`,`manner`,`party_id`,`guild_id`,`pet_id`,`homun_id`,`elemental_id`,`hair`," "`hair_color`,`clothes_color`,`weapon`,`shield`,`head_top`,`head_mid`,`head_bottom`,`last_map`,`last_x`,`last_y`," - "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`" + "`save_map`,`save_x`,`save_y`,`partner_id`,`father`,`mother`,`child`,`fame`,`rename`,`delete_date`,`robe`,`slotchange`," + "`char_opt`" " FROM `%s` WHERE `char_id`=? LIMIT 1", char_db) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) @@ -1165,9 +1150,11 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything || SQL_ERROR == SqlStmt_BindColumn(stmt, 46, SQLDT_INT, &p->mother, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 47, SQLDT_INT, &p->child, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 48, SQLDT_INT, &p->fame, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_SHORT, &p->rename, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 49, SQLDT_USHORT, &p->rename, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 50, SQLDT_UINT32, &p->delete_date, 0, NULL, NULL) || SQL_ERROR == SqlStmt_BindColumn(stmt, 51, SQLDT_SHORT, &p->robe, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 52, SQLDT_USHORT, &p->slotchange, 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 53, SQLDT_UINT, &opt, 0, NULL, NULL) ) { SqlStmt_ShowDebug(stmt); @@ -1183,6 +1170,18 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything p->last_point.map = mapindex_name2id(last_map); p->save_point.map = mapindex_name2id(save_map); + if( p->last_point.map == 0 ) { + p->last_point.map = strdb_iget(mapindex_db, MAP_DEFAULT); + p->last_point.x = MAP_DEFAULT_X; + p->last_point.y = MAP_DEFAULT_Y; + } + + if( p->save_point.map == 0 ) { + p->save_point.map = strdb_iget(mapindex_db, MAP_DEFAULT); + p->save_point.x = MAP_DEFAULT_X; + p->save_point.y = MAP_DEFAULT_Y; + } + strcat(t_msg, " status"); if (!load_everything) // For quick selection of data when displaying the char menu @@ -1201,8 +1200,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_SHORT, &tmp_point.y, 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); - for( i = 0; i < MAX_MEMOPOINTS && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - { + for( i = 0; i < MAX_MEMOPOINTS && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) { tmp_point.map = mapindex_name2id(point_map); memcpy(&p->memo_point[i], &tmp_point, sizeof(tmp_point)); } @@ -1210,13 +1208,13 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read inventory //`inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, `expire_time`, `favorite`, `unique_id`) - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `unique_id`"); + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `favorite`, `unique_id`"); for( i = 0; i < MAX_SLOTS; ++i ) - StringBuf_Printf(&buf, ", `card%d`", i); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY); + StrBuf->Printf(&buf, ", `card%d`", i); + StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY); - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StrBuf->Value(&buf)) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) @@ -1241,13 +1239,13 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read cart //`cart_inventory` (`id`,`char_id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `card0`, `card1`, `card2`, `card3`, expire_time`, `unique_id`) - StringBuf_Clear(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `unique_id`"); + StrBuf->Clear(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`, `nameid`, `amount`, `equip`, `identify`, `refine`, `attribute`, `expire_time`, `unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART); + StrBuf->Printf(&buf, ", `card%d`", j); + StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", cart_db, MAX_CART); - if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + if( SQL_ERROR == SqlStmt_PrepareStr(stmt, StrBuf->Value(&buf)) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_INT, &tmp_item.id, 0, NULL, NULL) @@ -1274,18 +1272,20 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything //read skill //`skill` (`char_id`, `id`, `lv`) - if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL) + if( SQL_ERROR == SqlStmt_Prepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL) || SQL_ERROR == SqlStmt_BindParam(stmt, 0, SQLDT_INT, &char_id, 0) || SQL_ERROR == SqlStmt_Execute(stmt) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id, 0, NULL, NULL) - || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_USHORT, &tmp_skill.lv, 0, NULL, NULL) ) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 0, SQLDT_USHORT, &tmp_skill.id , 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 1, SQLDT_UCHAR , &tmp_skill.lv , 0, NULL, NULL) + || SQL_ERROR == SqlStmt_BindColumn(stmt, 2, SQLDT_UCHAR , &tmp_skill.flag, 0, NULL, NULL) ) SqlStmt_ShowDebug(stmt); - tmp_skill.flag = SKILL_FLAG_PERMANENT; + + if( tmp_skill.flag != SKILL_FLAG_PERM_GRANTED ) + tmp_skill.flag = SKILL_FLAG_PERMANENT; - for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) - { - if( tmp_skill.id < ARRAYLENGTH(p->skill) ) - memcpy(&p->skill[tmp_skill.id], &tmp_skill, sizeof(tmp_skill)); + for( i = 0; i < MAX_SKILL && SQL_SUCCESS == SqlStmt_NextRow(stmt); ++i ) { + if( skillid2idx[tmp_skill.id] ) + memcpy(&p->skill[skillid2idx[tmp_skill.id]], &tmp_skill, sizeof(tmp_skill)); else ShowWarning("mmo_char_fromsql: ignoring invalid skill (id=%u,lv=%u) of character %s (AID=%d,CID=%d)\n", tmp_skill.id, tmp_skill.lv, p->name, p->account_id, p->char_id); } @@ -1334,8 +1334,14 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything if (save_log) ShowInfo("Loaded char (%d - %s): %s\n", char_id, p->name, t_msg); //ok. all data load successfuly! SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); - + StrBuf->Destroy(&buf); + + /* load options into proper vars */ + if( opt & OPT_ALLOW_PARTY ) + p->allow_party = true; + if( opt & OPT_SHOW_EQUIP ) + p->show_equip = true; + cp = idb_ensure(char_db_, char_id, create_charstatus); memcpy(cp, p, sizeof(struct mmo_charstatus)); return 1; @@ -1346,8 +1352,6 @@ int mmo_char_sql_init(void) { char_db_= idb_alloc(DB_OPT_RELEASE_DATA); - ShowStatus("Characters per Account: '%d'.\n", char_per_account); - //the 'set offline' part is now in check_login_conn ... //if the server connects to loginserver //it will dc all off players @@ -1359,6 +1363,54 @@ int mmo_char_sql_init(void) return 0; } +/* [Ind/Hercules] - special thanks to Yommy for providing the packet structure/data */ +bool char_slotchange(struct char_session_data *sd, int fd, unsigned short from, unsigned short to) { + struct mmo_charstatus char_dat; + int from_id = 0; + + if( from > MAX_CHARS || to > MAX_CHARS || ( sd->char_slots && to > sd->char_slots ) || sd->found_char[from] <= 0 ) + return false; + + if( !mmo_char_fromsql(sd->found_char[from], &char_dat, false) ) // Only the short data is needed. + return false; + + if( char_dat.slotchange == 0 ) + return false; + + from_id = sd->found_char[from]; + + if( sd->found_char[to] > 0 ) {/* moving char to occupied slot */ + bool result = false; + /* update both at once */ + if( SQL_SUCCESS != SQL->QueryStr(sql_handle, "START TRANSACTION") + || SQL_SUCCESS != SQL->Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d' LIMIT 1", char_db, from, sd->found_char[to]) + || SQL_SUCCESS != SQL->Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d' LIMIT 1", char_db, to, sd->found_char[from]) ) + Sql_ShowDebug(sql_handle); + else + result = true; + + if( SQL_ERROR == SQL->QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") ) { + Sql_ShowDebug(sql_handle); + result = false; + } + if( !result ) + return false; + + } else {/* slot is free. */ + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `char_num`='%d' WHERE `char_id`='%d' LIMIT 1", char_db, to, sd->found_char[from] ) ) { + Sql_ShowDebug(sql_handle); + return false; + } + } + + /* update count */ + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `slotchange`=`slotchange`-1 WHERE `char_id`='%d' LIMIT 1", char_db, from_id ) ) { + Sql_ShowDebug(sql_handle); + return false; + } + + return true; +} //----------------------------------- // Function to change chararcter's names @@ -1377,16 +1429,16 @@ int rename_char_sql(struct char_session_data *sd, int char_id) if( char_dat.rename == 0 ) return 1; - Sql_EscapeStringLen(sql_handle, esc_name, sd->new_name, strnlen(sd->new_name, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_name, sd->new_name, strnlen(sd->new_name, NAME_LENGTH)); // check if the char exist - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", char_db, esc_name) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` LIKE '%s' LIMIT 1", char_db, esc_name) ) { Sql_ShowDebug(sql_handle); return 4; } - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", char_db, esc_name, --char_dat.rename, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `name` = '%s', `rename` = '%d' WHERE `char_id` = '%d'", char_db, esc_name, --char_dat.rename, char_id) ) { Sql_ShowDebug(sql_handle); return 3; @@ -1402,7 +1454,7 @@ int rename_char_sql(struct char_session_data *sd, int char_id) // log change if( log_char ) { - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '0', '0', '0', '0', '0', '0', '0', '0')", charlog_db, "change char name", sd->account_id, char_dat.slot, esc_name) ) Sql_ShowDebug(sql_handle); @@ -1429,7 +1481,7 @@ int check_char_name(char * name, char * esc_name) return -2; // control chars in name // check for reserved names - if( strcmpi(name, main_chat_nick) == 0 || strcmpi(name, wisp_server_name) == 0 ) + if( strcmpi(name, wisp_server_name) == 0 ) return -1; // nick reserved for internal server messages // Check Authorised letters/symbols in the name of the character @@ -1446,17 +1498,17 @@ int check_char_name(char * name, char * esc_name) return -2; } if( name_ignoring_case ) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name) ) { + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT 1 FROM `%s` WHERE BINARY `name` = '%s' LIMIT 1", char_db, esc_name) ) { Sql_ShowDebug(sql_handle); return -2; } } else { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name) ) { + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT 1 FROM `%s` WHERE `name` = '%s' LIMIT 1", char_db, esc_name) ) { Sql_ShowDebug(sql_handle); return -2; } } - if( Sql_NumRows(sql_handle) > 0 ) + if( SQL->NumRows(sql_handle) > 0 ) return -1; // name already exists return 0; @@ -1474,52 +1526,45 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag char name[NAME_LENGTH]; char esc_name[NAME_LENGTH*2+1]; - int char_id, flag; + int char_id, flag, k; safestrncpy(name, name_, NAME_LENGTH); normalize_name(name,TRIM_CHARS); - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); flag = check_char_name(name,esc_name); if( flag < 0 ) return flag; - + //check other inputs #if PACKETVER >= 20120307 - if(slot >= MAX_CHARS) + if(slot < 0 || slot >= sd->char_slots) #else - if((slot >= MAX_CHARS) // slots + if((slot < 0 || slot >= sd->char_slots) // slots || (str + agi + vit + int_ + dex + luk != 6*5 ) // stats || (str < 1 || str > 9 || agi < 1 || agi > 9 || vit < 1 || vit > 9 || int_ < 1 || int_ > 9 || dex < 1 || dex > 9 || luk < 1 || luk > 9) // individual stat values || (str + int_ != 10 || agi + luk != 10 || vit + dex != 10) ) // pairs #endif +#if PACKETVER >= 20100413 + return -4; // invalid slot +#else return -2; // invalid input - - - // check the number of already existing chars in this account - if( char_per_account != 0 ) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d'", char_db, sd->account_id) ) - Sql_ShowDebug(sql_handle); - if( Sql_NumRows(sql_handle) >= char_per_account ) - return -2; // character account limit exceeded - } +#endif // check char slot - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT 1 FROM `%s` WHERE `account_id` = '%d' AND `char_num` = '%d' LIMIT 1", char_db, sd->account_id, slot) ) - Sql_ShowDebug(sql_handle); - if( Sql_NumRows(sql_handle) > 0 ) - return -2; // slot already in use + if( sd->found_char[slot] != -1 ) + return -2; /* character account limit exceeded */ // validation success, log result if (log_char) { - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` (`time`, `char_msg`,`account_id`,`char_num`,`name`,`str`,`agi`,`vit`,`int`,`dex`,`luk`,`hair`,`hair_color`)" "VALUES (NOW(), '%s', '%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", charlog_db, "make new char", sd->account_id, slot, esc_name, str, agi, vit, int_, dex, luk, hair_style, hair_color) ) Sql_ShowDebug(sql_handle); } #if PACKETVER >= 20120307 //Insert the new char entry to the database - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `status_point`,`str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `status_point`,`str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" "'%d', '%d', '%s', '%d', '%d','%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", char_db, sd->account_id , slot, esc_name, start_zeny, 48, str, agi, vit, int_, dex, luk, @@ -1531,7 +1576,7 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag } #else //Insert the new char entry to the database - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` (`account_id`, `char_num`, `name`, `zeny`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `max_hp`, `hp`," "`max_sp`, `sp`, `hair`, `hair_color`, `last_map`, `last_x`, `last_y`, `save_map`, `save_x`, `save_y`) VALUES (" "'%d', '%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d','%d', '%d','%d', '%d', '%s', '%d', '%d', '%s', '%d', '%d')", char_db, sd->account_id , slot, esc_name, start_zeny, str, agi, vit, int_, dex, luk, @@ -1543,15 +1588,12 @@ int make_new_char_sql(struct char_session_data* sd, char* name_, int str, int ag } #endif //Retrieve the newly auto-generated char id - char_id = (int)Sql_LastInsertId(sql_handle); + char_id = (int)SQL->LastInsertId(sql_handle); //Give the char the default items - if (start_weapon > 0) { //add Start Weapon (Knife?) - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `identify`) VALUES ('%d', '%d', '%d', '%d')", inventory_db, char_id, start_weapon, 1, 1) ) - Sql_ShowDebug(sql_handle); - } - if (start_armor > 0) { //Add default armor (cotton shirt?) - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `identify`) VALUES ('%d', '%d', '%d', '%d')", inventory_db, char_id, start_armor, 1, 1) ) - Sql_ShowDebug(sql_handle); + + for (k = 0; k < ARRAYLENGTH(start_items) && start_items[k] != 0; k += 2) { + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` (`char_id`,`nameid`, `amount`, `identify`) VALUES ('%d', '%d', '%d', '%d')", inventory_db, char_id, start_items[k], start_items[k + 1], 1) ) + Sql_ShowDebug(sql_handle); } ShowInfo("Created char: account: %d, char: %d, slot: %d, name: %s\n", sd->account_id, char_id, slot, name); @@ -1565,9 +1607,9 @@ int divorce_char_sql(int partner_id1, int partner_id2) { unsigned char buf[64]; - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", char_db, partner_id1, partner_id2) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `partner_id`='0' WHERE `char_id`='%d' OR `char_id`='%d' LIMIT 2", char_db, partner_id1, partner_id2) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE (`nameid`='%d' OR `nameid`='%d') AND (`char_id`='%d' OR `char_id`='%d') LIMIT 2", inventory_db, WEDDING_RING_M, WEDDING_RING_F, partner_id1, partner_id2) ) Sql_ShowDebug(sql_handle); WBUFW(buf,0) = 0x2b12; @@ -1592,30 +1634,30 @@ int delete_char_sql(int char_id) char *data; size_t len; - if (SQL_ERROR == Sql_Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", char_db, char_id)) + if (SQL_ERROR == SQL->Query(sql_handle, "SELECT `name`,`account_id`,`party_id`,`guild_id`,`base_level`,`homun_id`,`partner_id`,`father`,`mother`,`elemental_id` FROM `%s` WHERE `char_id`='%d'", char_db, char_id)) Sql_ShowDebug(sql_handle); - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { ShowError("delete_char_sql: Unable to fetch character data, deletion aborted.\n"); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return -1; } - Sql_GetData(sql_handle, 0, &data, &len); safestrncpy(name, data, NAME_LENGTH); - Sql_GetData(sql_handle, 1, &data, NULL); account_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); party_id = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); guild_id = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); hom_id = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); partner_id = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); father_id = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); mother_id = atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); + SQL->GetData(sql_handle, 0, &data, &len); safestrncpy(name, data, NAME_LENGTH); + SQL->GetData(sql_handle, 1, &data, NULL); account_id = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); party_id = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); guild_id = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); base_level = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); hom_id = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); partner_id = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); father_id = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); mother_id = atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); elemental_id = atoi(data); - Sql_EscapeStringLen(sql_handle, esc_name, name, min(len, NAME_LENGTH)); - Sql_FreeResult(sql_handle); + SQL->EscapeStringLen(sql_handle, esc_name, name, min(len, NAME_LENGTH)); + SQL->FreeResult(sql_handle); //check for config char del condition [Lupus] // TODO: Move this out to packet processing (0x68/0x1fb). @@ -1635,9 +1677,9 @@ int delete_char_sql(int char_id) { // Char is Baby unsigned char buf[64]; - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", char_db, father_id, mother_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `child`='0' WHERE `char_id`='%d' OR `char_id`='%d'", char_db, father_id, mother_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", skill_db, father_id, mother_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '410'AND (`char_id`='%d' OR `char_id`='%d')", skill_db, father_id, mother_id) ) Sql_ShowDebug(sql_handle); WBUFW(buf,0) = 0x2b25; @@ -1653,13 +1695,13 @@ int delete_char_sql(int char_id) /* delete char's pet */ //Delete the hatched pet if you have one... - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", pet_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `incuvate` = '0'", pet_db, char_id) ) Sql_ShowDebug(sql_handle); //Delete all pets that are stored in eggs (inventory + cart) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, inventory_db, inventory_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, inventory_db, inventory_db, char_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, cart_db, cart_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` USING `%s` JOIN `%s` ON `pet_id` = `card1`|`card2`<<16 WHERE `%s`.char_id = '%d' AND card0 = -256", pet_db, pet_db, cart_db, cart_db, char_id) ) Sql_ShowDebug(sql_handle); /* remove homunculus */ @@ -1674,69 +1716,69 @@ int delete_char_sql(int char_id) mercenary_owner_delete(char_id); /* delete char's friends list */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", friend_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", friend_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete char from other's friend list */ //NOTE: Won't this cause problems for people who are already online? [Skotlex] - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", friend_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `friend_id` = '%d'", friend_db, char_id) ) Sql_ShowDebug(sql_handle); #ifdef HOTKEY_SAVING /* delete hotkeys */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", hotkey_db, char_id) ) Sql_ShowDebug(sql_handle); #endif /* delete inventory */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", inventory_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete cart inventory */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", cart_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", cart_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete memo areas */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", memo_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete character registry */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete skills */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", skill_db, char_id) ) Sql_ShowDebug(sql_handle); /* delete mails (only received) */ - if (SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", mail_db, char_id)) + if (SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `dest_id`='%d'", mail_db, char_id)) Sql_ShowDebug(sql_handle); #ifdef ENABLE_SC_SAVING /* status changes */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, account_id, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, account_id, char_id) ) Sql_ShowDebug(sql_handle); #endif if (log_char) { - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')", + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`char_msg`,`name`) VALUES (NOW(), '%d', '%d', 'Deleted char (CID %d)', '%s')", charlog_db, account_id, 0, char_id, esc_name) ) Sql_ShowDebug(sql_handle); } /* delete character */ - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) Sql_ShowDebug(sql_handle); /* No need as we used inter_guild_leave [Skotlex] // Also delete info from guildtables. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", guild_member_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d'", guild_member_db, char_id) ) Sql_ShowDebug(sql_handle); */ - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", guild_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `char_id` = '%d'", guild_db, char_id) ) Sql_ShowDebug(sql_handle); - else if( Sql_NumRows(sql_handle) > 0 ) + else if( SQL->NumRows(sql_handle) > 0 ) mapif_parse_BreakGuild(0,guild_id); else if( guild_id ) inter_guild_leave(guild_id, account_id, char_id);// Leave your guild. @@ -1779,7 +1821,7 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) WBUFL(buf,16) = p->job_level; WBUFL(buf,20) = 0; // probably opt1 WBUFL(buf,24) = 0; // probably opt2 - WBUFL(buf,28) = p->option; + WBUFL(buf,28) = (p->option &~ 0x40); WBUFL(buf,32) = p->karma; WBUFL(buf,36) = p->manner; WBUFW(buf,40) = min(p->status_point, INT16_MAX); @@ -1828,7 +1870,7 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) #endif #if PACKETVER != 20111116 //2011-11-16 wants 136, ask gravity. #if PACKETVER >= 20110928 - WBUFL(buf,132) = 0; // change slot feature (0 = disabled, otherwise enabled) + WBUFL(buf,132) = ( p->slotchange > 0 ) ? 1 : 0; // change slot feature (0 = disabled, otherwise enabled) offset += 4; #endif #if PACKETVER >= 20111025 @@ -1839,7 +1881,32 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) return 106+offset; } - +/* Made Possible by Yommy~! <3 */ +void mmo_char_send099d(int fd, struct char_session_data *sd) { + WFIFOHEAD(fd,4 + (MAX_CHARS*MAX_CHAR_BUF)); + WFIFOW(fd,0) = 0x99d; + WFIFOW(fd,2) = mmo_chars_fromsql(sd, WFIFOP(fd,4)) + 4; + WFIFOSET(fd,WFIFOW(fd,2)); +} +int mmo_char_send006b(int fd, struct char_session_data* sd); +//---------------------------------------- +// [Ind/Hercules] notify client about charselect window data +//---------------------------------------- +void mmo_char_send082d(int fd, struct char_session_data* sd) { + + WFIFOHEAD(fd,29); + WFIFOW(fd,0) = 0x82d; + WFIFOW(fd,2) = 29; + WFIFOB(fd,4) = sd->char_slots; + WFIFOB(fd,5) = MAX_CHARS - sd->char_slots; + WFIFOB(fd,6) = MAX_CHARS - sd->char_slots; + WFIFOB(fd,7) = sd->char_slots; + WFIFOB(fd,8) = sd->char_slots; + memset(WFIFOP(fd,9), 0, 20); // unused bytes + WFIFOSET(fd,29); + mmo_char_send006b(fd,sd); + +} //---------------------------------------- // Function to send characters to a player //---------------------------------------- @@ -1848,18 +1915,17 @@ int mmo_char_send006b(int fd, struct char_session_data* sd) int j, offset = 0; #if PACKETVER >= 20100413 offset += 3; -#endif - +#endif if (save_log) ShowInfo("Loading Char Data ("CL_BOLD"%d"CL_RESET")\n",sd->account_id); - + j = 24 + offset; // offset WFIFOHEAD(fd,j + MAX_CHARS*MAX_CHAR_BUF); WFIFOW(fd,0) = 0x6b; #if PACKETVER >= 20100413 WFIFOB(fd,4) = MAX_CHARS; // Max slots. - WFIFOB(fd,5) = MAX_CHARS; // Available slots. - WFIFOB(fd,6) = MAX_CHARS; // Premium slots. + WFIFOB(fd,5) = sd->char_slots; // Available slots. (aka PremiumStartSlot) + WFIFOB(fd,6) = MAX_CHARS; // Premium slots. AKA any existent chars past sd->char_slots but within MAX_CHARS will show a 'Premium Service' in red #endif memset(WFIFOP(fd,4 + offset), 0, 20); // unknown bytes j+=mmo_chars_fromsql(sd, WFIFOP(fd,j)); @@ -1871,66 +1937,66 @@ int mmo_char_send006b(int fd, struct char_session_data* sd) int char_married(int pl1, int pl2) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `partner_id` FROM `%s` WHERE `char_id` = '%d'", char_db, pl1) ) Sql_ShowDebug(sql_handle); - else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + else if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); if( pl2 == atoi(data) ) { - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return 1; } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return 0; } int char_child(int parent_id, int child_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `child` FROM `%s` WHERE `char_id` = '%d'", char_db, parent_id) ) Sql_ShowDebug(sql_handle); - else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + else if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); if( child_id == atoi(data) ) { - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return 1; } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return 0; } int char_family(int cid1, int cid2, int cid3) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, cid1, cid2, cid3) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`,`partner_id`,`child` FROM `%s` WHERE `char_id` IN ('%d','%d','%d')", char_db, cid1, cid2, cid3) ) Sql_ShowDebug(sql_handle); - else while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + else while( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { int charid; int partnerid; int childid; char* data; - Sql_GetData(sql_handle, 0, &data, NULL); charid = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); partnerid = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); childid = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); charid = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); partnerid = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); childid = atoi(data); if( (cid1 == charid && ((cid2 == partnerid && cid3 == childid ) || (cid2 == childid && cid3 == partnerid))) || (cid1 == partnerid && ((cid2 == charid && cid3 == childid ) || (cid2 == childid && cid3 == charid ))) || (cid1 == childid && ((cid2 == charid && cid3 == partnerid) || (cid2 == partnerid && cid3 == charid ))) ) { - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return childid; } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return 0; } @@ -2077,299 +2143,302 @@ int parse_fromlogin(int fd) { while(RFIFOREST(fd) >= 2) { uint16 command = RFIFOW(fd,0); + switch( command ) { + + // acknowledgement of connect-to-loginserver request + case 0x2711: + if (RFIFOREST(fd) < 3) + return 0; + + if (RFIFOB(fd,2)) { + //printf("connect login server error : %d\n", RFIFOB(fd,2)); + ShowError("Can not connect to login-server.\n"); + ShowError("The server communication passwords (default s1/p1) are probably invalid.\n"); + ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n"); + ShowError("The communication passwords are set in /conf/map-server.conf and /conf/char-server.conf\n"); + set_eof(fd); + return 0; + } else { + ShowStatus("Connected to login-server (connection #%d).\n", fd); + loginif_on_ready(); + } + RFIFOSKIP(fd,3); + break; - switch( command ) - { - - // acknowledgement of connect-to-loginserver request - case 0x2711: - if (RFIFOREST(fd) < 3) - return 0; - - if (RFIFOB(fd,2)) { - //printf("connect login server error : %d\n", RFIFOB(fd,2)); - ShowError("Can not connect to login-server.\n"); - ShowError("The server communication passwords (default s1/p1) are probably invalid.\n"); - ShowError("Also, please make sure your login db has the correct communication username/passwords and the gender of the account is S.\n"); - ShowError("The communication passwords are set in /conf/map-server.conf and /conf/char-server.conf\n"); - set_eof(fd); - return 0; - } else { - ShowStatus("Connected to login-server (connection #%d).\n", fd); - loginif_on_ready(); - } - RFIFOSKIP(fd,3); - break; - - // acknowledgement of account authentication request - case 0x2713: - if (RFIFOREST(fd) < 25) - return 0; - { - int account_id = RFIFOL(fd,2); - uint32 login_id1 = RFIFOL(fd,6); - uint32 login_id2 = RFIFOL(fd,10); - uint8 sex = RFIFOB(fd,14); - uint8 result = RFIFOB(fd,15); - int request_id = RFIFOL(fd,16); - uint32 version = RFIFOL(fd,20); - uint8 clienttype = RFIFOB(fd,24); - RFIFOSKIP(fd,25); - - if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) && - !sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex ) + // acknowledgement of account authentication request + case 0x2713: + if (RFIFOREST(fd) < 25) + return 0; { - int client_fd = request_id; - sd->version = version; - sd->clienttype = clienttype; - switch( result ) + int account_id = RFIFOL(fd,2); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); + uint8 sex = RFIFOB(fd,14); + uint8 result = RFIFOB(fd,15); + int request_id = RFIFOL(fd,16); + uint32 version = RFIFOL(fd,20); + uint8 clienttype = RFIFOB(fd,24); + RFIFOSKIP(fd,25); + + if( session_isActive(request_id) && (sd=(struct char_session_data*)session[request_id]->session_data) && + !sd->auth && sd->account_id == account_id && sd->login_id1 == login_id1 && sd->login_id2 == login_id2 && sd->sex == sex ) { - case 0:// ok - char_auth_ok(client_fd, sd); - break; - case 1:// auth failed - WFIFOHEAD(client_fd,3); - WFIFOW(client_fd,0) = 0x6c; - WFIFOB(client_fd,2) = 0;// rejected from server - WFIFOSET(client_fd,3); - break; + int client_fd = request_id; + sd->version = version; + sd->clienttype = clienttype; + switch( result ) + { + case 0:// ok + char_auth_ok(client_fd, sd); + break; + case 1:// auth failed + WFIFOHEAD(client_fd,3); + WFIFOW(client_fd,0) = 0x6c; + WFIFOB(client_fd,2) = 0;// rejected from server + WFIFOSET(client_fd,3); + break; + } } } - } - break; - - case 0x2717: // account data - if (RFIFOREST(fd) < 62) - return 0; + break; - // find the authenticated session with this account id - ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) ); - if( i < fd_max ) - { - int server_id; - memcpy(sd->email, RFIFOP(fd,6), 40); - sd->expiration_time = (time_t)RFIFOL(fd,46); - sd->group_id = RFIFOB(fd,50); - safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,51), sizeof(sd->birthdate)); - ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] ); - // continued from char_auth_ok... - if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359 - ( max_connect_user && count_users() >= max_connect_user && sd->group_id != gm_allow_group ) ) { - // refuse connection (over populated) - WFIFOHEAD(i,3); - WFIFOW(i,0) = 0x6c; - WFIFOW(i,2) = 0; - WFIFOSET(i,3); - } else { - // send characters to player - mmo_char_send006b(i, sd); -#if PACKETVER >= 20110309 - // PIN code system, disabled - WFIFOHEAD(i, 12); - WFIFOW(i, 0) = 0x08B9; - WFIFOW(i, 2) = 0; - WFIFOW(i, 4) = 0; - WFIFOL(i, 6) = sd->account_id; - WFIFOW(i, 10) = 0; - WFIFOSET(i, 12); -#endif + case 0x2717: // account data + if (RFIFOREST(fd) < 72) + return 0; + + // find the authenticated session with this account id + ARR_FIND( 0, fd_max, i, session[i] && (sd = (struct char_session_data*)session[i]->session_data) && sd->auth && sd->account_id == RFIFOL(fd,2) ); + if( i < fd_max ) { + int server_id; + memcpy(sd->email, RFIFOP(fd,6), 40); + sd->expiration_time = (time_t)RFIFOL(fd,46); + sd->group_id = RFIFOB(fd,50); + sd->char_slots = RFIFOB(fd,51); + if( sd->char_slots > MAX_CHARS ) { + ShowError("Account '%d' `character_slots` column is higher than supported MAX_CHARS (%d), update MAX_CHARS in mmo.h! capping to MAX_CHARS...\n",sd->account_id,sd->char_slots); + sd->char_slots = MAX_CHARS;/* cap to maximum */ + } else if ( sd->char_slots <= 0 )/* no value aka 0 in sql */ + sd->char_slots = MAX_CHARS;/* cap to maximum */ + safestrncpy(sd->birthdate, (const char*)RFIFOP(fd,52), sizeof(sd->birthdate)); + safestrncpy(sd->pincode, (const char*)RFIFOP(fd,63), sizeof(sd->pincode)); + sd->pincode_change = RFIFOL(fd,68); + ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] ); + // continued from char_auth_ok... + if( server_id == ARRAYLENGTH(server) || //server not online, bugreport:2359 + (max_connect_user == 0 && sd->group_id != gm_allow_group) || + ( max_connect_user > 0 && count_users() >= max_connect_user && sd->group_id != gm_allow_group ) ) { + // refuse connection (over populated) + WFIFOHEAD(i,3); + WFIFOW(i,0) = 0x6c; + WFIFOW(i,2) = 0; + WFIFOSET(i,3); + } else { + // send characters to player + #if PACKETVER >= 20130000 + mmo_char_send082d(i, sd); + #else + mmo_char_send006b(i, sd); + #endif + #if PACKETVER >= 20110309 + pincode->handle(i, sd); + #endif + } } - } - RFIFOSKIP(fd,62); - break; - - // login-server alive packet - case 0x2718: - if (RFIFOREST(fd) < 2) - return 0; - RFIFOSKIP(fd,2); - session[fd]->flag.ping = 0; - break; - - // changesex reply - case 0x2723: - if (RFIFOREST(fd) < 7) - return 0; - { - unsigned char buf[7]; - - int acc = RFIFOL(fd,2); - int sex = RFIFOB(fd,6); - RFIFOSKIP(fd,7); - - if( acc > 0 ) - {// TODO: Is this even possible? - int char_id[MAX_CHARS]; - int class_[MAX_CHARS]; - int guild_id[MAX_CHARS]; - int num; - char* data; + RFIFOSKIP(fd,72); + break; - struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc); - if( node != NULL ) - node->sex = sex; + // login-server alive packet + case 0x2718: + if (RFIFOREST(fd) < 2) + return 0; + RFIFOSKIP(fd,2); + session[fd]->flag.ping = 0; + break; - // get characters - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) ) - Sql_ShowDebug(sql_handle); - for( i = 0; i < MAX_CHARS && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) - { - Sql_GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data); - } - num = i; - for( i = 0; i < num; ++i ) - { - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || - class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || - class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER || - class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER || - class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T || - class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER || - class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) + // changesex reply + case 0x2723: + if (RFIFOREST(fd) < 7) + return 0; + { + unsigned char buf[7]; + + int acc = RFIFOL(fd,2); + int sex = RFIFOB(fd,6); + RFIFOSKIP(fd,7); + + if( acc > 0 ) + {// TODO: Is this even possible? + int char_id[MAX_CHARS]; + int class_[MAX_CHARS]; + int guild_id[MAX_CHARS]; + int num; + char* data; + + struct auth_node* node = (struct auth_node*)idb_get(auth_db, acc); + if( node != NULL ) + node->sex = sex; + + // get characters + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`,`class`,`guild_id` FROM `%s` WHERE `account_id` = '%d'", char_db, acc) ) + Sql_ShowDebug(sql_handle); + for( i = 0; i < MAX_CHARS && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { - // job modification - if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) - class_[i] = (sex ? JOB_BARD : JOB_DANCER); - else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) - class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); - else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) - class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); - else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ) - class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER); - else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ) - class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T); - else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ) - class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); - else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) - class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); + SQL->GetData(sql_handle, 0, &data, NULL); char_id[i] = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); class_[i] = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); guild_id[i] = atoi(data); } + num = i; + for( i = 0; i < num; ++i ) + { + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER || + class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY || + class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER || + class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER || + class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T || + class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER || + class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) + { + // job modification + if( class_[i] == JOB_BARD || class_[i] == JOB_DANCER ) + class_[i] = (sex ? JOB_BARD : JOB_DANCER); + else if( class_[i] == JOB_CLOWN || class_[i] == JOB_GYPSY ) + class_[i] = (sex ? JOB_CLOWN : JOB_GYPSY); + else if( class_[i] == JOB_BABY_BARD || class_[i] == JOB_BABY_DANCER ) + class_[i] = (sex ? JOB_BABY_BARD : JOB_BABY_DANCER); + else if( class_[i] == JOB_MINSTREL || class_[i] == JOB_WANDERER ) + class_[i] = (sex ? JOB_MINSTREL : JOB_WANDERER); + else if( class_[i] == JOB_MINSTREL_T || class_[i] == JOB_WANDERER_T ) + class_[i] = (sex ? JOB_MINSTREL_T : JOB_WANDERER_T); + else if( class_[i] == JOB_BABY_MINSTREL || class_[i] == JOB_BABY_WANDERER ) + class_[i] = (sex ? JOB_BABY_MINSTREL : JOB_BABY_WANDERER); + else if( class_[i] == JOB_KAGEROU || class_[i] == JOB_OBORO ) + class_[i] = (sex ? JOB_KAGEROU : JOB_OBORO); + } + + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) ) + Sql_ShowDebug(sql_handle); + + if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] + inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); + } + SQL->FreeResult(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d', `weapon`='0', `shield`='0', `head_top`='0', `head_mid`='0', `head_bottom`='0' WHERE `char_id`='%d'", char_db, class_[i], char_id[i]) ) - Sql_ShowDebug(sql_handle); - - if( guild_id[i] )// If there is a guild, update the guild_member data [Skotlex] - inter_guild_sex_changed(guild_id[i], acc, char_id[i], sex); + // disconnect player if online on char-server + disconnect_player(acc); } - Sql_FreeResult(sql_handle); - // disconnect player if online on char-server - disconnect_player(acc); + // notify all mapservers about this change + WBUFW(buf,0) = 0x2b0d; + WBUFL(buf,2) = acc; + WBUFB(buf,6) = sex; + mapif_sendall(buf, 7); } + break; - // notify all mapservers about this change - WBUFW(buf,0) = 0x2b0d; - WBUFL(buf,2) = acc; - WBUFB(buf,6) = sex; - mapif_sendall(buf, 7); - } - break; - - // reply to an account_reg2 registry request - case 0x2729: - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - - { //Receive account_reg2 registry, forward to map servers. - unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)]; - memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2)); - WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex] - mapif_sendall(buf, WBUFW(buf,2)); - RFIFOSKIP(fd, RFIFOW(fd,2)); - } - break; - - // State change of account/ban notification (from login-server) - case 0x2731: - if (RFIFOREST(fd) < 11) - return 0; + // reply to an account_reg2 registry request + case 0x2729: + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + + { //Receive account_reg2 registry, forward to map servers. + unsigned char buf[13+ACCOUNT_REG2_NUM*sizeof(struct global_reg)]; + memcpy(buf,RFIFOP(fd,0), RFIFOW(fd,2)); + WBUFW(buf,0) = 0x3804; //Map server can now receive all kinds of reg values with the same packet. [Skotlex] + mapif_sendall(buf, WBUFW(buf,2)); + RFIFOSKIP(fd, RFIFOW(fd,2)); + } + break; - { // send to all map-servers to disconnect the player - unsigned char buf[11]; - WBUFW(buf,0) = 0x2b14; - WBUFL(buf,2) = RFIFOL(fd,2); - WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban - WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment - mapif_sendall(buf, 11); - } - // disconnect player if online on char-server - disconnect_player(RFIFOL(fd,2)); + // State change of account/ban notification (from login-server) + case 0x2731: + if (RFIFOREST(fd) < 11) + return 0; + + { // send to all map-servers to disconnect the player + unsigned char buf[11]; + WBUFW(buf,0) = 0x2b14; + WBUFL(buf,2) = RFIFOL(fd,2); + WBUFB(buf,6) = RFIFOB(fd,6); // 0: change of statut, 1: ban + WBUFL(buf,7) = RFIFOL(fd,7); // status or final date of a banishment + mapif_sendall(buf, 11); + } + // disconnect player if online on char-server + disconnect_player(RFIFOL(fd,2)); - RFIFOSKIP(fd,11); - break; + RFIFOSKIP(fd,11); + break; - // Login server request to kick a character out. [Skotlex] - case 0x2734: - if (RFIFOREST(fd) < 6) - return 0; - { - int aid = RFIFOL(fd,2); - struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid); - RFIFOSKIP(fd,6); - if( character != NULL ) - {// account is already marked as online! - if( character->server > -1 ) - { //Kick it from the map server it is on. - mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); - if (character->waiting_disconnect == INVALID_TIMER) - character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0); - } - else - {// Manual kick from char server. - struct char_session_data *tsd; - int i; - ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid ); - if( i < fd_max ) - { - WFIFOHEAD(i,3); - WFIFOW(i,0) = 0x81; - WFIFOB(i,2) = 2; // "Someone has already logged in with this id" - WFIFOSET(i,3); - set_eof(i); + // Login server request to kick a character out. [Skotlex] + case 0x2734: + if (RFIFOREST(fd) < 6) + return 0; + { + int aid = RFIFOL(fd,2); + struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, aid); + RFIFOSKIP(fd,6); + if( character != NULL ) + {// account is already marked as online! + if( character->server > -1 ) + { //Kick it from the map server it is on. + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); + if (character->waiting_disconnect == INVALID_TIMER) + character->waiting_disconnect = add_timer(gettick()+AUTH_TIMEOUT, chardb_waiting_disconnect, character->account_id, 0); + } + else + {// Manual kick from char server. + struct char_session_data *tsd; + int i; + ARR_FIND( 0, fd_max, i, session[i] && (tsd = (struct char_session_data*)session[i]->session_data) && tsd->account_id == aid ); + if( i < fd_max ) + { + WFIFOHEAD(i,3); + WFIFOW(i,0) = 0x81; + WFIFOB(i,2) = 2; // "Someone has already logged in with this id" + WFIFOSET(i,3); + set_eof(i); + } + else // still moving to the map-server + set_char_offline(-1, aid); } - else // still moving to the map-server - set_char_offline(-1, aid); } + idb_remove(auth_db, aid);// reject auth attempts from map-server } - idb_remove(auth_db, aid);// reject auth attempts from map-server - } - break; + break; - // ip address update signal from login server - case 0x2735: - { - unsigned char buf[2]; - uint32 new_ip = 0; - - WBUFW(buf,0) = 0x2b1e; - mapif_sendall(buf, 2); - - new_ip = host2ip(login_ip_str); - if (new_ip && new_ip != login_ip) - login_ip = new_ip; //Update login ip, too. - - new_ip = host2ip(char_ip_str); - if (new_ip && new_ip != char_ip) - { //Update ip. - char_ip = new_ip; - ShowInfo("Updating IP for [%s].\n", char_ip_str); - // notify login server about the change - WFIFOHEAD(fd,6); - WFIFOW(fd,0) = 0x2736; - WFIFOL(fd,2) = htonl(char_ip); - WFIFOSET(fd,6); - } + // ip address update signal from login server + case 0x2735: + { + unsigned char buf[2]; + uint32 new_ip = 0; + + WBUFW(buf,0) = 0x2b1e; + mapif_sendall(buf, 2); + + new_ip = host2ip(login_ip_str); + if (new_ip && new_ip != login_ip) + login_ip = new_ip; //Update login ip, too. + + new_ip = host2ip(char_ip_str); + if (new_ip && new_ip != char_ip) + { //Update ip. + char_ip = new_ip; + ShowInfo("Updating IP for [%s].\n", char_ip_str); + // notify login server about the change + WFIFOHEAD(fd,6); + WFIFOW(fd,0) = 0x2736; + WFIFOL(fd,2) = htonl(char_ip); + WFIFOSET(fd,6); + } - RFIFOSKIP(fd,2); - } - break; + RFIFOSKIP(fd,2); + } + break; - default: - ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command); - set_eof(fd); - return 0; - } + default: + ShowError("Unknown packet 0x%04x received from login-server, disconnecting.\n", command); + set_eof(fd); + return 0; + } } RFIFOFLUSH(fd); @@ -2437,51 +2506,51 @@ void char_read_fame_list(void) memset(chemist_fame_list, 0, sizeof(chemist_fame_list)); memset(taekwon_fame_list, 0, sizeof(taekwon_fame_list)); // Build Blacksmith ranking list - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_BLACKSMITH, JOB_WHITESMITH, JOB_BABY_BLACKSMITH, JOB_MECHANIC, JOB_MECHANIC_T, JOB_BABY_MECHANIC, fame_list_size_smith) ) Sql_ShowDebug(sql_handle); - for( i = 0; i < fame_list_size_smith && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < fame_list_size_smith && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { // char_id - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); smith_fame_list[i].id = atoi(data); // fame - Sql_GetData(sql_handle, 1, &data, &len); + SQL->GetData(sql_handle, 1, &data, &len); smith_fame_list[i].fame = atoi(data); // name - Sql_GetData(sql_handle, 2, &data, &len); + SQL->GetData(sql_handle, 2, &data, &len); memcpy(smith_fame_list[i].name, data, min(len, NAME_LENGTH)); } // Build Alchemist ranking list - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d' OR `class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_ALCHEMIST, JOB_CREATOR, JOB_BABY_ALCHEMIST, JOB_GENETIC, JOB_GENETIC_T, JOB_BABY_GENETIC, fame_list_size_chemist) ) Sql_ShowDebug(sql_handle); - for( i = 0; i < fame_list_size_chemist && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < fame_list_size_chemist && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { // char_id - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); chemist_fame_list[i].id = atoi(data); // fame - Sql_GetData(sql_handle, 1, &data, &len); + SQL->GetData(sql_handle, 1, &data, &len); chemist_fame_list[i].fame = atoi(data); // name - Sql_GetData(sql_handle, 2, &data, &len); + SQL->GetData(sql_handle, 2, &data, &len); memcpy(chemist_fame_list[i].name, data, min(len, NAME_LENGTH)); } // Build Taekwon ranking list - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_TAEKWON, fame_list_size_taekwon) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`,`fame`,`name` FROM `%s` WHERE `fame`>0 AND (`class`='%d') ORDER BY `fame` DESC LIMIT 0,%d", char_db, JOB_TAEKWON, fame_list_size_taekwon) ) Sql_ShowDebug(sql_handle); - for( i = 0; i < fame_list_size_taekwon && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < fame_list_size_taekwon && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { // char_id - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); taekwon_fame_list[i].id = atoi(data); // fame - Sql_GetData(sql_handle, 1, &data, &len); + SQL->GetData(sql_handle, 1, &data, &len); taekwon_fame_list[i].fame = atoi(data); // name - Sql_GetData(sql_handle, 2, &data, &len); + SQL->GetData(sql_handle, 2, &data, &len); memcpy(taekwon_fame_list[i].name, data, min(len, NAME_LENGTH)); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } // Send map-servers the fame ranking lists @@ -2538,11 +2607,11 @@ int char_loadName(int char_id, char* name) char* data; size_t len; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `name` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) ) Sql_ShowDebug(sql_handle); - else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + else if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { - Sql_GetData(sql_handle, 0, &data, &len); + SQL->GetData(sql_handle, 0, &data, &len); safestrncpy(name, data, NAME_LENGTH); return 1; } @@ -2593,7 +2662,7 @@ void mapif_server_reset(int id) WBUFW(buf,2) = j * 4 + 10; mapif_sendallwos(fd, buf, WBUFW(buf,2)); } - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", ragsrvinfo_db, server[id].fd) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `index`='%d'", ragsrvinfo_db, server[id].fd) ) Sql_ShowDebug(sql_handle); online_char_db->foreach(online_char_db,char_db_setoffline,id); //Tag relevant chars as 'in disconnected' server. mapif_server_destroy(id); @@ -2615,732 +2684,754 @@ int parse_frommap(int fd) int id; ARR_FIND( 0, ARRAYLENGTH(server), id, server[id].fd == fd ); - if( id == ARRAYLENGTH(server) ) - {// not a map server + if( id == ARRAYLENGTH(server) ) {// not a map server ShowDebug("parse_frommap: Disconnecting invalid session #%d (is not a map-server)\n", fd); do_close(fd); return 0; } - if( session[fd]->flag.eof ) - { + if( session[fd]->flag.eof ) { do_close(fd); server[id].fd = -1; mapif_on_disconnect(id); return 0; } - while(RFIFOREST(fd) >= 2) - { - switch(RFIFOW(fd,0)) - { + while(RFIFOREST(fd) >= 2) { + switch(RFIFOW(fd,0)) { - case 0x2afa: // Receiving map names list from the map-server - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; + case 0x2b0a: + if( RFIFOREST(fd) < RFIFOW(fd, 2) ) + return 0; + socket_datasync(fd, false); + RFIFOSKIP(fd,RFIFOW(fd,2)); + break; - memset(server[id].map, 0, sizeof(server[id].map)); - j = 0; - for(i = 4; i < RFIFOW(fd,2); i += 4) { - server[id].map[j] = RFIFOW(fd,i); - j++; - } + case 0x2b0b: + if( RFIFOREST(fd) < RFIFOW(fd, 2) ) + return 0; + memset(&skillid2idx, 0, sizeof(skillid2idx)); + j = RFIFOW(fd, 2) - 4; + if( j ) + j /= 4; + for(i = 0; i < j; i++) { + if( RFIFOW(fd, 4 + (i*4)) > MAX_SKILL_ID ) { + ShowWarning("Error skillid2dx[%d] = %d failed, %d is higher than MAX_SKILL_ID (%d)\n",RFIFOW(fd, 4 + (i*4)), RFIFOW(fd, 6 + (i*4)),RFIFOW(fd, 4 + (i*4)),MAX_SKILL_ID); + continue; + } + skillid2idx[RFIFOW(fd, 4 + (i*4))] = RFIFOW(fd, 6 + (i*4)); + } + RFIFOSKIP(fd, RFIFOW(fd, 2)); + break; + case 0x2afa: // Receiving map names list from the map-server + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + + memset(server[id].map, 0, sizeof(server[id].map)); + j = 0; + for(i = 4; i < RFIFOW(fd,2); i += 4) { + server[id].map[j] = RFIFOW(fd,i); + j++; + } - ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", - id, j, CONVIP(server[id].ip), server[id].port); - ShowStatus("Map-server %d loading complete.\n", id); + ShowStatus("Map-Server %d connected: %d maps, from IP %d.%d.%d.%d port %d.\n", + id, j, CONVIP(server[id].ip), server[id].port); + ShowStatus("Map-server %d loading complete.\n", id); - // send name for wisp to player - WFIFOHEAD(fd, 3 + NAME_LENGTH); - WFIFOW(fd,0) = 0x2afb; - WFIFOB(fd,2) = 0; - memcpy(WFIFOP(fd,3), wisp_server_name, NAME_LENGTH); - WFIFOSET(fd,3+NAME_LENGTH); + // send name for wisp to player + WFIFOHEAD(fd, 3 + NAME_LENGTH); + WFIFOW(fd,0) = 0x2afb; + WFIFOB(fd,2) = 0; + memcpy(WFIFOP(fd,3), wisp_server_name, NAME_LENGTH); + WFIFOSET(fd,3+NAME_LENGTH); - char_send_fame_list(fd); //Send fame list. + char_send_fame_list(fd); //Send fame list. - { - unsigned char buf[16384]; - int x; - if (j == 0) { - ShowWarning("Map-server %d has NO maps.\n", id); - } else { - // Transmitting maps information to the other map-servers - WBUFW(buf,0) = 0x2b04; - WBUFW(buf,2) = j * 4 + 10; - WBUFL(buf,4) = htonl(server[id].ip); - WBUFW(buf,8) = htons(server[id].port); - memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4); - mapif_sendallwos(fd, buf, WBUFW(buf,2)); - } - // Transmitting the maps of the other map-servers to the new map-server - for(x = 0; x < ARRAYLENGTH(server); x++) { - if (server[x].fd > 0 && x != id) { - WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server[x].map)); - WFIFOW(fd,0) = 0x2b04; - WFIFOL(fd,4) = htonl(server[x].ip); - WFIFOW(fd,8) = htons(server[x].port); - j = 0; - for(i = 0; i < ARRAYLENGTH(server[x].map); i++) - if (server[x].map[i]) - WFIFOW(fd,10+(j++)*4) = server[x].map[i]; - if (j > 0) { - WFIFOW(fd,2) = j * 4 + 10; - WFIFOSET(fd,WFIFOW(fd,2)); + { + unsigned char buf[16384]; + int x; + if (j == 0) { + ShowWarning("Map-server %d has NO maps.\n", id); + } else { + // Transmitting maps information to the other map-servers + WBUFW(buf,0) = 0x2b04; + WBUFW(buf,2) = j * 4 + 10; + WBUFL(buf,4) = htonl(server[id].ip); + WBUFW(buf,8) = htons(server[id].port); + memcpy(WBUFP(buf,10), RFIFOP(fd,4), j * 4); + mapif_sendallwos(fd, buf, WBUFW(buf,2)); + } + // Transmitting the maps of the other map-servers to the new map-server + for(x = 0; x < ARRAYLENGTH(server); x++) { + if (server[x].fd > 0 && x != id) { + WFIFOHEAD(fd,10 +4*ARRAYLENGTH(server[x].map)); + WFIFOW(fd,0) = 0x2b04; + WFIFOL(fd,4) = htonl(server[x].ip); + WFIFOW(fd,8) = htons(server[x].port); + j = 0; + for(i = 0; i < ARRAYLENGTH(server[x].map); i++) + if (server[x].map[i]) + WFIFOW(fd,10+(j++)*4) = server[x].map[i]; + if (j > 0) { + WFIFOW(fd,2) = j * 4 + 10; + WFIFOSET(fd,WFIFOW(fd,2)); + } } } - } - } - RFIFOSKIP(fd,RFIFOW(fd,2)); - break; + } + RFIFOSKIP(fd,RFIFOW(fd,2)); + break; - case 0x2afc: //Packet command is now used for sc_data request. [Skotlex] - if (RFIFOREST(fd) < 10) - return 0; - { -#ifdef ENABLE_SC_SAVING - int aid, cid; - aid = RFIFOL(fd,2); - cid = RFIFOL(fd,6); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", - scdata_db, aid, cid) ) + case 0x2afc: //Packet command is now used for sc_data request. [Skotlex] + if (RFIFOREST(fd) < 10) + return 0; { - Sql_ShowDebug(sql_handle); - break; - } - if( Sql_NumRows(sql_handle) > 0 ) - { - struct status_change_data scdata; - int count; - char* data; - - WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); - WFIFOW(fd,0) = 0x2b1d; - WFIFOL(fd,4) = aid; - WFIFOL(fd,8) = cid; - for( count = 0; count < 50 && SQL_SUCCESS == Sql_NextRow(sql_handle); ++count ) + #ifdef ENABLE_SC_SAVING + int aid, cid; + aid = RFIFOL(fd,2); + cid = RFIFOL(fd,6); + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", + scdata_db, aid, cid) ) { - Sql_GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); - memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); + Sql_ShowDebug(sql_handle); + break; } - if (count >= 50) - ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); - if (count > 0) + if( SQL->NumRows(sql_handle) > 0 ) { - WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); - WFIFOW(fd,12) = count; - WFIFOSET(fd,WFIFOW(fd,2)); + struct status_change_data scdata; + int count; + char* data; + + WFIFOHEAD(fd,14+50*sizeof(struct status_change_data)); + WFIFOW(fd,0) = 0x2b1d; + WFIFOL(fd,4) = aid; + WFIFOL(fd,8) = cid; + for( count = 0; count < 50 && SQL_SUCCESS == SQL->NextRow(sql_handle); ++count ) + { + SQL->GetData(sql_handle, 0, &data, NULL); scdata.type = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); scdata.tick = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); scdata.val1 = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data); + memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data)); + } + if (count >= 50) + ShowWarning("Too many status changes for %d:%d, some of them were not loaded.\n", aid, cid); + if (count > 0) + { + WFIFOW(fd,2) = 14 + count*sizeof(struct status_change_data); + WFIFOW(fd,12) = count; + WFIFOSET(fd,WFIFOW(fd,2)); - //Clear the data once loaded. - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, aid, cid) ) - Sql_ShowDebug(sql_handle); + //Clear the data once loaded. + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '%d' AND `char_id`='%d'", scdata_db, aid, cid) ) + Sql_ShowDebug(sql_handle); + } } + SQL->FreeResult(sql_handle); + #endif + RFIFOSKIP(fd, 10); } - Sql_FreeResult(sql_handle); -#endif - RFIFOSKIP(fd, 10); - } - break; + break; - case 0x2afe: //set MAP user count - if (RFIFOREST(fd) < 4) - return 0; - if (RFIFOW(fd,2) != server[id].users) { - server[id].users = RFIFOW(fd,2); - ShowInfo("User Count: %d (Server: %d)\n", server[id].users, id); + case 0x2afe: //set MAP user count + if (RFIFOREST(fd) < 4) + return 0; + if (RFIFOW(fd,2) != server[id].users) { + server[id].users = RFIFOW(fd,2); + ShowInfo("User Count: %d (Server: %d)\n", server[id].users, id); + } + RFIFOSKIP(fd, 4); + break; + + case 0x2aff: //set MAP users + if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { + //TODO: When data mismatches memory, update guild/party online/offline states. + int aid, cid; + struct online_char_data* character; + + server[id].users = RFIFOW(fd,4); + online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown' + for(i = 0; i < server[id].users; i++) { + aid = RFIFOL(fd,6+i*8); + cid = RFIFOL(fd,6+i*8+4); + character = idb_ensure(online_char_db, aid, create_online_char_data); + if( character->server > -1 && character->server != id ) + { + ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", + character->account_id, character->char_id, character->server, id, aid, cid); + mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); + } + character->server = id; + character->char_id = cid; + } + //If any chars remain in -2, they will be cleaned in the cleanup timer. + RFIFOSKIP(fd,RFIFOW(fd,2)); } - RFIFOSKIP(fd, 4); break; - case 0x2aff: //set MAP users - if (RFIFOREST(fd) < 6 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - { - //TODO: When data mismatches memory, update guild/party online/offline states. - int aid, cid; - struct online_char_data* character; - - server[id].users = RFIFOW(fd,4); - online_char_db->foreach(online_char_db,char_db_setoffline,id); //Set all chars from this server as 'unknown' - for(i = 0; i < server[id].users; i++) { - aid = RFIFOL(fd,6+i*8); - cid = RFIFOL(fd,6+i*8+4); - character = idb_ensure(online_char_db, aid, create_online_char_data); - if( character->server > -1 && character->server != id ) + case 0x2b01: // Receive character data from map-server for saving + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; + { + int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2); + struct online_char_data* character; + + if (size - 13 != sizeof(struct mmo_charstatus)) { - ShowNotice("Set map user: Character (%d:%d) marked on map server %d, but map server %d claims to have (%d:%d) online!\n", - character->account_id, character->char_id, character->server, id, aid, cid); - mapif_disconnectplayer(server[character->server].fd, character->account_id, character->char_id, 2); + ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus)); + RFIFOSKIP(fd,size); + break; + } + //Check account only if this ain't final save. Final-save goes through because of the char-map reconnect + if (RFIFOB(fd,12) || ( + (character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL && + character->char_id == cid)) + { + struct mmo_charstatus char_dat; + memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus)); + mmo_char_tosql(cid, &char_dat); + } else { //This may be valid on char-server reconnection, when re-sending characters that already logged off. + ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid); + set_char_online(id, cid, aid); } - character->server = id; - character->char_id = cid; - } - //If any chars remain in -2, they will be cleaned in the cleanup timer. - RFIFOSKIP(fd,RFIFOW(fd,2)); - } - break; - - case 0x2b01: // Receive character data from map-server for saving - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - { - int aid = RFIFOL(fd,4), cid = RFIFOL(fd,8), size = RFIFOW(fd,2); - struct online_char_data* character; - if (size - 13 != sizeof(struct mmo_charstatus)) - { - ShowError("parse_from_map (save-char): Size mismatch! %d != %d\n", size-13, sizeof(struct mmo_charstatus)); + if (RFIFOB(fd,12)) + { //Flag, set character offline after saving. [Skotlex] + set_char_offline(cid, aid); + WFIFOHEAD(fd,10); + WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save. + WFIFOL(fd,2) = aid; + WFIFOL(fd,6) = cid; + WFIFOSET(fd,10); + } RFIFOSKIP(fd,size); - break; } - //Check account only if this ain't final save. Final-save goes through because of the char-map reconnect - if (RFIFOB(fd,12) || ( - (character = (struct online_char_data*)idb_get(online_char_db, aid)) != NULL && - character->char_id == cid)) + break; + + case 0x2b02: // req char selection + if( RFIFOREST(fd) < 18 ) + return 0; { - struct mmo_charstatus char_dat; - memcpy(&char_dat, RFIFOP(fd,13), sizeof(struct mmo_charstatus)); - mmo_char_tosql(cid, &char_dat); - } else { //This may be valid on char-server reconnection, when re-sending characters that already logged off. - ShowError("parse_from_map (save-char): Received data for non-existant/offline character (%d:%d).\n", aid, cid); - set_char_online(id, cid, aid); - } + int account_id = RFIFOL(fd,2); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); + uint32 ip = RFIFOL(fd,14); + RFIFOSKIP(fd,18); - if (RFIFOB(fd,12)) - { //Flag, set character offline after saving. [Skotlex] - set_char_offline(cid, aid); - WFIFOHEAD(fd,10); - WFIFOW(fd,0) = 0x2b21; //Save ack only needed on final save. - WFIFOL(fd,2) = aid; - WFIFOL(fd,6) = cid; - WFIFOSET(fd,10); + if( runflag != CHARSERVER_ST_RUNNING ) + { + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 0;// not ok + WFIFOSET(fd,7); + } + else + { + struct auth_node* node; + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = account_id; + node->char_id = 0; + node->login_id1 = login_id1; + node->login_id2 = login_id2; + //node->sex = 0; + node->ip = ntohl(ip); + //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) + //node->gmlevel = 0; + idb_put(auth_db, account_id, node); + + //Set char to "@ char select" in online db [Kevin] + set_char_charselect(account_id); + + WFIFOHEAD(fd,7); + WFIFOW(fd,0) = 0x2b03; + WFIFOL(fd,2) = account_id; + WFIFOB(fd,6) = 1;// ok + WFIFOSET(fd,7); + } } - RFIFOSKIP(fd,size); - } - break; - - case 0x2b02: // req char selection - if( RFIFOREST(fd) < 18 ) - return 0; - { - struct auth_node* node; - - int account_id = RFIFOL(fd,2); - uint32 login_id1 = RFIFOL(fd,6); - uint32 login_id2 = RFIFOL(fd,10); - uint32 ip = RFIFOL(fd,14); - RFIFOSKIP(fd,18); + break; - if( runflag != CHARSERVER_ST_RUNNING ) + case 0x2b05: // request "change map server" + if (RFIFOREST(fd) < 39) + return 0; { - WFIFOHEAD(fd,7); - WFIFOW(fd,0) = 0x2b03; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 0;// not ok - WFIFOSET(fd,7); - } - else - { - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = account_id; - node->char_id = 0; - node->login_id1 = login_id1; - node->login_id2 = login_id2; - //node->sex = 0; - node->ip = ntohl(ip); - //node->expiration_time = 0; // unlimited/unknown time by default (not display in map-server) - //node->gmlevel = 0; - idb_put(auth_db, account_id, node); - - //Set char to "@ char select" in online db [Kevin] - set_char_charselect(account_id); - - WFIFOHEAD(fd,7); - WFIFOW(fd,0) = 0x2b03; - WFIFOL(fd,2) = account_id; - WFIFOB(fd,6) = 1;// ok - WFIFOSET(fd,7); - } - } - break; + int map_id, map_fd = -1; + struct mmo_charstatus* char_data; + struct mmo_charstatus char_dat; - case 0x2b05: // request "change map server" - if (RFIFOREST(fd) < 39) - return 0; - { - int map_id, map_fd = -1; - struct online_char_data* data; - struct mmo_charstatus* char_data; - struct mmo_charstatus char_dat; - - map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. - if (map_id >= 0) - map_fd = server[map_id].fd; - //Char should just had been saved before this packet, so this should be safe. [Skotlex] - char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); - if (char_data == NULL) { //Really shouldn't happen. - mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); + map_id = search_mapserver(RFIFOW(fd,18), ntohl(RFIFOL(fd,24)), ntohs(RFIFOW(fd,28))); //Locate mapserver by ip and port. + if (map_id >= 0) + map_fd = server[map_id].fd; + //Char should just had been saved before this packet, so this should be safe. [Skotlex] char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); - } - - if( runflag == CHARSERVER_ST_RUNNING && - session_isActive(map_fd) && - char_data ) - { //Send the map server the auth of this player. - struct auth_node* node; - - //Update the "last map" as this is where the player must be spawned on the new map server. - char_data->last_point.map = RFIFOW(fd,18); - char_data->last_point.x = RFIFOW(fd,20); - char_data->last_point.y = RFIFOW(fd,22); - char_data->sex = RFIFOB(fd,30); + if (char_data == NULL) { //Really shouldn't happen. + mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true); + char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14)); + } - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = RFIFOL(fd,2); - node->char_id = RFIFOL(fd,14); - node->login_id1 = RFIFOL(fd,6); - node->login_id2 = RFIFOL(fd,10); - node->sex = RFIFOB(fd,30); - node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing) - node->ip = ntohl(RFIFOL(fd,31)); - node->group_id = RFIFOL(fd,35); - node->changing_mapservers = 1; - idb_put(auth_db, RFIFOL(fd,2), node); - - data = idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data); - data->char_id = char_data->char_id; - data->server = map_id; //Update server where char is. - - //Reply with an ack. - WFIFOHEAD(fd,30); - WFIFOW(fd,0) = 0x2b06; - memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); - WFIFOSET(fd,30); - } else { //Reply with nak - WFIFOHEAD(fd,30); - WFIFOW(fd,0) = 0x2b06; - memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); - WFIFOL(fd,6) = 0; //Set login1 to 0. - WFIFOSET(fd,30); + if( runflag == CHARSERVER_ST_RUNNING && + session_isActive(map_fd) && + char_data ) + { //Send the map server the auth of this player. + struct online_char_data* data; + struct auth_node* node; + + //Update the "last map" as this is where the player must be spawned on the new map server. + char_data->last_point.map = RFIFOW(fd,18); + char_data->last_point.x = RFIFOW(fd,20); + char_data->last_point.y = RFIFOW(fd,22); + char_data->sex = RFIFOB(fd,30); + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = RFIFOL(fd,2); + node->char_id = RFIFOL(fd,14); + node->login_id1 = RFIFOL(fd,6); + node->login_id2 = RFIFOL(fd,10); + node->sex = RFIFOB(fd,30); + node->expiration_time = 0; // FIXME (this thing isn't really supported we could as well purge it instead of fixing) + node->ip = ntohl(RFIFOL(fd,31)); + node->group_id = RFIFOL(fd,35); + node->changing_mapservers = 1; + idb_put(auth_db, RFIFOL(fd,2), node); + + data = idb_ensure(online_char_db, RFIFOL(fd,2), create_online_char_data); + data->char_id = char_data->char_id; + data->server = map_id; //Update server where char is. + + //Reply with an ack. + WFIFOHEAD(fd,30); + WFIFOW(fd,0) = 0x2b06; + memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); + WFIFOSET(fd,30); + } else { //Reply with nak + WFIFOHEAD(fd,30); + WFIFOW(fd,0) = 0x2b06; + memcpy(WFIFOP(fd,2), RFIFOP(fd,2), 28); + WFIFOL(fd,6) = 0; //Set login1 to 0. + WFIFOSET(fd,30); + } + RFIFOSKIP(fd,39); } - RFIFOSKIP(fd,39); - } - break; + break; - case 0x2b07: // Remove RFIFOL(fd,6) (friend_id) from RFIFOL(fd,2) (char_id) friend list [Ind] - if (RFIFOREST(fd) < 10) - return 0; - { - int char_id, friend_id; - char_id = RFIFOL(fd,2); - friend_id = RFIFOL(fd,6); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1", - friend_db, char_id, friend_id) ) { - Sql_ShowDebug(sql_handle); - break; + case 0x2b07: // Remove RFIFOL(fd,6) (friend_id) from RFIFOL(fd,2) (char_id) friend list [Ind] + if (RFIFOREST(fd) < 10) + return 0; + { + int char_id, friend_id; + char_id = RFIFOL(fd,2); + friend_id = RFIFOL(fd,6); + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id`='%d' AND `friend_id`='%d' LIMIT 1", + friend_db, char_id, friend_id) ) { + Sql_ShowDebug(sql_handle); + break; + } + RFIFOSKIP(fd,10); } - RFIFOSKIP(fd,10); - } - break; + break; - case 0x2b08: // char name request - if (RFIFOREST(fd) < 6) - return 0; + case 0x2b08: // char name request + if (RFIFOREST(fd) < 6) + return 0; - WFIFOHEAD(fd,30); - WFIFOW(fd,0) = 0x2b09; - WFIFOL(fd,2) = RFIFOL(fd,2); - char_loadName((int)RFIFOL(fd,2), (char*)WFIFOP(fd,6)); - WFIFOSET(fd,30); + WFIFOHEAD(fd,30); + WFIFOW(fd,0) = 0x2b09; + WFIFOL(fd,2) = RFIFOL(fd,2); + char_loadName((int)RFIFOL(fd,2), (char*)WFIFOP(fd,6)); + WFIFOSET(fd,30); - RFIFOSKIP(fd,6); - break; + RFIFOSKIP(fd,6); + break; - case 0x2b0c: // Map server send information to change an email of an account -> login-server - if (RFIFOREST(fd) < 86) - return 0; - if (login_fd > 0) { // don't send request if no login-server - WFIFOHEAD(login_fd,86); - memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B - WFIFOW(login_fd,0) = 0x2722; - WFIFOSET(login_fd,86); - } - RFIFOSKIP(fd, 86); - break; + case 0x2b0c: // Map server send information to change an email of an account -> login-server + if (RFIFOREST(fd) < 86) + return 0; + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,86); + memcpy(WFIFOP(login_fd,0), RFIFOP(fd,0),86); // 0x2722 <account_id>.L <actual_e-mail>.40B <new_e-mail>.40B + WFIFOW(login_fd,0) = 0x2722; + WFIFOSET(login_fd,86); + } + RFIFOSKIP(fd, 86); + break; - case 0x2b0e: // Request from map-server to change an account's status (will just be forwarded to login server) - if (RFIFOREST(fd) < 44) - return 0; - { - int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline - char esc_name[NAME_LENGTH*2+1]; - - int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request) - const char* name = (char*)RFIFOP(fd,6); // name of the target character - int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban - short year = RFIFOW(fd,32); - short month = RFIFOW(fd,34); - short day = RFIFOW(fd,36); - short hour = RFIFOW(fd,38); - short minute = RFIFOW(fd,40); - short second = RFIFOW(fd,42); - RFIFOSKIP(fd,44); - - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) - Sql_ShowDebug(sql_handle); - else - if( Sql_NumRows(sql_handle) == 0 ) - { - result = 1; // 1-player not found - } - else - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) - Sql_ShowDebug(sql_handle); - //FIXME: set proper result value? - else + case 0x2b0e: // Request from map-server to change an account's status (will just be forwarded to login server) + if (RFIFOREST(fd) < 44) + return 0; { - char name[NAME_LENGTH]; - int account_id; - char* data; - - Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); + int result = 0; // 0-login-server request done, 1-player not found, 2-gm level too low, 3-login-server offline + char esc_name[NAME_LENGTH*2+1]; - if( login_fd <= 0 ) - result = 3; // 3-login-server offline - //FIXME: need to move this check to login server [ultramage] -// else -// if( acc != -1 && isGM(acc) < isGM(account_id) ) -// result = 2; // 2-gm level too low + int acc = RFIFOL(fd,2); // account_id of who ask (-1 if server itself made this request) + const char* name = (char*)RFIFOP(fd,6); // name of the target character + int type = RFIFOW(fd,30); // type of operation: 1-block, 2-ban, 3-unblock, 4-unban + short year = RFIFOW(fd,32); + short month = RFIFOW(fd,34); + short day = RFIFOW(fd,36); + short hour = RFIFOW(fd,38); + short minute = RFIFOW(fd,40); + short second = RFIFOW(fd,42); + RFIFOSKIP(fd,44); + + SQL->EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`,`name` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) + Sql_ShowDebug(sql_handle); else - switch( type ) { - case 1: // block - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = account_id; - WFIFOL(login_fd,6) = 5; // new account status - WFIFOSET(login_fd,10); - break; - case 2: // ban - WFIFOHEAD(login_fd,18); - WFIFOW(login_fd, 0) = 0x2725; - WFIFOL(login_fd, 2) = account_id; - WFIFOW(login_fd, 6) = year; - WFIFOW(login_fd, 8) = month; - WFIFOW(login_fd,10) = day; - WFIFOW(login_fd,12) = hour; - WFIFOW(login_fd,14) = minute; - WFIFOW(login_fd,16) = second; - WFIFOSET(login_fd,18); - break; - case 3: // unblock - WFIFOHEAD(login_fd,10); - WFIFOW(login_fd,0) = 0x2724; - WFIFOL(login_fd,2) = account_id; - WFIFOL(login_fd,6) = 0; // new account status - WFIFOSET(login_fd,10); - break; - case 4: // unban - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x272a; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); - break; - case 5: // changesex - WFIFOHEAD(login_fd,6); - WFIFOW(login_fd,0) = 0x2727; - WFIFOL(login_fd,2) = account_id; - WFIFOSET(login_fd,6); - break; + if( SQL->NumRows(sql_handle) == 0 ) + { + result = 1; // 1-player not found + } + else + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) + Sql_ShowDebug(sql_handle); + //FIXME: set proper result value? + else + { + char name[NAME_LENGTH]; + int account_id; + char* data; + + SQL->GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); + + if( login_fd <= 0 ) + result = 3; // 3-login-server offline + //FIXME: need to move this check to login server [ultramage] + // else + // if( acc != -1 && isGM(acc) < isGM(account_id) ) + // result = 2; // 2-gm level too low + else + switch( type ) { + case 1: // block + WFIFOHEAD(login_fd,10); + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = account_id; + WFIFOL(login_fd,6) = 5; // new account status + WFIFOSET(login_fd,10); + break; + case 2: // ban + WFIFOHEAD(login_fd,18); + WFIFOW(login_fd, 0) = 0x2725; + WFIFOL(login_fd, 2) = account_id; + WFIFOW(login_fd, 6) = year; + WFIFOW(login_fd, 8) = month; + WFIFOW(login_fd,10) = day; + WFIFOW(login_fd,12) = hour; + WFIFOW(login_fd,14) = minute; + WFIFOW(login_fd,16) = second; + WFIFOSET(login_fd,18); + break; + case 3: // unblock + WFIFOHEAD(login_fd,10); + WFIFOW(login_fd,0) = 0x2724; + WFIFOL(login_fd,2) = account_id; + WFIFOL(login_fd,6) = 0; // new account status + WFIFOSET(login_fd,10); + break; + case 4: // unban + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x272a; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); + break; + case 5: // changesex + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x2727; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); + break; + } } - } - Sql_FreeResult(sql_handle); - - // send answer if a player ask, not if the server ask - if( acc != -1 && type != 5) { // Don't send answer for changesex - WFIFOHEAD(fd,34); - WFIFOW(fd, 0) = 0x2b0f; - WFIFOL(fd, 2) = acc; - safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); - WFIFOW(fd,30) = type; - WFIFOW(fd,32) = result; - WFIFOSET(fd,34); + SQL->FreeResult(sql_handle); + + // send answer if a player ask, not if the server ask + if( acc != -1 && type != 5) { // Don't send answer for changesex + WFIFOHEAD(fd,34); + WFIFOW(fd, 0) = 0x2b0f; + WFIFOL(fd, 2) = acc; + safestrncpy((char*)WFIFOP(fd,6), name, NAME_LENGTH); + WFIFOW(fd,30) = type; + WFIFOW(fd,32) = result; + WFIFOSET(fd,34); + } } - } - break; + break; - case 0x2b10: // Update and send fame ranking list - if (RFIFOREST(fd) < 11) - return 0; - { - int cid = RFIFOL(fd, 2); - int fame = RFIFOL(fd, 6); - char type = RFIFOB(fd, 10); - int size; - struct fame_list* list; - int player_pos; - int fame_pos; - - switch(type) + case 0x2b10: // Update and send fame ranking list + if (RFIFOREST(fd) < 11) + return 0; { - case 1: size = fame_list_size_smith; list = smith_fame_list; break; - case 2: size = fame_list_size_chemist; list = chemist_fame_list; break; - case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; - default: size = 0; list = NULL; break; - } + int cid = RFIFOL(fd, 2); + int fame = RFIFOL(fd, 6); + char type = RFIFOB(fd, 10); + int size; + struct fame_list* list; + int player_pos; + int fame_pos; + + switch(type) + { + case 1: size = fame_list_size_smith; list = smith_fame_list; break; + case 2: size = fame_list_size_chemist; list = chemist_fame_list; break; + case 3: size = fame_list_size_taekwon; list = taekwon_fame_list; break; + default: size = 0; list = NULL; break; + } - ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player - ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be + ARR_FIND(0, size, player_pos, list[player_pos].id == cid);// position of the player + ARR_FIND(0, size, fame_pos, list[fame_pos].fame <= fame);// where the player should be - if( player_pos == size && fame_pos == size ) - ;// not on list and not enough fame to get on it - else if( fame_pos == player_pos ) - {// same position - list[player_pos].fame = fame; - char_update_fame_list(type, player_pos, fame); - } - else - {// move in the list - if( player_pos == size ) - {// new ranker - not in the list - ARR_MOVE(size - 1, fame_pos, list, struct fame_list); - list[fame_pos].id = cid; - list[fame_pos].fame = fame; - char_loadName(cid, list[fame_pos].name); + if( player_pos == size && fame_pos == size ) + ;// not on list and not enough fame to get on it + else if( fame_pos == player_pos ) + {// same position + list[player_pos].fame = fame; + char_update_fame_list(type, player_pos, fame); } else - {// already in the list - if( fame_pos == size ) - --fame_pos;// move to the end of the list - ARR_MOVE(player_pos, fame_pos, list, struct fame_list); - list[fame_pos].fame = fame; + {// move in the list + if( player_pos == size ) + {// new ranker - not in the list + ARR_MOVE(size - 1, fame_pos, list, struct fame_list); + list[fame_pos].id = cid; + list[fame_pos].fame = fame; + char_loadName(cid, list[fame_pos].name); + } + else + {// already in the list + if( fame_pos == size ) + --fame_pos;// move to the end of the list + ARR_MOVE(player_pos, fame_pos, list, struct fame_list); + list[fame_pos].fame = fame; + } + char_send_fame_list(-1); } - char_send_fame_list(-1); - } - - RFIFOSKIP(fd,11); - } - break; - // Divorce chars - case 0x2b11: - if( RFIFOREST(fd) < 10 ) - return 0; - - divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6)); - RFIFOSKIP(fd,10); - break; + RFIFOSKIP(fd,11); + } + break; - case 0x2b16: // Receive rates [Wizputer] - if( RFIFOREST(fd) < 14 ) - return 0; - { - char esc_server_name[sizeof(server_name)*2+1]; + // Divorce chars + case 0x2b11: + if( RFIFOREST(fd) < 10 ) + return 0; - Sql_EscapeString(sql_handle, esc_server_name, server_name); + divorce_char_sql(RFIFOL(fd,2), RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + break; - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d'", - ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) ) - Sql_ShowDebug(sql_handle); - RFIFOSKIP(fd,14); - } - break; + case 0x2b16: // Receive rates [Wizputer] + if( RFIFOREST(fd) < 14 ) + return 0; + { + char esc_server_name[sizeof(server_name)*2+1]; - case 0x2b17: // Character disconnected set online 0 [Wizputer] - if (RFIFOREST(fd) < 6) - return 0; - set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); - RFIFOSKIP(fd,10); - break; + SQL->EscapeString(sql_handle, esc_server_name, server_name); - case 0x2b18: // Reset all chars to offline [Wizputer] - set_all_offline(id); - RFIFOSKIP(fd,2); - break; + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` SET `index`='%d',`name`='%s',`exp`='%d',`jexp`='%d',`drop`='%d'", + ragsrvinfo_db, fd, esc_server_name, RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10)) ) + Sql_ShowDebug(sql_handle); + RFIFOSKIP(fd,14); + } + break; - case 0x2b19: // Character set online [Wizputer] - if (RFIFOREST(fd) < 10) - return 0; - set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6)); - RFIFOSKIP(fd,10); - break; + case 0x2b17: // Character disconnected set online 0 [Wizputer] + if (RFIFOREST(fd) < 6) + return 0; + set_char_offline(RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + break; - case 0x2b1a: // Build and send fame ranking lists [DracoRPG] - if (RFIFOREST(fd) < 2) - return 0; - char_read_fame_list(); - char_send_fame_list(-1); - RFIFOSKIP(fd,2); - break; + case 0x2b18: // Reset all chars to offline [Wizputer] + set_all_offline(id); + RFIFOSKIP(fd,2); + break; - case 0x2b1c: //Request to save status change data. [Skotlex] - if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) - return 0; - { -#ifdef ENABLE_SC_SAVING - int count, aid, cid; + case 0x2b19: // Character set online [Wizputer] + if (RFIFOREST(fd) < 10) + return 0; + set_char_online(id, RFIFOL(fd,2),RFIFOL(fd,6)); + RFIFOSKIP(fd,10); + break; - aid = RFIFOL(fd, 4); - cid = RFIFOL(fd, 8); - count = RFIFOW(fd, 12); + case 0x2b1a: // Build and send fame ranking lists [DracoRPG] + if (RFIFOREST(fd) < 2) + return 0; + char_read_fame_list(); + char_send_fame_list(-1); + RFIFOSKIP(fd,2); + break; - if( count > 0 ) + case 0x2b1c: //Request to save status change data. [Skotlex] + if (RFIFOREST(fd) < 4 || RFIFOREST(fd) < RFIFOW(fd,2)) + return 0; { - struct status_change_data data; - StringBuf buf; - int i; + #ifdef ENABLE_SC_SAVING + int count, aid, cid; - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db); - for( i = 0; i < count; ++i ) + aid = RFIFOL(fd, 4); + cid = RFIFOL(fd, 8); + count = RFIFOW(fd, 12); + + if( count > 0 ) { - memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); - if( i > 0 ) - StringBuf_AppendStr(&buf, ", "); - StringBuf_Printf(&buf, "('%d','%d','%hu','%d','%d','%d','%d','%d')", aid, cid, - data.type, data.tick, data.val1, data.val2, data.val3, data.val4); + struct status_change_data data; + StringBuf buf; + int i; + + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", scdata_db); + for( i = 0; i < count; ++i ) + { + memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data)); + if( i > 0 ) + StrBuf->AppendStr(&buf, ", "); + StrBuf->Printf(&buf, "('%d','%d','%hu','%d','%d','%d','%d','%d')", aid, cid, + data.type, data.tick, data.val1, data.val2, data.val3, data.val4); + } + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) + Sql_ShowDebug(sql_handle); + StrBuf->Destroy(&buf); } - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) - Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + #endif + RFIFOSKIP(fd, RFIFOW(fd, 2)); } -#endif - RFIFOSKIP(fd, RFIFOW(fd, 2)); - } - break; + break; - case 0x2b23: // map-server alive packet - WFIFOHEAD(fd,2); - WFIFOW(fd,0) = 0x2b24; - WFIFOSET(fd,2); - RFIFOSKIP(fd,2); - break; + case 0x2b23: // map-server alive packet + WFIFOHEAD(fd,2); + WFIFOW(fd,0) = 0x2b24; + WFIFOSET(fd,2); + RFIFOSKIP(fd,2); + break; - case 0x2b26: // auth request from map-server - if (RFIFOREST(fd) < 19) - return 0; + case 0x2b26: // auth request from map-server + if (RFIFOREST(fd) < 19) + return 0; - { - int account_id; - int char_id; - int login_id1; - char sex; - uint32 ip; - struct auth_node* node; - struct mmo_charstatus* cd; - struct mmo_charstatus char_dat; - - account_id = RFIFOL(fd,2); - char_id = RFIFOL(fd,6); - login_id1 = RFIFOL(fd,10); - sex = RFIFOB(fd,14); - ip = ntohl(RFIFOL(fd,15)); - RFIFOSKIP(fd,19); - - node = (struct auth_node*)idb_get(auth_db, account_id); - cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); - if( cd == NULL ) - { //Really shouldn't happen. - mmo_char_fromsql(char_id, &char_dat, true); + { + int account_id; + int char_id; + int login_id1; + char sex; + uint32 ip; + struct auth_node* node; + struct mmo_charstatus* cd; + struct mmo_charstatus char_dat; + + account_id = RFIFOL(fd,2); + char_id = RFIFOL(fd,6); + login_id1 = RFIFOL(fd,10); + sex = RFIFOB(fd,14); + ip = ntohl(RFIFOL(fd,15)); + RFIFOSKIP(fd,19); + + node = (struct auth_node*)idb_get(auth_db, account_id); cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); - } - if( runflag == CHARSERVER_ST_RUNNING && - cd != NULL && - node != NULL && - node->account_id == account_id && - node->char_id == char_id && - node->login_id1 == login_id1 && - node->sex == sex /*&& - node->ip == ip*/ ) - {// auth ok - cd->sex = sex; - - WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus)); - WFIFOW(fd,0) = 0x2afd; - WFIFOW(fd,2) = 25 + sizeof(struct mmo_charstatus); - WFIFOL(fd,4) = account_id; - WFIFOL(fd,8) = node->login_id1; - WFIFOL(fd,12) = node->login_id2; - WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" - WFIFOL(fd,20) = node->group_id; - WFIFOB(fd,24) = node->changing_mapservers; - memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); - WFIFOSET(fd, WFIFOW(fd,2)); - - // only use the auth once and mark user online - idb_remove(auth_db, account_id); - set_char_online(id, char_id, account_id); - } - else - {// auth failed - WFIFOHEAD(fd,19); - WFIFOW(fd,0) = 0x2b27; - WFIFOL(fd,2) = account_id; - WFIFOL(fd,6) = char_id; - WFIFOL(fd,10) = login_id1; - WFIFOB(fd,14) = sex; - WFIFOL(fd,15) = htonl(ip); - WFIFOSET(fd,19); - } - } - break; - - case 0x2736: // ip address update - if (RFIFOREST(fd) < 6) return 0; - server[id].ip = ntohl(RFIFOL(fd, 2)); - ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(server[id].ip)); - RFIFOSKIP(fd,6); - break; - - case 0x3008: - if( RFIFOREST(fd) < RFIFOW(fd,4) ) - return 0;/* packet wasn't fully received yet (still fragmented) */ - else { - int sfd;/* stat server fd */ - RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */ - - if( (sfd = make_connection(host2ip("stats.rathena.org"),(uint16)25421,true) ) == -1 ) { - RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ - break;/* connection not possible, we drop the report */ + if( cd == NULL ) + { //Really shouldn't happen. + mmo_char_fromsql(char_id, &char_dat, true); + cd = (struct mmo_charstatus*)uidb_get(char_db_,char_id); } + if( runflag == CHARSERVER_ST_RUNNING && + cd != NULL && + node != NULL && + node->account_id == account_id && + node->char_id == char_id && + node->login_id1 == login_id1 && + node->sex == sex /*&& + node->ip == ip*/ ) + {// auth ok + cd->sex = sex; + + WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus)); + WFIFOW(fd,0) = 0x2afd; + WFIFOW(fd,2) = 25 + sizeof(struct mmo_charstatus); + WFIFOL(fd,4) = account_id; + WFIFOL(fd,8) = node->login_id1; + WFIFOL(fd,12) = node->login_id2; + WFIFOL(fd,16) = (uint32)node->expiration_time; // FIXME: will wrap to negative after "19-Jan-2038, 03:14:07 AM GMT" + WFIFOL(fd,20) = node->group_id; + WFIFOB(fd,24) = node->changing_mapservers; + memcpy(WFIFOP(fd,25), cd, sizeof(struct mmo_charstatus)); + WFIFOSET(fd, WFIFOW(fd,2)); + + // only use the auth once and mark user online + idb_remove(auth_db, account_id); + set_char_online(id, char_id, account_id); + } + else + {// auth failed + WFIFOHEAD(fd,19); + WFIFOW(fd,0) = 0x2b27; + WFIFOL(fd,2) = account_id; + WFIFOL(fd,6) = char_id; + WFIFOL(fd,10) = login_id1; + WFIFOB(fd,14) = sex; + WFIFOL(fd,15) = htonl(ip); + WFIFOSET(fd,19); + } + } + break; - session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */ + case 0x2736: // ip address update + if (RFIFOREST(fd) < 6) return 0; + server[id].ip = ntohl(RFIFOL(fd, 2)); + ShowInfo("Updated IP address of map-server #%d to %d.%d.%d.%d.\n", id, CONVIP(server[id].ip)); + RFIFOSKIP(fd,6); + break; - WFIFOHEAD(sfd, RFIFOW(fd,2) ); + case 0x3008: + if( RFIFOREST(fd) < RFIFOW(fd,4) ) + return 0;/* packet wasn't fully received yet (still fragmented) */ + else { + int sfd;/* stat server fd */ + RFIFOSKIP(fd, 2);/* we skip first 2 bytes which are the 0x3008, so we end up with a buffer equal to the one we send */ - memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2)); + if( (sfd = make_connection(host2ip("stats.hercules.ws"),(uint16)25427,true) ) == -1 ) { + RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ + RFIFOFLUSH(fd); + break;/* connection not possible, we drop the report */ + } + + session[sfd]->flag.server = 1;/* to ensure we won't drop our own packet */ + realloc_fifo(sfd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + + WFIFOHEAD(sfd, RFIFOW(fd,2) ); - WFIFOSET(sfd, RFIFOW(fd,2) ); + memcpy((char*)WFIFOP(sfd,0), (char*)RFIFOP(fd, 0), RFIFOW(fd,2)); - flush_fifo(sfd); + WFIFOSET(sfd, RFIFOW(fd,2) ); - do_close(sfd); + flush_fifo(sfd); - RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ - } - break; + do_close(sfd); + + RFIFOSKIP(fd, RFIFOW(fd,2) );/* skip this packet */ + RFIFOFLUSH(fd); + } + break; - default: - { - // inter server - packet - int r = inter_parse_frommap(fd); - if (r == 1) break; // processed - if (r == 2) return 0; // need more packet + default: + { + // inter server - packet + int r = inter_parse_frommap(fd); + if (r == 1) break; // processed + if (r == 2) return 0; // need more packet - // no inter server packet. no char server packet -> disconnect - ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0)); - set_eof(fd); - return 0; - } + // no inter server packet. no char server packet -> disconnect + ShowError("Unknown packet 0x%04x from map server, disconnecting.\n", RFIFOW(fd,0)); + set_eof(fd); + return 0; + } } // switch } // while @@ -3470,14 +3561,14 @@ static void char_delete2_req(int fd, struct char_session_data* sd) return; } - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->Query(sql_handle, "SELECT `delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != SQL->NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); char_delete2_ack(fd, char_id, 3, 0); return; } - Sql_GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); + SQL->GetData(sql_handle, 0, &data, NULL); delete_date = strtoul(data, NULL, 10); if( delete_date ) {// character already queued for deletion char_delete2_ack(fd, char_id, 0, 0); @@ -3504,7 +3595,7 @@ static void char_delete2_req(int fd, struct char_session_data* sd) // success delete_date = time(NULL)+char_del_delay; - if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", char_db, (unsigned long)delete_date, char_id) ) + if( SQL_SUCCESS != SQL->Query(sql_handle, "UPDATE `%s` SET `delete_date`='%lu' WHERE `char_id`='%d'", char_db, (unsigned long)delete_date, char_id) ) { Sql_ShowDebug(sql_handle); char_delete2_ack(fd, char_id, 3, 0); @@ -3545,15 +3636,15 @@ static void char_delete2_accept(int fd, struct char_session_data* sd) return; } - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->Query(sql_handle, "SELECT `base_level`,`delete_date` FROM `%s` WHERE `char_id`='%d'", char_db, char_id) || SQL_SUCCESS != SQL->NextRow(sql_handle) ) {// data error Sql_ShowDebug(sql_handle); char_delete2_accept_ack(fd, char_id, 3); return; } - Sql_GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10); + SQL->GetData(sql_handle, 0, &data, NULL); base_level = (unsigned int)strtoul(data, NULL, 10); + SQL->GetData(sql_handle, 1, &data, NULL); delete_date = strtoul(data, NULL, 10); if( !delete_date || delete_date>time(NULL) ) {// not queued or delay not yet passed @@ -3581,8 +3672,7 @@ static void char_delete2_accept(int fd, struct char_session_data* sd) } // refresh character list cache - for(k = i; k < MAX_CHARS-1; k++) - { + for(k = i; k < MAX_CHARS-1; k++) { sd->found_char[k] = sd->found_char[k+1]; } sd->found_char[MAX_CHARS-1] = -1; @@ -3607,7 +3697,7 @@ static void char_delete2_cancel(int fd, struct char_session_data* sd) // there is no need to check, whether or not the character was // queued for deletion, as the client prints an error message by // itself, if it was not the case (@see char_delete2_cancel_ack) - if( SQL_SUCCESS != Sql_Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", char_db, char_id) ) + if( SQL_SUCCESS != SQL->Query(sql_handle, "UPDATE `%s` SET `delete_date`='0' WHERE `char_id`='%d'", char_db, char_id) ) { Sql_ShowDebug(sql_handle); char_delete2_cancel_ack(fd, char_id, 2); @@ -3647,525 +3737,633 @@ int parse_char(int fd) return 0; } - while( RFIFOREST(fd) >= 2 ) - { + while( RFIFOREST(fd) >= 2 ) { //For use in packets that depend on an sd being present [Skotlex] #define FIFOSD_CHECK(rest) { if(RFIFOREST(fd) < rest) return 0; if (sd==NULL || !sd->auth) { RFIFOSKIP(fd,rest); return 0; } } cmd = RFIFOW(fd,0); - switch( cmd ) - { - // request to connect - // 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B - case 0x65: - if( RFIFOREST(fd) < 17 ) - return 0; - { - struct auth_node* node; + switch( cmd ) { - int account_id = RFIFOL(fd,2); - uint32 login_id1 = RFIFOL(fd,6); - uint32 login_id2 = RFIFOL(fd,10); - int sex = RFIFOB(fd,16); - RFIFOSKIP(fd,17); - - ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2); + // request to connect + // 0065 <account id>.L <login id1>.L <login id2>.L <???>.W <sex>.B + case 0x65: + if( RFIFOREST(fd) < 17 ) + return 0; + { + struct auth_node* node; - if (sd) { - //Received again auth packet for already authentified account?? Discard it. - //TODO: Perhaps log this as a hack attempt? - //TODO: and perhaps send back a reply? - break; - } + int account_id = RFIFOL(fd,2); + uint32 login_id1 = RFIFOL(fd,6); + uint32 login_id2 = RFIFOL(fd,10); + int sex = RFIFOB(fd,16); + RFIFOSKIP(fd,17); - CREATE(session[fd]->session_data, struct char_session_data, 1); - sd = (struct char_session_data*)session[fd]->session_data; - sd->account_id = account_id; - sd->login_id1 = login_id1; - sd->login_id2 = login_id2; - sd->sex = sex; - sd->auth = false; // not authed yet + ShowInfo("request connect - account_id:%d/login_id1:%d/login_id2:%d\n", account_id, login_id1, login_id2); - // send back account_id - WFIFOHEAD(fd,4); - WFIFOL(fd,0) = account_id; - WFIFOSET(fd,4); + if (sd) { + //Received again auth packet for already authentified account?? Discard it. + //TODO: Perhaps log this as a hack attempt? + //TODO: and perhaps send back a reply? + break; + } - if( runflag != CHARSERVER_ST_RUNNING ) - { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0;// rejected from server - WFIFOSET(fd,3); - break; - } + CREATE(session[fd]->session_data, struct char_session_data, 1); + sd = (struct char_session_data*)session[fd]->session_data; + sd->account_id = account_id; + sd->login_id1 = login_id1; + sd->login_id2 = login_id2; + sd->sex = sex; + sd->auth = false; // not authed yet + + // send back account_id + WFIFOHEAD(fd,4); + WFIFOL(fd,0) = account_id; + WFIFOSET(fd,4); - // search authentification - node = (struct auth_node*)idb_get(auth_db, account_id); - if( node != NULL && - node->account_id == account_id && - node->login_id1 == login_id1 && - node->login_id2 == login_id2 /*&& - node->ip == ipl*/ ) - {// authentication found (coming from map server) - idb_remove(auth_db, account_id); - char_auth_ok(fd, sd); - } - else - {// authentication not found (coming from login server) - if (login_fd > 0) { // don't send request if no login-server - WFIFOHEAD(login_fd,23); - WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account - WFIFOL(login_fd,2) = sd->account_id; - WFIFOL(login_fd,6) = sd->login_id1; - WFIFOL(login_fd,10) = sd->login_id2; - WFIFOB(login_fd,14) = sd->sex; - WFIFOL(login_fd,15) = htonl(ipl); - WFIFOL(login_fd,19) = fd; - WFIFOSET(login_fd,23); - } else { // if no login-server, we must refuse connection + if( runflag != CHARSERVER_ST_RUNNING ) + { WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0; + WFIFOB(fd,2) = 0;// rejected from server WFIFOSET(fd,3); + break; } - } - } - break; - // char select - case 0x66: - FIFOSD_CHECK(3); - { - struct mmo_charstatus char_dat; - struct mmo_charstatus *cd; - char* data; - int char_id; - uint32 subnet_map_ip; - struct auth_node* node; - - int slot = RFIFOB(fd,2); - RFIFOSKIP(fd,3); - - if ( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot) - || SQL_SUCCESS != Sql_NextRow(sql_handle) - || SQL_SUCCESS != Sql_GetData(sql_handle, 0, &data, NULL) ) - { //Not found?? May be forged packet. - Sql_ShowDebug(sql_handle); - Sql_FreeResult(sql_handle); - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6c; - WFIFOB(fd,2) = 0; // rejected from server - WFIFOSET(fd,3); - break; + // search authentification + node = (struct auth_node*)idb_get(auth_db, account_id); + if( node != NULL && + node->account_id == account_id && + node->login_id1 == login_id1 && + node->login_id2 == login_id2 /*&& + node->ip == ipl*/ ) + {// authentication found (coming from map server) + idb_remove(auth_db, account_id); + char_auth_ok(fd, sd); + } + else + {// authentication not found (coming from login server) + if (login_fd > 0) { // don't send request if no login-server + WFIFOHEAD(login_fd,23); + WFIFOW(login_fd,0) = 0x2712; // ask login-server to authentify an account + WFIFOL(login_fd,2) = sd->account_id; + WFIFOL(login_fd,6) = sd->login_id1; + WFIFOL(login_fd,10) = sd->login_id2; + WFIFOB(login_fd,14) = sd->sex; + WFIFOL(login_fd,15) = htonl(ipl); + WFIFOL(login_fd,19) = fd; + WFIFOSET(login_fd,23); + } else { // if no login-server, we must refuse connection + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + } + } } + break; - char_id = atoi(data); - Sql_FreeResult(sql_handle); - mmo_char_fromsql(char_id, &char_dat, true); - - //Have to switch over to the DB instance otherwise data won't propagate [Kevin] - cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); - cd->sex = sd->sex; - - if (log_char) { - char esc_name[NAME_LENGTH*2+1]; + // char select + case 0x66: + FIFOSD_CHECK(3); + { + struct mmo_charstatus char_dat; + struct mmo_charstatus *cd; + char* data; + int char_id; + uint32 subnet_map_ip; + struct auth_node* node; - Sql_EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", - charlog_db, sd->account_id, slot, esc_name) ) + int slot = RFIFOB(fd,2); + RFIFOSKIP(fd,3); +#if PACKETVER >= 20110309 + if( *pincode->enabled ){ // hack check + struct online_char_data* character; + character = (struct online_char_data*)idb_get(online_char_db, sd->account_id); + if( character && character->pincode_enable == -1){ + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + break; + } + } +#endif + if ( SQL_SUCCESS != SQL->Query(sql_handle, "SELECT `char_id` FROM `%s` WHERE `account_id`='%d' AND `char_num`='%d'", char_db, sd->account_id, slot) + || SQL_SUCCESS != SQL->NextRow(sql_handle) + || SQL_SUCCESS != SQL->GetData(sql_handle, 0, &data, NULL) ) + { //Not found?? May be forged packet. Sql_ShowDebug(sql_handle); - } - ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name); - - // searching map server - i = search_mapserver(cd->last_point.map, -1, -1); - - // if map is not found, we check major cities - if (i < 0 || !cd->last_point.map) { - unsigned short j; - //First check that there's actually a map server online. - ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] ); - if (j == ARRAYLENGTH(server)) { - ShowInfo("Connection Closed. No map servers available.\n"); + SQL->FreeResult(sql_handle); WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 1; // 01 = Server closed + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; // rejected from server WFIFOSET(fd,3); break; } - if ((i = search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) { - cd->last_point.x = 273; - cd->last_point.y = 354; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) { - cd->last_point.x = 120; - cd->last_point.y = 100; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) { - cd->last_point.x = 160; - cd->last_point.y = 94; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) { - cd->last_point.x = 116; - cd->last_point.y = 57; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) { - cd->last_point.x = 87; - cd->last_point.y = 117; - } else if ((i = search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) { - cd->last_point.x = 94; - cd->last_point.y = 103; - } else { - ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map)); + + char_id = atoi(data); + SQL->FreeResult(sql_handle); + + /* set char as online prior to loading its data so 3rd party applications will realise the sql data is not reliable */ + set_char_online(-2,char_id,sd->account_id); + if( !mmo_char_fromsql(char_id, &char_dat, true) ) { /* failed? set it back offline */ + set_char_offline(char_id, sd->account_id); + /* failed to load something. REJECT! */ + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + break;/* jump off this boat */ + } + + //Have to switch over to the DB instance otherwise data won't propagate [Kevin] + cd = (struct mmo_charstatus *)idb_get(char_db_, char_id); + cd->sex = sd->sex; + + if (log_char) { + char esc_name[NAME_LENGTH*2+1]; + + SQL->EscapeStringLen(sql_handle, esc_name, char_dat.name, strnlen(char_dat.name, NAME_LENGTH)); + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s`(`time`, `account_id`,`char_num`,`name`) VALUES (NOW(), '%d', '%d', '%s')", + charlog_db, sd->account_id, slot, esc_name) ) + Sql_ShowDebug(sql_handle); + } + ShowInfo("Selected char: (Account %d: %d - %s)\n", sd->account_id, slot, char_dat.name); + + // searching map server + i = search_mapserver(cd->last_point.map, -1, -1); + + // if map is not found, we check major cities + if (i < 0 || !cd->last_point.map) { + unsigned short j; + //First check that there's actually a map server online. + ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map[0] ); + if (j == ARRAYLENGTH(server)) { + ShowInfo("Connection Closed. No map servers available.\n"); + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = 1; // 01 = Server closed + WFIFOSET(fd,3); + break; + } + if ((i = search_mapserver((j=mapindex_name2id(MAP_PRONTERA)),-1,-1)) >= 0) { + cd->last_point.x = 273; + cd->last_point.y = 354; + } else if ((i = search_mapserver((j=mapindex_name2id(MAP_GEFFEN)),-1,-1)) >= 0) { + cd->last_point.x = 120; + cd->last_point.y = 100; + } else if ((i = search_mapserver((j=mapindex_name2id(MAP_MORROC)),-1,-1)) >= 0) { + cd->last_point.x = 160; + cd->last_point.y = 94; + } else if ((i = search_mapserver((j=mapindex_name2id(MAP_ALBERTA)),-1,-1)) >= 0) { + cd->last_point.x = 116; + cd->last_point.y = 57; + } else if ((i = search_mapserver((j=mapindex_name2id(MAP_PAYON)),-1,-1)) >= 0) { + cd->last_point.x = 87; + cd->last_point.y = 117; + } else if ((i = search_mapserver((j=mapindex_name2id(MAP_IZLUDE)),-1,-1)) >= 0) { + cd->last_point.x = 94; + cd->last_point.y = 103; + } else { + ShowInfo("Connection Closed. No map server available that has a major city, and unable to find map-server for '%s'.\n", mapindex_id2name(cd->last_point.map)); + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x81; + WFIFOB(fd,2) = 1; // 01 = Server closed + WFIFOSET(fd,3); + break; + } + ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j)); + cd->last_point.map = j; + } + + //Send NEW auth packet [Kevin] + //FIXME: is this case even possible? [ultramage] + if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL) + { + ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); + server[i].fd = -1; + memset(&server[i], 0, sizeof(struct mmo_map_server)); + //Send server closed. WFIFOHEAD(fd,3); WFIFOW(fd,0) = 0x81; WFIFOB(fd,2) = 1; // 01 = Server closed WFIFOSET(fd,3); break; } - ShowWarning("Unable to find map-server for '%s', sending to major city '%s'.\n", mapindex_id2name(cd->last_point.map), mapindex_id2name(j)); - cd->last_point.map = j; - } - //Send NEW auth packet [Kevin] - //FIXME: is this case even possible? [ultramage] - if ((map_fd = server[i].fd) < 1 || session[map_fd] == NULL) - { - ShowError("parse_char: Attempting to write to invalid session %d! Map Server #%d disconnected.\n", map_fd, i); - server[i].fd = -1; - memset(&server[i], 0, sizeof(struct mmo_map_server)); - //Send server closed. - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x81; - WFIFOB(fd,2) = 1; // 01 = Server closed - WFIFOSET(fd,3); - break; + //Send player to map + WFIFOHEAD(fd,28); + WFIFOW(fd,0) = 0x71; + WFIFOL(fd,2) = cd->char_id; + mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); + subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] + WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip); + WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!] + WFIFOSET(fd,28); + + // create temporary auth entry + CREATE(node, struct auth_node, 1); + node->account_id = sd->account_id; + node->char_id = cd->char_id; + node->login_id1 = sd->login_id1; + node->login_id2 = sd->login_id2; + node->sex = sd->sex; + node->expiration_time = sd->expiration_time; + node->group_id = sd->group_id; + node->ip = ipl; + idb_put(auth_db, sd->account_id, node); + } + break; - //Send player to map - WFIFOHEAD(fd,28); - WFIFOW(fd,0) = 0x71; - WFIFOL(fd,2) = cd->char_id; - mapindex_getmapname_ext(mapindex_id2name(cd->last_point.map), (char*)WFIFOP(fd,6)); - subnet_map_ip = lan_subnetcheck(ipl); // Advanced subnet check [LuzZza] - WFIFOL(fd,22) = htonl((subnet_map_ip) ? subnet_map_ip : server[i].ip); - WFIFOW(fd,26) = ntows(htons(server[i].port)); // [!] LE byte order here [!] - WFIFOSET(fd,28); - - // create temporary auth entry - CREATE(node, struct auth_node, 1); - node->account_id = sd->account_id; - node->char_id = cd->char_id; - node->login_id1 = sd->login_id1; - node->login_id2 = sd->login_id2; - node->sex = sd->sex; - node->expiration_time = sd->expiration_time; - node->group_id = sd->group_id; - node->ip = ipl; - idb_put(auth_db, sd->account_id, node); - - set_char_online(-2,node->char_id,sd->account_id); + // create new char + #if PACKETVER >= 20120307 + // S 0970 <name>.24B <slot>.B <hair color>.W <hair style>.W + case 0x970: + FIFOSD_CHECK(31); + #else + // S 0067 <name>.24B <str>.B <agi>.B <vit>.B <int>.B <dex>.B <luk>.B <slot>.B <hair color>.W <hair style>.W + case 0x67: + FIFOSD_CHECK(37); + #endif - } - break; + if( !char_new ) //turn character creation on/off [Kevin] + i = -2; + else + #if PACKETVER >= 20120307 + i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29)); + #else + i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35)); + #endif - // create new char -#if PACKETVER >= 20120307 - // S 0970 <name>.24B <slot>.B <hair color>.W <hair style>.W - case 0x970: - FIFOSD_CHECK(31); -#else - // S 0067 <name>.24B <str>.B <agi>.B <vit>.B <int>.B <dex>.B <luk>.B <slot>.B <hair color>.W <hair style>.W - case 0x67: - FIFOSD_CHECK(37); -#endif + //'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3) + if (i < 0) { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6e; + /* Others I found [Ind] */ + /* 0x02 = Symbols in Character Names are forbidden */ + /* 0x03 = You are not elegible to open the Character Slot. */ + switch (i) { + case -1: WFIFOB(fd,2) = 0x00; break; + case -2: WFIFOB(fd,2) = 0xFF; break; + case -3: WFIFOB(fd,2) = 0x01; break; + case -4: WFIFOB(fd,2) = 0x03; break; + } + WFIFOSET(fd,3); + } else { + int len; + // retrieve data + struct mmo_charstatus char_dat; + mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed. + + // send to player + WFIFOHEAD(fd,2+MAX_CHAR_BUF); + WFIFOW(fd,0) = 0x6d; + len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat); + WFIFOSET(fd,len); + + // add new entry to the chars list + ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 ); + if( ch < MAX_CHARS ) + sd->found_char[ch] = i; // the char_id of the new char + } + #if PACKETVER >= 20120307 + RFIFOSKIP(fd,31); + #else + RFIFOSKIP(fd,37); + #endif + break; - if( !char_new ) //turn character creation on/off [Kevin] - i = -2; - else -#if PACKETVER >= 20120307 - i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOW(fd,27),RFIFOW(fd,29)); -#else - i = make_new_char_sql(sd, (char*)RFIFOP(fd,2),RFIFOB(fd,26),RFIFOB(fd,27),RFIFOB(fd,28),RFIFOB(fd,29),RFIFOB(fd,30),RFIFOB(fd,31),RFIFOB(fd,32),RFIFOW(fd,33),RFIFOW(fd,35)); + // delete char + case 0x68: + // 2004-04-19aSakexe+ langtype 12 char deletion packet + case 0x1fb: + if (cmd == 0x68) FIFOSD_CHECK(46); + if (cmd == 0x1fb) FIFOSD_CHECK(56); + { + int cid = RFIFOL(fd,2); +#if PACKETVER >= 20110309 + if( *pincode->enabled ){ // hack check + struct online_char_data* character; + character = (struct online_char_data*)idb_get(online_char_db, sd->account_id); + if( character && character->pincode_enable == -1 ){ + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x6c; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + break; + } + } #endif + ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); + memcpy(email, RFIFOP(fd,6), 40); + RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); + + // Check if e-mail is correct + if(strcmpi(email, sd->email) && //email does not matches and + ( + strcmp("a@a.com", sd->email) || //it is not default email, or + (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default + )) { //Fail + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; // 00 = Incorrect Email address + WFIFOSET(fd,3); + break; + } - //'Charname already exists' (-1), 'Char creation denied' (-2) and 'You are underaged' (-3) - if (i < 0) - { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x6e; - switch (i) { - case -1: WFIFOB(fd,2) = 0x00; break; - case -2: WFIFOB(fd,2) = 0xFF; break; - case -3: WFIFOB(fd,2) = 0x01; break; + // check if this char exists + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + { // Such a character does not exist in the account + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x70; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + break; } - WFIFOSET(fd,3); - } - else - { - int len; - // retrieve data - struct mmo_charstatus char_dat; - mmo_char_fromsql(i, &char_dat, false); //Only the short data is needed. - - // send to player - WFIFOHEAD(fd,2+MAX_CHAR_BUF); - WFIFOW(fd,0) = 0x6d; - len = 2 + mmo_char_tobuf(WFIFOP(fd,2), &char_dat); - WFIFOSET(fd,len); - - // add new entry to the chars list - ARR_FIND( 0, MAX_CHARS, ch, sd->found_char[ch] == -1 ); - if( ch < MAX_CHARS ) - sd->found_char[ch] = i; // the char_id of the new char + + // remove char from list and compact it + for(ch = i; ch < MAX_CHARS-1; ch++) + sd->found_char[ch] = sd->found_char[ch+1]; + sd->found_char[MAX_CHARS-1] = -1; + + /* Delete character */ + if(delete_char_sql(cid)<0){ + //can't delete the char + //either SQL error or can't delete by some CONFIG conditions + //del fail + WFIFOHEAD(fd,3); + WFIFOW(fd, 0) = 0x70; + WFIFOB(fd, 2) = 0; + WFIFOSET(fd, 3); + break; + } + /* Char successfully deleted.*/ + WFIFOHEAD(fd,2); + WFIFOW(fd,0) = 0x6f; + WFIFOSET(fd,2); } -#if PACKETVER >= 20120307 - RFIFOSKIP(fd,31); -#else - RFIFOSKIP(fd,37); -#endif - break; - - // delete char - case 0x68: - // 2004-04-19aSakexe+ langtype 12 char deletion packet - case 0x1fb: - if (cmd == 0x68) FIFOSD_CHECK(46); - if (cmd == 0x1fb) FIFOSD_CHECK(56); - { - int cid = RFIFOL(fd,2); - - ShowInfo(CL_RED"Request Char Deletion: "CL_GREEN"%d (%d)"CL_RESET"\n", sd->account_id, cid); - memcpy(email, RFIFOP(fd,6), 40); - RFIFOSKIP(fd,( cmd == 0x68) ? 46 : 56); - - // Check if e-mail is correct - if(strcmpi(email, sd->email) && //email does not matches and - ( - strcmp("a@a.com", sd->email) || //it is not default email, or - (strcmp("a@a.com", email) && strcmp("", email)) //email sent does not matches default - )) { //Fail - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x70; - WFIFOB(fd,2) = 0; // 00 = Incorrect Email address - WFIFOSET(fd,3); + break; + + // client keep-alive packet (every 12 seconds) + // R 0187 <account ID>.l + case 0x187: + if (RFIFOREST(fd) < 6) + return 0; + RFIFOSKIP(fd,6); + break; + // char rename request + // R 08fc <char ID>.l <new name>.24B + case 0x8fc: + FIFOSD_CHECK(30); + { + int i, cid =RFIFOL(fd,2); + char name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1]; + safestrncpy(name, (char *)RFIFOP(fd,6), NAME_LENGTH); + RFIFOSKIP(fd,30); + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + break; + + normalize_name(name,TRIM_CHARS); + SQL->EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( !check_char_name(name,esc_name) ) { + i = 1; + safestrncpy(sd->new_name, name, NAME_LENGTH); + } else + i = 0; + + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x28e; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + } break; - } - // check if this char exists - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - { // Such a character does not exist in the account - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x70; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); + // char rename request + // R 028d <account ID>.l <char ID>.l <new name>.24B + case 0x28d: + FIFOSD_CHECK(34); + { + int i, aid = RFIFOL(fd,2), cid =RFIFOL(fd,6); + char name[NAME_LENGTH]; + char esc_name[NAME_LENGTH*2+1]; + safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH); + RFIFOSKIP(fd,34); + + if( aid != sd->account_id ) + break; + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + break; + + normalize_name(name,TRIM_CHARS); + SQL->EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( !check_char_name(name,esc_name) ) + { + i = 1; + safestrncpy(sd->new_name, name, NAME_LENGTH); + } + else + i = 0; + + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x28e; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + } + break; + //Confirm change name. + // 0x28f <char_id>.L + case 0x28f: + // 0: Sucessfull + // 1: This character's name has already been changed. You cannot change a character's name more than once. + // 2: User information is not correct. + // 3: You have failed to change this character's name. + // 4: Another user is using this character name, so please select another one. + FIFOSD_CHECK(6); + { + int i; + int cid = RFIFOL(fd,2); + RFIFOSKIP(fd,6); + + ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); + if( i == MAX_CHARS ) + break; + i = rename_char_sql(sd, cid); + + WFIFOHEAD(fd, 4); + WFIFOW(fd,0) = 0x290; + WFIFOW(fd,2) = i; + WFIFOSET(fd,4); + } break; - } - // remove char from list and compact it - for(ch = i; ch < MAX_CHARS-1; ch++) - sd->found_char[ch] = sd->found_char[ch+1]; - sd->found_char[MAX_CHARS-1] = -1; - - /* Delete character */ - if(delete_char_sql(cid)<0){ - //can't delete the char - //either SQL error or can't delete by some CONFIG conditions - //del fail - WFIFOHEAD(fd,3); - WFIFOW(fd, 0) = 0x70; - WFIFOB(fd, 2) = 0; - WFIFOSET(fd, 3); + // captcha code request (not implemented) + // R 07e5 <?>.w <aid>.l + case 0x7e5: + WFIFOHEAD(fd,5); + WFIFOW(fd,0) = 0x7e9; + WFIFOW(fd,2) = 5; + WFIFOB(fd,4) = 1; + WFIFOSET(fd,5); + RFIFOSKIP(fd,8); break; - } - /* Char successfully deleted.*/ - WFIFOHEAD(fd,2); - WFIFOW(fd,0) = 0x6f; - WFIFOSET(fd,2); - } - break; - // client keep-alive packet (every 12 seconds) - // R 0187 <account ID>.l - case 0x187: - if (RFIFOREST(fd) < 6) - return 0; - RFIFOSKIP(fd,6); - break; + // captcha code check (not implemented) + // R 07e7 <len>.w <aid>.l <code>.b10 <?>.b14 + case 0x7e7: + WFIFOHEAD(fd,5); + WFIFOW(fd,0) = 0x7e9; + WFIFOW(fd,2) = 5; + WFIFOB(fd,4) = 1; + WFIFOSET(fd,5); + RFIFOSKIP(fd,32); + break; - // char rename request - // R 028d <account ID>.l <char ID>.l <new name>.24B - case 0x28d: - FIFOSD_CHECK(34); - { - int i, aid = RFIFOL(fd,2), cid =RFIFOL(fd,6); - char name[NAME_LENGTH]; - char esc_name[NAME_LENGTH*2+1]; - safestrncpy(name, (char *)RFIFOP(fd,10), NAME_LENGTH); - RFIFOSKIP(fd,34); + // deletion timer request + case 0x827: + FIFOSD_CHECK(6); + char_delete2_req(fd, sd); + RFIFOSKIP(fd,6); + break; - if( aid != sd->account_id ) - break; - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - break; + // deletion accept request + case 0x829: + FIFOSD_CHECK(12); + char_delete2_accept(fd, sd); + RFIFOSKIP(fd,12); + break; - normalize_name(name,TRIM_CHARS); - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( !check_char_name(name,esc_name) ) + // deletion cancel request + case 0x82b: + FIFOSD_CHECK(6); + char_delete2_cancel(fd, sd); + RFIFOSKIP(fd,6); + break; + + // login as map-server + case 0x2af8: + if (RFIFOREST(fd) < 60) + return 0; + { + char* l_user = (char*)RFIFOP(fd,2); + char* l_pass = (char*)RFIFOP(fd,26); + l_user[23] = '\0'; + l_pass[23] = '\0'; + ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 ); + if( runflag != CHARSERVER_ST_RUNNING || + i == ARRAYLENGTH(server) || + strcmp(l_user, userid) != 0 || + strcmp(l_pass, passwd) != 0 ) { - i = 1; - safestrncpy(sd->new_name, name, NAME_LENGTH); + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2af9; + WFIFOB(fd,2) = 3; + WFIFOSET(fd,3); + } else { + WFIFOHEAD(fd,3); + WFIFOW(fd,0) = 0x2af9; + WFIFOB(fd,2) = 0; + WFIFOSET(fd,3); + + server[i].fd = fd; + server[i].ip = ntohl(RFIFOL(fd,54)); + server[i].port = ntohs(RFIFOW(fd,58)); + server[i].users = 0; + memset(server[i].map, 0, sizeof(server[i].map)); + session[fd]->func_parse = parse_frommap; + session[fd]->flag.server = 1; + realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); + char_mapif_init(fd); } - else - i = 0; + socket_datasync(fd, true); - WFIFOHEAD(fd, 4); - WFIFOW(fd,0) = 0x28e; - WFIFOW(fd,2) = i; - WFIFOSET(fd,4); + RFIFOSKIP(fd,60); } + return 0; // avoid processing of followup packets here + + // checks the entered pin + case 0x8b8: + if( RFIFOREST(fd) < 10 ) + return 0; + + if( RFIFOL(fd,2) == sd->account_id ) + pincode->check( fd, sd ); + + RFIFOSKIP(fd,10); break; - //Confirm change name. - // 0x28f <char_id>.L - case 0x28f: - // 0: Sucessfull - // 1: This character's name has already been changed. You cannot change a character's name more than once. - // 2: User information is not correct. - // 3: You have failed to change this character's name. - // 4: Another user is using this character name, so please select another one. - FIFOSD_CHECK(6); - { - int i; - int cid = RFIFOL(fd,2); + + // request for PIN window + case 0x8c5: + if( RFIFOREST(fd) < 6 ) + return 0; + if( RFIFOL(fd,2) == sd->account_id ) + pincode->sendstate( fd, sd, PINCODE_NOTSET ); + RFIFOSKIP(fd,6); - - ARR_FIND( 0, MAX_CHARS, i, sd->found_char[i] == cid ); - if( i == MAX_CHARS ) - break; - i = rename_char_sql(sd, cid); - - WFIFOHEAD(fd, 4); - WFIFOW(fd,0) = 0x290; - WFIFOW(fd,2) = i; - WFIFOSET(fd,4); - } break; - - // captcha code request (not implemented) - // R 07e5 <?>.w <aid>.l - case 0x7e5: - WFIFOHEAD(fd,5); - WFIFOW(fd,0) = 0x7e9; - WFIFOW(fd,2) = 5; - WFIFOB(fd,4) = 1; - WFIFOSET(fd,5); - RFIFOSKIP(fd,8); + + // pincode change request + case 0x8be: + if( RFIFOREST(fd) < 14 ) + return 0; + if( RFIFOL(fd,2) == sd->account_id ) + pincode->change( fd, sd ); + + RFIFOSKIP(fd,14); break; - - // captcha code check (not implemented) - // R 07e7 <len>.w <aid>.l <code>.b10 <?>.b14 - case 0x7e7: - WFIFOHEAD(fd,5); - WFIFOW(fd,0) = 0x7e9; - WFIFOW(fd,2) = 5; - WFIFOB(fd,4) = 1; - WFIFOSET(fd,5); - RFIFOSKIP(fd,32); - break; - - // deletion timer request - case 0x827: - FIFOSD_CHECK(6); - char_delete2_req(fd, sd); - RFIFOSKIP(fd,6); - break; - - // deletion accept request - case 0x829: - FIFOSD_CHECK(12); - char_delete2_accept(fd, sd); - RFIFOSKIP(fd,12); - break; - - // deletion cancel request - case 0x82b: - FIFOSD_CHECK(6); - char_delete2_cancel(fd, sd); - RFIFOSKIP(fd,6); - break; - - // login as map-server - case 0x2af8: - if (RFIFOREST(fd) < 60) + + // activate PIN system and set first PIN + case 0x8ba: + if( RFIFOREST(fd) < 10 ) + return 0; + if( RFIFOL(fd,2) == sd->account_id ) + pincode->setnew( fd, sd ); + RFIFOSKIP(fd,10); + break; + + /* 0x8d4 <from>.W <to>.W <unused>.W (2+2+2+2) */ + case 0x8d4: + if( RFIFOREST(fd) < 8 ) + return 0; + else { + bool ret; + ret = char_slotchange(sd, fd, RFIFOW(fd, 2), RFIFOW(fd, 4)); + WFIFOHEAD(fd, 8); + WFIFOW(fd, 0) = 0x8d5; + WFIFOW(fd, 2) = 8; + WFIFOW(fd, 4) = ret?0:1; + WFIFOW(fd, 6) = 0;/* we enforce it elsewhere, go 0 */ + WFIFOSET(fd, 8); + /* for some stupid reason it requires the char data again (gravity -_-) */ + if( ret ) +#if PACKETVER >= 20130000 + mmo_char_send099d(fd, sd); +#else + mmo_char_send006b(fd, sd); +#endif + + RFIFOSKIP(fd, 8); + } + break; + + // unknown packet received + default: + ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); + set_eof(fd); return 0; - { - char* l_user = (char*)RFIFOP(fd,2); - char* l_pass = (char*)RFIFOP(fd,26); - l_user[23] = '\0'; - l_pass[23] = '\0'; - ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd <= 0 ); - if( runflag != CHARSERVER_ST_RUNNING || - i == ARRAYLENGTH(server) || - strcmp(l_user, userid) != 0 || - strcmp(l_pass, passwd) != 0 ) - { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x2af9; - WFIFOB(fd,2) = 3; - WFIFOSET(fd,3); - } else { - WFIFOHEAD(fd,3); - WFIFOW(fd,0) = 0x2af9; - WFIFOB(fd,2) = 0; - WFIFOSET(fd,3); - - server[i].fd = fd; - server[i].ip = ntohl(RFIFOL(fd,54)); - server[i].port = ntohs(RFIFOW(fd,58)); - server[i].users = 0; - memset(server[i].map, 0, sizeof(server[i].map)); - session[fd]->func_parse = parse_frommap; - session[fd]->flag.server = 1; - realloc_fifo(fd, FIFOSIZE_SERVERLINK, FIFOSIZE_SERVERLINK); - char_mapif_init(fd); } - - RFIFOSKIP(fd,60); - } - return 0; // avoid processing of followup packets here - - // unknown packet received - default: - ShowError("parse_char: Received unknown packet "CL_WHITE"0x%x"CL_RESET" from ip '"CL_WHITE"%s"CL_RESET"'! Disconnecting!\n", RFIFOW(fd,0), ip2str(ipl, NULL)); - set_eof(fd); - return 0; - } } RFIFOFLUSH(fd); return 0; } -// Console Command Parser [Wizputer] -int parse_console(const char* command) -{ - ShowNotice("Console command: %s\n", command); - - if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 ) - runflag = 0; - else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 ) - ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n"); - else if( strcmpi("help", command) == 0 ) - { - ShowInfo("To shutdown the server:\n"); - ShowInfo(" 'shutdown|exit|quit|end'\n"); - ShowInfo("To know if server is alive:\n"); - ShowInfo(" 'alive|status'\n"); - } - - return 0; -} - int mapif_sendall(unsigned char *buf, unsigned int len) { int i, c; @@ -4252,7 +4450,7 @@ int broadcast_user_count(int tid, unsigned int tick, int id, intptr_t data) */ static int send_accounts_tologin_sub(DBKey key, DBData *data, va_list ap) { - struct online_char_data* character = db_data2ptr(data); + struct online_char_data* character = DB->data2ptr(data); int* i = va_arg(ap, int*); if(character->server > -1) @@ -4334,7 +4532,7 @@ static int chardb_waiting_disconnect(int tid, unsigned int tick, int id, intptr_ */ static int online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) { - struct online_char_data *character= db_data2ptr(data); + struct online_char_data *character= DB->data2ptr(data); if (character->fd != -1) return 0; //Character still connected if (character->server == -2) //Unknown server.. set them offline @@ -4488,7 +4686,17 @@ void sql_config_read(const char* cfgName) fclose(fp); ShowInfo("Done reading %s.\n", cfgName); } - +void char_config_dispatch(char *w1, char *w2) { + bool (*dispatch_to[]) (char *w1, char *w2) = { + /* as many as it needs */ + pincode->config_read + }; + int i, len = ARRAYLENGTH(dispatch_to); + for(i = 0; i < len; i++) { + if( (*dispatch_to[i])(w1,w2) ) + break;/* we found who this belongs to, can stop */ + } +} int char_config_read(const char* cfgName) { char line[1024], w1[1024], w2[1024]; @@ -4527,25 +4735,25 @@ int char_config_read(const char* cfgName) safestrncpy(wisp_server_name, w2, sizeof(wisp_server_name)); } } else if (strcmpi(w1, "login_ip") == 0) { - char ip_str[16]; login_ip = host2ip(w2); if (login_ip) { + char ip_str[16]; safestrncpy(login_ip_str, w2, sizeof(login_ip_str)); ShowStatus("Login server IP address : %s -> %s\n", w2, ip2str(login_ip, ip_str)); } } else if (strcmpi(w1, "login_port") == 0) { login_port = atoi(w2); } else if (strcmpi(w1, "char_ip") == 0) { - char ip_str[16]; char_ip = host2ip(w2); - if (char_ip){ + if (char_ip) { + char ip_str[16]; safestrncpy(char_ip_str, w2, sizeof(char_ip_str)); ShowStatus("Character server IP address : %s -> %s\n", w2, ip2str(char_ip, ip_str)); } } else if (strcmpi(w1, "bind_ip") == 0) { - char ip_str[16]; bind_ip = host2ip(w2); if (bind_ip) { + char ip_str[16]; safestrncpy(bind_ip_str, w2, sizeof(bind_ip_str)); ShowStatus("Character server binding IP address : %s -> %s\n", w2, ip2str(bind_ip, ip_str)); } @@ -4559,8 +4767,8 @@ int char_config_read(const char* cfgName) char_new_display = atoi(w2); } else if (strcmpi(w1, "max_connect_user") == 0) { max_connect_user = atoi(w2); - if (max_connect_user < 0) - max_connect_user = 0; // unlimited online players + if (max_connect_user < -1) + max_connect_user = -1; // unlimited online players } else if(strcmpi(w1, "gm_allow_group") == 0) { gm_allow_group = atoi(w2); } else if (strcmpi(w1, "autosave_time") == 0) { @@ -4579,18 +4787,29 @@ int char_config_read(const char* cfgName) ShowError("Specified start_point %s not found in map-index cache.\n", map); start_point.x = x; start_point.y = y; + } else if (strcmpi(w1, "start_items") == 0) { + int i; + char *split, *split2; + + i = 0; + split = strtok(w2, ","); + while (split != NULL && i < MAX_START_ITEMS*2) { + split2 = split; + split = strtok(NULL, ","); + start_items[i] = atoi(split2); + if (start_items[i] < 0) + start_items[i] = 0; + ++i; + } + + if (i%2) { //we know it must be a even number + ShowError("Specified 'start_items' is missing a parameter. Removing '%d'.\n", start_items[i - 1]); + start_items[i - 1] = 0; + } } else if (strcmpi(w1, "start_zeny") == 0) { start_zeny = atoi(w2); if (start_zeny < 0) start_zeny = 0; - } else if (strcmpi(w1, "start_weapon") == 0) { - start_weapon = atoi(w2); - if (start_weapon < 0) - start_weapon = 0; - } else if (strcmpi(w1, "start_armor") == 0) { - start_armor = atoi(w2); - if (start_armor < 0) - start_armor = 0; } else if(strcmpi(w1,"log_char")==0) { //log char or not [devil] log_char = atoi(w2); } else if (strcmpi(w1, "unknown_char_name") == 0) { @@ -4602,21 +4821,12 @@ int char_config_read(const char* cfgName) char_name_option = atoi(w2); } else if (strcmpi(w1, "char_name_letters") == 0) { safestrncpy(char_name_letters, w2, sizeof(char_name_letters)); - } else if (strcmpi(w1, "chars_per_account") == 0) { //maxchars per account [Sirius] - char_per_account = atoi(w2); - if( char_per_account == 0 || char_per_account > MAX_CHARS ) { - if( char_per_account > MAX_CHARS ) - ShowWarning("Max chars per account '%d' exceeded limit. Defaulting to '%d'.\n", char_per_account, MAX_CHARS); - char_per_account = MAX_CHARS; - } } else if (strcmpi(w1, "char_del_level") == 0) { //disable/enable char deletion by its level condition [Lupus] char_del_level = atoi(w2); } else if (strcmpi(w1, "char_del_delay") == 0) { char_del_delay = atoi(w2); } else if(strcmpi(w1,"db_path")==0) { safestrncpy(db_path, w2, sizeof(db_path)); - } else if (strcmpi(w1, "console") == 0) { - console = config_switch(w2); } else if (strcmpi(w1, "fame_list_alchemist") == 0) { fame_list_size_chemist = atoi(w2); if (fame_list_size_chemist > MAX_FAME_LIST) { @@ -4639,7 +4849,8 @@ int char_config_read(const char* cfgName) guild_exp_rate = atoi(w2); } else if (strcmpi(w1, "import") == 0) { char_config_read(w2); - } + } else + char_config_dispatch(w1,w2); } fclose(fp); @@ -4661,7 +4872,7 @@ void do_final(void) do_final_mapif(); do_final_loginif(); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s`", ragsrvinfo_db) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s`", ragsrvinfo_db) ) Sql_ShowDebug(sql_handle); char_db_->destroy(char_db_, NULL); @@ -4674,7 +4885,7 @@ void do_final(void) char_fd = -1; } - Sql_Free(sql_handle); + SQL->Free(sql_handle); mapindex_final(); ShowStatus("Finished.\n"); @@ -4688,9 +4899,8 @@ void do_abort(void) { } -void set_server_type(void) -{ - SERVER_TYPE = ATHENA_SERVER_CHAR; +void set_server_type(void) { + SERVER_TYPE = SERVER_TYPE_CHAR; } @@ -4712,12 +4922,14 @@ void do_shutdown(void) } -int do_init(int argc, char **argv) -{ +int do_init(int argc, char **argv) { + memset(&skillid2idx, 0, sizeof(skillid2idx)); //Read map indexes mapindex_init(); start_point.map = mapindex_name2id("new_zone01"); + pincode_defaults(); + char_config_read((argc < 2) ? CHAR_CONF_NAME : argv[1]); char_lan_config_read((argc > 3) ? argv[3] : LAN_CONF_NAME); sql_config_read(SQL_CONF_NAME); @@ -4725,9 +4937,9 @@ int do_init(int argc, char **argv) if (strcmp(userid, "s1")==0 && strcmp(passwd, "p1")==0) { ShowWarning("Using the default user/password s1/p1 is NOT RECOMMENDED.\n"); ShowNotice("Please edit your 'login' table to create a proper inter-server user/password (gender 'S')\n"); - ShowNotice("And then change the user/password to use in conf/char_athena.conf (or conf/import/char_conf.txt)\n"); + ShowNotice("And then change the user/password to use in conf/char-server.conf (or conf/import/char_conf.txt)\n"); } - + inter_init_sql((argc > 2) ? argv[2] : inter_cfgName); // inter server configuration auth_db = idb_alloc(DB_OPT_RELEASE_DATA); @@ -4735,8 +4947,7 @@ int do_init(int argc, char **argv) mmo_char_sql_init(); char_read_fame_list(); //Read fame lists. - if ((naddr_ != 0) && (!login_ip || !char_ip)) - { + if ((naddr_ != 0) && (!login_ip || !char_ip)) { char ip_str[16]; ip2str(addr_[0], ip_str); @@ -4768,28 +4979,30 @@ int do_init(int argc, char **argv) add_timer_func_list(online_data_cleanup, "online_data_cleanup"); add_timer_interval(gettick() + 1000, online_data_cleanup, 0, 0, 600 * 1000); - if( console ) - { - //##TODO invoke a CONSOLE_START plugin event - } - //Cleaning the tables for NULL entrys @ startup [Sirius] //Chardb clean - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '0'", char_db) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = '0'", char_db) ) Sql_ShowDebug(sql_handle); //guilddb clean - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_lv` = '0' AND `max_member` = '0' AND `exp` = '0' AND `next_exp` = '0' AND `average_lv` = '0'", guild_db) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_lv` = '0' AND `max_member` = '0' AND `exp` = '0' AND `next_exp` = '0' AND `average_lv` = '0'", guild_db) ) Sql_ShowDebug(sql_handle); //guildmemberdb clean - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '0' AND `account_id` = '0' AND `char_id` = '0'", guild_member_db) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '0' AND `account_id` = '0' AND `char_id` = '0'", guild_member_db) ) Sql_ShowDebug(sql_handle); set_defaultparse(parse_char); - char_fd = make_listen_bind(bind_ip, char_port); + + if( (char_fd = make_listen_bind(bind_ip,char_port)) == -1 ) { + ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",char_port); + exit(EXIT_FAILURE); + } + + Sql_HerculesUpdateCheck(sql_handle); + ShowStatus("The char-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %d).\n\n", char_port); - + if( runflag != CORE_ST_STOP ) { shutdown_callback = do_shutdown; diff --git a/src/char/char.h b/src/char/char.h index e16350cb3..b48ea359c 100644 --- a/src/char/char.h +++ b/src/char/char.h @@ -6,9 +6,9 @@ #include "../config/core.h" #include "../common/core.h" // CORE_ST_LAST +#include "../common/db.h" -enum E_CHARSERVER_ST -{ +enum E_CHARSERVER_ST { CHARSERVER_ST_RUNNING = CORE_ST_LAST, CHARSERVER_ST_SHUTDOWN, CHARSERVER_ST_LAST @@ -16,6 +16,35 @@ enum E_CHARSERVER_ST struct mmo_charstatus; +struct char_session_data { + bool auth; // whether the session is authed or not + int account_id, login_id1, login_id2, sex; + int found_char[MAX_CHARS]; // ids of chars on this account + char email[40]; // e-mail (default: a@a.com) by [Yor] + time_t expiration_time; // # of seconds 1/1/1970 (timestamp): Validity limit of the account (0 = unlimited) + int group_id; // permission + uint8 char_slots; + uint32 version; + uint8 clienttype; + char pincode[4+1]; + uint32 pincode_seed; + uint16 pincode_try; + uint32 pincode_change; + char new_name[NAME_LENGTH]; + char birthdate[10+1]; // YYYY-MM-DD +}; + +struct online_char_data { + int account_id; + int char_id; + int fd; + int waiting_disconnect; + short server; // -2: unknown server, -1: not connected, 0+: id of server + int pincode_enable; +}; + +DBMap* online_char_db; // int account_id -> struct online_char_data* + #define MAX_MAP_SERVERS 30 #define DEFAULT_AUTOSAVE_INTERVAL 300*1000 @@ -39,7 +68,7 @@ int char_family(int pl1,int pl2,int pl3); int request_accreg2(int account_id, int char_id); int save_accreg2(unsigned char* buf, int len); - +int login_fd; extern int char_name_option; extern char char_name_letters[]; extern bool char_gm_read; diff --git a/src/char/int_auction.c b/src/char/int_auction.c index 34aed5bf7..977638aad 100644 --- a/src/char/int_auction.c +++ b/src/char/int_auction.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/malloc.h" @@ -48,15 +49,15 @@ void auction_save(struct auction_data *auction) if( !auction ) return; - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `seller_id` = '%d', `seller_name` = ?, `buyer_id` = '%d', `buyer_name` = ?, `price` = '%d', `buynow` = '%d', `hours` = '%d', `timestamp` = '%lu', `nameid` = '%d', `item_name` = ?, `type` = '%d', `refine` = '%d', `attribute` = '%d'", + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "UPDATE `%s` SET `seller_id` = '%d', `seller_name` = ?, `buyer_id` = '%d', `buyer_name` = ?, `price` = '%d', `buynow` = '%d', `hours` = '%d', `timestamp` = '%lu', `nameid` = '%d', `item_name` = ?, `type` = '%d', `refine` = '%d', `attribute` = '%d'", auction_db, auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute); for( j = 0; j < MAX_SLOTS; j++ ) - StringBuf_Printf(&buf, ", `card%d` = '%d'", j, auction->item.card[j]); - StringBuf_Printf(&buf, " WHERE `auction_id` = '%d'", auction->auction_id); + StrBuf->Printf(&buf, ", `card%d` = '%d'", j, auction->item.card[j]); + StrBuf->Printf(&buf, " WHERE `auction_id` = '%d'", auction->auction_id); stmt = SqlStmt_Malloc(sql_handle); - if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StrBuf->Value(&buf)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, auction->seller_name, strnlen(auction->seller_name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, auction->buyer_name, strnlen(auction->buyer_name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, auction->item_name, strnlen(auction->item_name, ITEM_NAME_LENGTH)) @@ -66,7 +67,7 @@ void auction_save(struct auction_data *auction) } SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); } unsigned int auction_create(struct auction_data *auction) @@ -80,22 +81,22 @@ unsigned int auction_create(struct auction_data *auction) auction->timestamp = time(NULL) + (auction->hours * 3600); - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", auction_db); + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s` (`seller_id`,`seller_name`,`buyer_id`,`buyer_name`,`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`", auction_db); for( j = 0; j < MAX_SLOTS; j++ ) - StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, ") VALUES ('%d',?,'%d',?,'%d','%d','%d','%lu','%d',?,'%d','%d','%d','%"PRIu64"'", + StrBuf->Printf(&buf, ",`card%d`", j); + StrBuf->Printf(&buf, ") VALUES ('%d',?,'%d',?,'%d','%d','%d','%lu','%d',?,'%d','%d','%d','%"PRIu64"'", auction->seller_id, auction->buyer_id, auction->price, auction->buynow, auction->hours, (unsigned long)auction->timestamp, auction->item.nameid, auction->type, auction->item.refine, auction->item.attribute, auction->item.unique_id); for( j = 0; j < MAX_SLOTS; j++ ) - StringBuf_Printf(&buf, ",'%d'", auction->item.card[j]); - StringBuf_AppendStr(&buf, ")"); + StrBuf->Printf(&buf, ",'%d'", auction->item.card[j]); + StrBuf->AppendStr(&buf, ")"); //Unique Non Stackable Item ID updateLastUid(auction->item.unique_id); dbUpdateUid(sql_handle); stmt = SqlStmt_Malloc(sql_handle); - if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StrBuf->Value(&buf)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, auction->seller_name, strnlen(auction->seller_name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, auction->buyer_name, strnlen(auction->buyer_name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, auction->item_name, strnlen(auction->item_name, ITEM_NAME_LENGTH)) @@ -123,7 +124,7 @@ unsigned int auction_create(struct auction_data *auction) } SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return auction->auction_id; } @@ -165,7 +166,7 @@ void auction_delete(struct auction_data *auction) { unsigned int auction_id = auction->auction_id; - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", auction_db, auction_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `auction_id` = '%d'", auction_db, auction_id) ) Sql_ShowDebug(sql_handle); if( auction->auction_end_timer != INVALID_TIMER ) @@ -184,39 +185,39 @@ void inter_auctions_fromsql(void) unsigned int tick = gettick(), endtick; time_t now = time(NULL); - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `auction_id`,`seller_id`,`seller_name`,`buyer_id`,`buyer_name`," + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `auction_id`,`seller_id`,`seller_name`,`buyer_id`,`buyer_name`," "`price`,`buynow`,`hours`,`timestamp`,`nameid`,`item_name`,`type`,`refine`,`attribute`,`unique_id`"); for( i = 0; i < MAX_SLOTS; i++ ) - StringBuf_Printf(&buf, ",`card%d`", i); - StringBuf_Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db); + StrBuf->Printf(&buf, ",`card%d`", i); + StrBuf->Printf(&buf, " FROM `%s` ORDER BY `auction_id` DESC", auction_db); - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf)) ) Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); - while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + while( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { CREATE(auction, struct auction_data, 1); - Sql_GetData(sql_handle, 0, &data, NULL); auction->auction_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); auction->seller_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(auction->seller_name, data, NAME_LENGTH); - Sql_GetData(sql_handle, 3, &data, NULL); auction->buyer_id = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(auction->buyer_name, data, NAME_LENGTH); - Sql_GetData(sql_handle, 5, &data, NULL); auction->price = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); auction->buynow = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); auction->hours = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); auction->timestamp = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); auction->auction_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); auction->seller_id = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); safestrncpy(auction->seller_name, data, NAME_LENGTH); + SQL->GetData(sql_handle, 3, &data, NULL); auction->buyer_id = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); safestrncpy(auction->buyer_name, data, NAME_LENGTH); + SQL->GetData(sql_handle, 5, &data, NULL); auction->price = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); auction->buynow = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); auction->hours = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); auction->timestamp = atoi(data); item = &auction->item; - Sql_GetData(sql_handle, 9, &data, NULL); item->nameid = atoi(data); - Sql_GetData(sql_handle,10, &data, NULL); safestrncpy(auction->item_name, data, ITEM_NAME_LENGTH); - Sql_GetData(sql_handle,11, &data, NULL); auction->type = atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); item->nameid = atoi(data); + SQL->GetData(sql_handle,10, &data, NULL); safestrncpy(auction->item_name, data, ITEM_NAME_LENGTH); + SQL->GetData(sql_handle,11, &data, NULL); auction->type = atoi(data); - Sql_GetData(sql_handle,12, &data, NULL); item->refine = atoi(data); - Sql_GetData(sql_handle,13, &data, NULL); item->attribute = atoi(data); - Sql_GetData(sql_handle,14, &data, NULL); item->unique_id = strtoull(data, NULL, 10); + SQL->GetData(sql_handle,12, &data, NULL); item->refine = atoi(data); + SQL->GetData(sql_handle,13, &data, NULL); item->attribute = atoi(data); + SQL->GetData(sql_handle,14, &data, NULL); item->unique_id = strtoull(data, NULL, 10); item->identify = 1; item->amount = 1; @@ -224,7 +225,7 @@ void inter_auctions_fromsql(void) for( i = 0; i < MAX_SLOTS; i++ ) { - Sql_GetData(sql_handle, 14 + i, &data, NULL); + SQL->GetData(sql_handle, 15 + i, &data, NULL); item->card[i] = atoi(data); } @@ -237,7 +238,7 @@ void inter_auctions_fromsql(void) idb_put(auction_db_, auction->auction_id, auction); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } static void mapif_Auction_sendlist(int fd, int char_id, short count, short pages, unsigned char *buf) diff --git a/src/char/int_elemental.c b/src/char/int_elemental.c index 3c2f6672d..53a63a212 100644 --- a/src/char/int_elemental.c +++ b/src/char/int_elemental.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/malloc.h" @@ -19,7 +20,7 @@ bool mapif_elemental_save(struct s_elemental* ele) { bool flag = true; if( ele->elemental_id == 0 ) { // Create new DB entry - if( SQL_ERROR == Sql_Query(sql_handle, + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `elemental` (`char_id`,`class`,`mode`,`hp`,`sp`,`max_hp`,`max_sp`,`atk1`,`atk2`,`matk`,`aspd`,`def`,`mdef`,`flee`,`hit`,`life_time`)" "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%d','%u')", ele->char_id, ele->class_, ele->mode, ele->hp, ele->sp, ele->max_hp, ele->max_sp, ele->atk, ele->atk2, ele->matk, ele->amotion, ele->def, ele->mdef, ele->flee, ele->hit, ele->life_time) ) @@ -28,8 +29,8 @@ bool mapif_elemental_save(struct s_elemental* ele) { flag = false; } else - ele->elemental_id = (int)Sql_LastInsertId(sql_handle); - } else if( SQL_ERROR == Sql_Query(sql_handle, + ele->elemental_id = (int)SQL->LastInsertId(sql_handle); + } else if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `elemental` SET `char_id` = '%d', `class` = '%d', `mode` = '%d', `hp` = '%d', `sp` = '%d'," "`max_hp` = '%d', `max_sp` = '%d', `atk1` = '%d', `atk2` = '%d', `matk` = '%d', `aspd` = '%d', `def` = '%d'," "`mdef` = '%d', `flee` = '%d', `hit` = '%d', `life_time` = '%u' WHERE `ele_id` = '%d'", @@ -49,34 +50,34 @@ bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) { ele->elemental_id = ele_id; ele->char_id = char_id; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `mode`, `hp`, `sp`, `max_hp`, `max_sp`, `atk1`, `atk2`, `matk`, `aspd`," + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `class`, `mode`, `hp`, `sp`, `max_hp`, `max_sp`, `atk1`, `atk2`, `matk`, `aspd`," "`def`, `mdef`, `flee`, `hit`, `life_time` FROM `elemental` WHERE `ele_id` = '%d' AND `char_id` = '%d'", ele_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) { - Sql_FreeResult(sql_handle); + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { + SQL->FreeResult(sql_handle); return false; } - Sql_GetData(sql_handle, 0, &data, NULL); ele->class_ = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); ele->mode = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); ele->hp = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); ele->sp = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); ele->max_hp = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); ele->max_sp = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); ele->atk = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); ele->atk2 = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); ele->matk = atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); ele->amotion = atoi(data); - Sql_GetData(sql_handle, 10, &data, NULL); ele->def = atoi(data); - Sql_GetData(sql_handle, 11, &data, NULL); ele->mdef = atoi(data); - Sql_GetData(sql_handle, 12, &data, NULL); ele->flee = atoi(data); - Sql_GetData(sql_handle, 13, &data, NULL); ele->hit = atoi(data); - Sql_GetData(sql_handle, 14, &data, NULL); ele->life_time = atoi(data); - Sql_FreeResult(sql_handle); + SQL->GetData(sql_handle, 0, &data, NULL); ele->class_ = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); ele->mode = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); ele->hp = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); ele->sp = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); ele->max_hp = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); ele->max_sp = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); ele->atk = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); ele->atk2 = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); ele->matk = atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); ele->amotion = atoi(data); + SQL->GetData(sql_handle, 10, &data, NULL); ele->def = atoi(data); + SQL->GetData(sql_handle, 11, &data, NULL); ele->mdef = atoi(data); + SQL->GetData(sql_handle, 12, &data, NULL); ele->flee = atoi(data); + SQL->GetData(sql_handle, 13, &data, NULL); ele->hit = atoi(data); + SQL->GetData(sql_handle, 14, &data, NULL); ele->life_time = atoi(data); + SQL->FreeResult(sql_handle); if( save_log ) ShowInfo("Elemental loaded (%d - %d).\n", ele->elemental_id, ele->char_id); @@ -84,7 +85,7 @@ bool mapif_elemental_load(int ele_id, int char_id, struct s_elemental *ele) { } bool mapif_elemental_delete(int ele_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `elemental` WHERE `ele_id` = '%d'", ele_id) ) { + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `elemental` WHERE `ele_id` = '%d'", ele_id) ) { Sql_ShowDebug(sql_handle); return false; } diff --git a/src/char/int_guild.c b/src/char/int_guild.c index 9090bc007..e1e012725 100644 --- a/src/char/int_guild.c +++ b/src/char/int_guild.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/mmo.h" @@ -56,7 +57,7 @@ static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data) if( last_id == 0 ) //Save the first guild in the list. state = 1; - for( g = db_data2ptr(iter->first(iter, &key)); dbi_exists(iter); g = db_data2ptr(iter->next(iter, &key)) ) + for( g = DB->data2ptr(iter->first(iter, &key)); dbi_exists(iter); g = DB->data2ptr(iter->next(iter, &key)) ) { if( state == 0 && g->guild_id == last_id ) state++; //Save next guild in the list. @@ -91,9 +92,9 @@ static int guild_save_timer(int tid, unsigned int tick, int id, intptr_t data) int inter_guild_removemember_tosql(int account_id, int char_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", guild_member_db, account_id, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE from `%s` where `account_id` = '%d' and `char_id` = '%d'", guild_member_db, account_id, char_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '0' WHERE `char_id` = '%d'", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `guild_id` = '0' WHERE `char_id` = '%d'", char_db, char_id) ) Sql_ShowDebug(sql_handle); return 0; } @@ -128,8 +129,8 @@ int inter_guild_tosql(struct guild *g,int flag) ShowInfo("Save guild request ("CL_BOLD"%d"CL_RESET" - flag 0x%x).",g->guild_id, flag); #endif - Sql_EscapeStringLen(sql_handle, esc_name, g->name, strnlen(g->name, NAME_LENGTH)); - Sql_EscapeStringLen(sql_handle, esc_master, g->master, strnlen(g->master, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_name, g->name, strnlen(g->name, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_master, g->master, strnlen(g->master, NAME_LENGTH)); *t_info = '\0'; // Insert a new guild the guild @@ -138,7 +139,7 @@ int inter_guild_tosql(struct guild *g,int flag) strcat(t_info, " guild_create"); // Create a new guild - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` " "(`name`,`master`,`guild_lv`,`max_member`,`average_lv`,`char_id`) " "VALUES ('%s', '%s', '%d', '%d', '%d', '%d')", guild_db, esc_name, esc_master, g->guild_lv, g->max_member, g->average_lv, g->member[0].char_id) ) @@ -149,7 +150,7 @@ int inter_guild_tosql(struct guild *g,int flag) } else { - g->guild_id = (int)Sql_LastInsertId(sql_handle); + g->guild_id = (int)SQL->LastInsertId(sql_handle); new_guild = 1; } } @@ -160,8 +161,8 @@ int inter_guild_tosql(struct guild *g,int flag) StringBuf buf; bool add_comma = false; - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET ", guild_db); + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "UPDATE `%s` SET ", guild_db); if (flag & GS_EMBLEM) { @@ -176,26 +177,26 @@ int inter_guild_tosql(struct guild *g,int flag) *pData++ = dataToHex[g->emblem_data[i] & 0x0F]; } *pData = 0; - StringBuf_Printf(&buf, "`emblem_len`=%d, `emblem_id`=%d, `emblem_data`='%s'", g->emblem_len, g->emblem_id, emblem_data); + StrBuf->Printf(&buf, "`emblem_len`=%d, `emblem_id`=%d, `emblem_data`='%s'", g->emblem_len, g->emblem_id, emblem_data); add_comma = true; } if (flag & GS_BASIC) { strcat(t_info, " basic"); if( add_comma ) - StringBuf_AppendStr(&buf, ", "); + StrBuf->AppendStr(&buf, ", "); else add_comma = true; - StringBuf_Printf(&buf, "`name`='%s', `master`='%s', `char_id`=%d", esc_name, esc_master, g->member[0].char_id); + StrBuf->Printf(&buf, "`name`='%s', `master`='%s', `char_id`=%d", esc_name, esc_master, g->member[0].char_id); } if (flag & GS_CONNECT) { strcat(t_info, " connect"); if( add_comma ) - StringBuf_AppendStr(&buf, ", "); + StrBuf->AppendStr(&buf, ", "); else add_comma = true; - StringBuf_Printf(&buf, "`connect_member`=%d, `average_lv`=%d", g->connect_member, g->average_lv); + StrBuf->Printf(&buf, "`connect_member`=%d, `average_lv`=%d", g->connect_member, g->average_lv); } if (flag & GS_MES) { @@ -204,26 +205,26 @@ int inter_guild_tosql(struct guild *g,int flag) strcat(t_info, " mes"); if( add_comma ) - StringBuf_AppendStr(&buf, ", "); + StrBuf->AppendStr(&buf, ", "); else add_comma = true; - Sql_EscapeStringLen(sql_handle, esc_mes1, g->mes1, strnlen(g->mes1, sizeof(g->mes1))); - Sql_EscapeStringLen(sql_handle, esc_mes2, g->mes2, strnlen(g->mes2, sizeof(g->mes2))); - StringBuf_Printf(&buf, "`mes1`='%s', `mes2`='%s'", esc_mes1, esc_mes2); + SQL->EscapeStringLen(sql_handle, esc_mes1, g->mes1, strnlen(g->mes1, sizeof(g->mes1))); + SQL->EscapeStringLen(sql_handle, esc_mes2, g->mes2, strnlen(g->mes2, sizeof(g->mes2))); + StrBuf->Printf(&buf, "`mes1`='%s', `mes2`='%s'", esc_mes1, esc_mes2); } if (flag & GS_LEVEL) { strcat(t_info, " level"); if( add_comma ) - StringBuf_AppendStr(&buf, ", "); - else - add_comma = true; - StringBuf_Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%"PRIu64", `next_exp`=%u, `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member); + StrBuf->AppendStr(&buf, ", "); + //else //last condition using add_coma setting + // add_comma = true; + StrBuf->Printf(&buf, "`guild_lv`=%d, `skill_point`=%d, `exp`=%"PRIu64", `next_exp`=%u, `max_member`=%d", g->guild_lv, g->skill_point, g->exp, g->next_exp, g->max_member); } - StringBuf_Printf(&buf, " WHERE `guild_id`=%d", g->guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "%s", StringBuf_Value(&buf)) ) + StrBuf->Printf(&buf, " WHERE `guild_id`=%d", g->guild_id); + if( SQL_ERROR == SQL->Query(sql_handle, "%s", StrBuf->Value(&buf)) ) Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); } if (flag&GS_MEMBER) @@ -238,8 +239,8 @@ int inter_guild_tosql(struct guild *g,int flag) continue; if(m->account_id) { //Since nothing references guild member table as foreign keys, it's safe to use REPLACE INTO - Sql_EscapeStringLen(sql_handle, esc_name, m->name, strnlen(m->name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`) " + SQL->EscapeStringLen(sql_handle, esc_name, m->name, strnlen(m->name, NAME_LENGTH)); + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name`) " "VALUES ('%d','%d','%d','%d','%d','%d','%d','%d','%"PRIu64"','%d','%d','%d','%s')", guild_member_db, g->guild_id, m->account_id, m->char_id, m->hair, m->hair_color, m->gender, @@ -247,7 +248,7 @@ int inter_guild_tosql(struct guild *g,int flag) Sql_ShowDebug(sql_handle); if (m->modified&GS_MEMBER_NEW || new_guild == 1) { - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id` = '%d' WHERE `char_id` = '%d'", + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `guild_id` = '%d' WHERE `char_id` = '%d'", char_db, g->guild_id, m->char_id) ) Sql_ShowDebug(sql_handle); } @@ -263,8 +264,8 @@ int inter_guild_tosql(struct guild *g,int flag) struct guild_position *p = &g->position[i]; if (!p->modified) continue; - Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ('%d','%d','%s','%d','%d')", + SQL->EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`position`,`name`,`mode`,`exp_mode`) VALUES ('%d','%d','%s','%d','%d')", guild_position_db, g->guild_id, i, esc_name, p->mode, p->exp_mode) ) Sql_ShowDebug(sql_handle); p->modified = GS_POSITION_UNMODIFIED; @@ -277,8 +278,8 @@ int inter_guild_tosql(struct guild *g,int flag) // NOTE: no need to do it on both sides since both guilds in memory had // their info changed, not to mention this would also mess up oppositions! // [Skotlex] - //if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d'", guild_alliance_db, g->guild_id, g->guild_id) ) - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, g->guild_id) ) + //if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d' OR `alliance_id`='%d'", guild_alliance_db, g->guild_id, g->guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, g->guild_id) ) { Sql_ShowDebug(sql_handle); } @@ -290,8 +291,8 @@ int inter_guild_tosql(struct guild *g,int flag) struct guild_alliance *a=&g->alliance[i]; if(a->guild_id>0) { - Sql_EscapeStringLen(sql_handle, esc_name, a->name, strnlen(a->name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) " + SQL->EscapeStringLen(sql_handle, esc_name, a->name, strnlen(a->name, NAME_LENGTH)); + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`opposition`,`alliance_id`,`name`) " "VALUES ('%d','%d','%d','%s')", guild_alliance_db, g->guild_id, a->opposition, a->guild_id, esc_name) ) Sql_ShowDebug(sql_handle); @@ -308,9 +309,9 @@ int inter_guild_tosql(struct guild *g,int flag) if(e->account_id>0){ char esc_mes[sizeof(e->mes)*2+1]; - Sql_EscapeStringLen(sql_handle, esc_name, e->name, strnlen(e->name, NAME_LENGTH)); - Sql_EscapeStringLen(sql_handle, esc_mes, e->mes, strnlen(e->mes, sizeof(e->mes))); - if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`name`,`mes`) " + SQL->EscapeStringLen(sql_handle, esc_name, e->name, strnlen(e->name, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_mes, e->mes, strnlen(e->mes, sizeof(e->mes))); + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`account_id`,`name`,`mes`) " "VALUES ('%d','%d','%s','%s')", guild_expulsion_db, g->guild_id, e->account_id, esc_name, esc_mes) ) Sql_ShowDebug(sql_handle); } @@ -322,7 +323,7 @@ int inter_guild_tosql(struct guild *g,int flag) //printf("- Insert guild %d to guild_skill\n",g->guild_id); for(i=0;i<MAX_GUILDSKILL;i++){ if (g->skill[i].id>0 && g->skill[i].lv>0){ - if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`id`,`lv`) VALUES ('%d','%d','%d')", + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`guild_id`,`id`,`lv`) VALUES ('%d','%d','%d')", guild_skill_db, g->guild_id, g->skill[i].id, g->skill[i].lv) ) Sql_ShowDebug(sql_handle); } @@ -354,38 +355,38 @@ struct guild * inter_guild_fromsql(int guild_id) ShowInfo("Guild load request (%d)...\n", guild_id); #endif - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT g.`name`,c.`name`,g.`guild_lv`,g.`connect_member`,g.`max_member`,g.`average_lv`,g.`exp`,g.`next_exp`,g.`skill_point`,g.`mes1`,g.`mes2`,g.`emblem_len`,g.`emblem_id`,g.`emblem_data` " + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT g.`name`,c.`name`,g.`guild_lv`,g.`connect_member`,g.`max_member`,g.`average_lv`,g.`exp`,g.`next_exp`,g.`skill_point`,g.`mes1`,g.`mes2`,g.`emblem_len`,g.`emblem_id`,g.`emblem_data` " "FROM `%s` g LEFT JOIN `%s` c ON c.`char_id` = g.`char_id` WHERE g.`guild_id`='%d'", guild_db, char_db, guild_id) ) { Sql_ShowDebug(sql_handle); return NULL; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) return NULL;// Guild does not exists. CREATE(g, struct guild, 1); g->guild_id = guild_id; - Sql_GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 2, &data, NULL); g->guild_lv = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); g->connect_member = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); g->max_member = atoi(data); + SQL->GetData(sql_handle, 0, &data, &len); memcpy(g->name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 1, &data, &len); memcpy(g->master, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 2, &data, NULL); g->guild_lv = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); g->connect_member = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); g->max_member = atoi(data); if( g->max_member > MAX_GUILD ) { // Fix reduction of MAX_GUILD [PoW] ShowWarning("Guild %d:%s specifies higher capacity (%d) than MAX_GUILD (%d)\n", guild_id, g->name, g->max_member, MAX_GUILD); g->max_member = MAX_GUILD; } - Sql_GetData(sql_handle, 5, &data, NULL); g->average_lv = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); g->exp = strtoull(data, NULL, 10); - Sql_GetData(sql_handle, 7, &data, NULL); g->next_exp = (unsigned int)strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 8, &data, NULL); g->skill_point = atoi(data); - Sql_GetData(sql_handle, 9, &data, &len); memcpy(g->mes1, data, min(len, sizeof(g->mes1))); - Sql_GetData(sql_handle, 10, &data, &len); memcpy(g->mes2, data, min(len, sizeof(g->mes2))); - Sql_GetData(sql_handle, 11, &data, &len); g->emblem_len = atoi(data); - Sql_GetData(sql_handle, 12, &data, &len); g->emblem_id = atoi(data); - Sql_GetData(sql_handle, 13, &data, &len); + SQL->GetData(sql_handle, 5, &data, NULL); g->average_lv = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); g->exp = strtoull(data, NULL, 10); + SQL->GetData(sql_handle, 7, &data, NULL); g->next_exp = (unsigned int)strtoul(data, NULL, 10); + SQL->GetData(sql_handle, 8, &data, NULL); g->skill_point = atoi(data); + SQL->GetData(sql_handle, 9, &data, &len); memcpy(g->mes1, data, min(len, sizeof(g->mes1))); + SQL->GetData(sql_handle, 10, &data, &len); memcpy(g->mes2, data, min(len, sizeof(g->mes2))); + SQL->GetData(sql_handle, 11, &data, &len); g->emblem_len = atoi(data); + SQL->GetData(sql_handle, 12, &data, &len); g->emblem_id = atoi(data); + SQL->GetData(sql_handle, 13, &data, &len); // convert emblem data from hexadecimal to binary //TODO: why not store it in the db as binary directly? [ultramage] for( i = 0, p = g->emblem_data; i < g->emblem_len; ++i, ++p ) @@ -409,90 +410,90 @@ struct guild * inter_guild_fromsql(int guild_id) } // load guild member info - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` " + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`,`char_id`,`hair`,`hair_color`,`gender`,`class`,`lv`,`exp`,`exp_payper`,`online`,`position`,`name` " "FROM `%s` WHERE `guild_id`='%d' ORDER BY `position`", guild_member_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - for( i = 0; i < g->max_member && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < g->max_member && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { struct guild_member* m = &g->member[i]; - Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); m->hair = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); m->hair_color = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); m->gender = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); m->class_ = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); m->lv = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); m->exp = strtoull(data, NULL, 10); - Sql_GetData(sql_handle, 8, &data, NULL); m->exp_payper = (unsigned int)atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); m->online = atoi(data); - Sql_GetData(sql_handle, 10, &data, NULL); m->position = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); m->hair = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); m->hair_color = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); m->gender = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); m->class_ = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); m->lv = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); m->exp = strtoull(data, NULL, 10); + SQL->GetData(sql_handle, 8, &data, NULL); m->exp_payper = (unsigned int)atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); m->online = atoi(data); + SQL->GetData(sql_handle, 10, &data, NULL); m->position = atoi(data); if( m->position >= MAX_GUILDPOSITION ) // Fix reduction of MAX_GUILDPOSITION [PoW] m->position = MAX_GUILDPOSITION - 1; - Sql_GetData(sql_handle, 11, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 11, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); m->modified = GS_MEMBER_UNMODIFIED; } //printf("- Read guild_position %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `position`,`name`,`mode`,`exp_mode` FROM `%s` WHERE `guild_id`='%d'", guild_position_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + while( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { int position; struct guild_position* p; - Sql_GetData(sql_handle, 0, &data, NULL); position = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); position = atoi(data); if( position < 0 || position >= MAX_GUILDPOSITION ) continue;// invalid position p = &g->position[position]; - Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 2, &data, NULL); p->mode = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); p->exp_mode = atoi(data); + SQL->GetData(sql_handle, 1, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 2, &data, NULL); p->mode = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); p->exp_mode = atoi(data); p->modified = GS_POSITION_UNMODIFIED; } //printf("- Read guild_alliance %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `opposition`,`alliance_id`,`name` FROM `%s` WHERE `guild_id`='%d'", guild_alliance_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - for( i = 0; i < MAX_GUILDALLIANCE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < MAX_GUILDALLIANCE && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { struct guild_alliance* a = &g->alliance[i]; - Sql_GetData(sql_handle, 0, &data, NULL); a->opposition = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); a->guild_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 0, &data, NULL); a->opposition = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); a->guild_id = atoi(data); + SQL->GetData(sql_handle, 2, &data, &len); memcpy(a->name, data, min(len, NAME_LENGTH)); } //printf("- Read guild_expulsion %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`,`name`,`mes` FROM `%s` WHERE `guild_id`='%d'", guild_expulsion_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); return NULL; } - for( i = 0; i < MAX_GUILDEXPULSION && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < MAX_GUILDEXPULSION && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { struct guild_expulsion *e = &g->expulsion[i]; - Sql_GetData(sql_handle, 0, &data, NULL); e->account_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, &len); memcpy(e->name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 2, &data, &len); memcpy(e->mes, data, min(len, sizeof(e->mes))); + SQL->GetData(sql_handle, 0, &data, NULL); e->account_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, &len); memcpy(e->name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 2, &data, &len); memcpy(e->mes, data, min(len, sizeof(e->mes))); } //printf("- Read guild_skill %d from sql \n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `guild_id`='%d' ORDER BY `id`", guild_skill_db, guild_id) ) { Sql_ShowDebug(sql_handle); aFree(g); @@ -504,15 +505,15 @@ struct guild * inter_guild_fromsql(int guild_id) g->skill[i].id = i + GD_SKILLBASE; } - while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + while( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { int id; - Sql_GetData(sql_handle, 0, &data, NULL); id = atoi(data) - GD_SKILLBASE; - if( id < 0 && id >= MAX_GUILDSKILL ) + SQL->GetData(sql_handle, 0, &data, NULL); id = atoi(data) - GD_SKILLBASE; + if( id < 0 || id >= MAX_GUILDSKILL ) continue;// invalid guild skill - Sql_GetData(sql_handle, 1, &data, NULL); g->skill[id].lv = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); g->skill[id].lv = atoi(data); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); idb_put(guild_db_, guild_id, g); //Add to cache g->save_flag |= GS_REMOVE; //But set it to be removed, in case it is not needed for long. @@ -529,20 +530,20 @@ int inter_guildcastle_tosql(struct guild_castle *gc) StringBuf buf; int i; - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "REPLACE INTO `%s` SET `castle_id`='%d', `guild_id`='%d', `economy`='%d', `defense`='%d', " + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "REPLACE INTO `%s` SET `castle_id`='%d', `guild_id`='%d', `economy`='%d', `defense`='%d', " "`triggerE`='%d', `triggerD`='%d', `nextTime`='%d', `payTime`='%d', `createTime`='%d', `visibleC`='%d'", guild_castle_db, gc->castle_id, gc->guild_id, gc->economy, gc->defense, gc->triggerE, gc->triggerD, gc->nextTime, gc->payTime, gc->createTime, gc->visibleC); for (i = 0; i < MAX_GUARDIANS; ++i) - StringBuf_Printf(&buf, ", `visibleG%d`='%d'", i, gc->guardian[i].visible); + StrBuf->Printf(&buf, ", `visibleG%d`='%d'", i, gc->guardian[i].visible); - if (SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf))) + if (SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf))) Sql_ShowDebug(sql_handle); else if(save_log) ShowInfo("Saved guild castle (%d)\n", gc->castle_id); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return 0; } @@ -557,37 +558,37 @@ static struct guild_castle* inter_guildcastle_fromsql(int castle_id) if (gc != NULL) return gc; - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, " + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `castle_id`, `guild_id`, `economy`, `defense`, `triggerE`, " "`triggerD`, `nextTime`, `payTime`, `createTime`, `visibleC`"); for (i = 0; i < MAX_GUARDIANS; ++i) - StringBuf_Printf(&buf, ", `visibleG%d`", i); - StringBuf_Printf(&buf, " FROM `%s` WHERE `castle_id`='%d'", guild_castle_db, castle_id); - if (SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf))) { + StrBuf->Printf(&buf, ", `visibleG%d`", i); + StrBuf->Printf(&buf, " FROM `%s` WHERE `castle_id`='%d'", guild_castle_db, castle_id); + if (SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf))) { Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return NULL; } - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); CREATE(gc, struct guild_castle, 1); gc->castle_id = castle_id; - if (SQL_SUCCESS == Sql_NextRow(sql_handle)) { - Sql_GetData(sql_handle, 1, &data, NULL); gc->guild_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); gc->economy = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); gc->defense = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); gc->triggerE = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); gc->triggerD = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); gc->nextTime = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); gc->payTime = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); gc->createTime = atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); gc->visibleC = atoi(data); + if (SQL_SUCCESS == SQL->NextRow(sql_handle)) { + SQL->GetData(sql_handle, 1, &data, NULL); gc->guild_id = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); gc->economy = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); gc->defense = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); gc->triggerE = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); gc->triggerD = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); gc->nextTime = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); gc->payTime = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); gc->createTime = atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); gc->visibleC = atoi(data); for (i = 10; i < 10+MAX_GUARDIANS; i++) { - Sql_GetData(sql_handle, i, &data, NULL); gc->guardian[i-10].visible = atoi(data); + SQL->GetData(sql_handle, i, &data, NULL); gc->guardian[i-10].visible = atoi(data); } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); idb_put(castle_db, castle_id, gc); @@ -601,9 +602,9 @@ static struct guild_castle* inter_guildcastle_fromsql(int castle_id) // Read exp_guild.txt static bool exp_guild_parse_row(char* split[], int column, int current) { - int exp = atoi(split[0]); + unsigned int exp = (unsigned int)atol(split[0]); - if (exp < 0 || exp >= INT_MAX) { + if (exp >= UINT_MAX) { ShowError("exp_guild: Invalid exp %d at line %d\n", exp, current); return false; } @@ -620,24 +621,24 @@ int inter_guild_CharOnline(int char_id, int guild_id) if (guild_id == -1) { //Get guild_id from the database - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; } - if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); guild_id = atoi(data); } else { guild_id = 0; } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } if (guild_id == 0) return 0; //No guild... @@ -671,24 +672,24 @@ int inter_guild_CharOffline(int char_id, int guild_id) if (guild_id == -1) { //Get guild_id from the database - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT guild_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; } - if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); guild_id = atoi(data); } else { guild_id = 0; } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } if (guild_id == 0) return 0; //No guild... @@ -726,7 +727,7 @@ int inter_guild_sql_init(void) castle_db = idb_alloc(DB_OPT_RELEASE_DATA); //Read exp file - sv_readdb("db/"DBPATH, "exp_guild.txt", ',', 1, 1, 100, exp_guild_parse_row); + sv->readdb("db", DBPATH"exp_guild.txt", ',', 1, 1, 100, exp_guild_parse_row); add_timer_func_list(guild_save_timer, "guild_save_timer"); add_timer(gettick() + 10000, guild_save_timer, 0, 0); @@ -738,7 +739,7 @@ int inter_guild_sql_init(void) */ static int guild_db_final(DBKey key, DBData *data, va_list ap) { - struct guild *g = db_data2ptr(data); + struct guild *g = DB->data2ptr(data); if (g->save_flag&GS_MASK) { inter_guild_tosql(g, g->save_flag&GS_MASK); return 1; @@ -759,26 +760,26 @@ int search_guildname(char *str) int guild_id; char esc_name[NAME_LENGTH*2+1]; - Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH)); //Lookup guilds with the same name - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT guild_id FROM `%s` WHERE name='%s'", guild_db, esc_name) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT guild_id FROM `%s` WHERE name='%s'", guild_db, esc_name) ) { Sql_ShowDebug(sql_handle); return -1; } - if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); guild_id = atoi(data); } else { guild_id = 0; } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return guild_id; } @@ -1261,13 +1262,13 @@ int mapif_parse_GuildAddMember(int fd,int guild_id,struct guild_member *m) // Delete member from guild int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, int flag, const char *mes) { - int i, j; + int i; struct guild* g = inter_guild_fromsql(guild_id); if( g == NULL ) { // Unknown guild, just update the player - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, account_id, char_id) ) Sql_ShowDebug(sql_handle); // mapif_guild_withdraw(guild_id,account_id,char_id,flag,g->member[i].name,mes); return 0; @@ -1284,6 +1285,7 @@ int mapif_parse_GuildLeave(int fd, int guild_id, int account_id, int char_id, in if( flag ) { // Write expulsion reason // Find an empty slot + int j; ARR_FIND( 0, MAX_GUILDEXPULSION, j, g->expulsion[j].account_id == 0 ); if( j == MAX_GUILDEXPULSION ) { @@ -1379,32 +1381,32 @@ int mapif_parse_BreakGuild(int fd,int guild_id) // Delete guild from sql //printf("- Delete guild %d from guild\n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_member_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_castle_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_storage_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d' OR `alliance_id` = '%d'", guild_alliance_db, guild_id, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_position_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_skill_db, guild_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id` = '%d'", guild_expulsion_db, guild_id) ) Sql_ShowDebug(sql_handle); //printf("- Update guild %d of char\n",guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", char_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `guild_id`='0' WHERE `guild_id`='%d'", char_db, guild_id) ) Sql_ShowDebug(sql_handle); mapif_guild_broken(guild_id,0); @@ -1815,7 +1817,7 @@ int mapif_parse_GuildMasterChange(int fd, int guild_id, const char* name, int le g->member[0].position = 0; //Position 0: guild Master. g->member[0].modified = GS_MEMBER_MODIFIED; - strncpy(g->master, name, len); + safestrncpy(g->master, name, len); if (len < NAME_LENGTH) g->master[len] = '\0'; diff --git a/src/char/int_homun.c b/src/char/int_homun.c index 933661954..6e4f63849 100644 --- a/src/char/int_homun.c +++ b/src/char/int_homun.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/malloc.h" @@ -88,11 +89,11 @@ bool mapif_homunculus_save(struct s_homunculus* hd) bool flag = true; char esc_name[NAME_LENGTH*2+1]; - Sql_EscapeStringLen(sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_name, hd->name, strnlen(hd->name, NAME_LENGTH)); if( hd->hom_id == 0 ) {// new homunculus - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` " "(`char_id`, `class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`, `rename_flag`, `vaporize`) " "VALUES ('%d', '%d', '%d', '%s', '%d', '%u', '%u', '%d', '%d', %d, '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, @@ -103,12 +104,12 @@ bool mapif_homunculus_save(struct s_homunculus* hd) } else { - hd->hom_id = (int)Sql_LastInsertId(sql_handle); + hd->hom_id = (int)SQL->LastInsertId(sql_handle); } } else { - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'", + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `char_id`='%d', `class`='%d',`prev_class`='%d',`name`='%s',`level`='%d',`exp`='%u',`intimacy`='%u',`hunger`='%d', `str`='%d', `agi`='%d', `vit`='%d', `int`='%d', `dex`='%d', `luk`='%d', `hp`='%d',`max_hp`='%d',`sp`='%d',`max_sp`='%d',`skill_point`='%d', `rename_flag`='%d', `vaporize`='%d' WHERE `homun_id`='%d'", homunculus_db, hd->char_id, hd->class_, hd->prev_class, esc_name, hd->level, hd->exp, hd->intimacy, hd->hunger, hd->str, hd->agi, hd->vit, hd->int_, hd->dex, hd->luk, hd->hp, hd->max_hp, hd->sp, hd->max_sp, hd->skillpts, hd->rename_flag, hd->vaporize, hd->hom_id) ) { @@ -156,61 +157,61 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) memset(hd, 0, sizeof(*hd)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'", homunculus_db, homun_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `homun_id`,`char_id`,`class`,`prev_class`,`name`,`level`,`exp`,`intimacy`,`hunger`, `str`, `agi`, `vit`, `int`, `dex`, `luk`, `hp`,`max_hp`,`sp`,`max_sp`,`skill_point`,`rename_flag`, `vaporize` FROM `%s` WHERE `homun_id`='%u'", homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; } - if( !Sql_NumRows(sql_handle) ) + if( !SQL->NumRows(sql_handle) ) { //No homunculus found. - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } hd->hom_id = homun_id; - Sql_GetData(sql_handle, 1, &data, NULL); hd->char_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); hd->class_ = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); hd->prev_class = atoi(data); - Sql_GetData(sql_handle, 4, &data, &len); safestrncpy(hd->name, data, sizeof(hd->name)); - Sql_GetData(sql_handle, 5, &data, NULL); hd->level = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); hd->exp = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); hd->intimacy = (unsigned int)strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 8, &data, NULL); hd->hunger = atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); hd->str = atoi(data); - Sql_GetData(sql_handle, 10, &data, NULL); hd->agi = atoi(data); - Sql_GetData(sql_handle, 11, &data, NULL); hd->vit = atoi(data); - Sql_GetData(sql_handle, 12, &data, NULL); hd->int_ = atoi(data); - Sql_GetData(sql_handle, 13, &data, NULL); hd->dex = atoi(data); - Sql_GetData(sql_handle, 14, &data, NULL); hd->luk = atoi(data); - Sql_GetData(sql_handle, 15, &data, NULL); hd->hp = atoi(data); - Sql_GetData(sql_handle, 16, &data, NULL); hd->max_hp = atoi(data); - Sql_GetData(sql_handle, 17, &data, NULL); hd->sp = atoi(data); - Sql_GetData(sql_handle, 18, &data, NULL); hd->max_sp = atoi(data); - Sql_GetData(sql_handle, 19, &data, NULL); hd->skillpts = atoi(data); - Sql_GetData(sql_handle, 20, &data, NULL); hd->rename_flag = atoi(data); - Sql_GetData(sql_handle, 21, &data, NULL); hd->vaporize = atoi(data); - Sql_FreeResult(sql_handle); + SQL->GetData(sql_handle, 1, &data, NULL); hd->char_id = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); hd->class_ = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); hd->prev_class = atoi(data); + SQL->GetData(sql_handle, 4, &data, &len); safestrncpy(hd->name, data, sizeof(hd->name)); + SQL->GetData(sql_handle, 5, &data, NULL); hd->level = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); hd->exp = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); hd->intimacy = (unsigned int)strtoul(data, NULL, 10); + SQL->GetData(sql_handle, 8, &data, NULL); hd->hunger = atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); hd->str = atoi(data); + SQL->GetData(sql_handle, 10, &data, NULL); hd->agi = atoi(data); + SQL->GetData(sql_handle, 11, &data, NULL); hd->vit = atoi(data); + SQL->GetData(sql_handle, 12, &data, NULL); hd->int_ = atoi(data); + SQL->GetData(sql_handle, 13, &data, NULL); hd->dex = atoi(data); + SQL->GetData(sql_handle, 14, &data, NULL); hd->luk = atoi(data); + SQL->GetData(sql_handle, 15, &data, NULL); hd->hp = atoi(data); + SQL->GetData(sql_handle, 16, &data, NULL); hd->max_hp = atoi(data); + SQL->GetData(sql_handle, 17, &data, NULL); hd->sp = atoi(data); + SQL->GetData(sql_handle, 18, &data, NULL); hd->max_sp = atoi(data); + SQL->GetData(sql_handle, 19, &data, NULL); hd->skillpts = atoi(data); + SQL->GetData(sql_handle, 20, &data, NULL); hd->rename_flag = atoi(data); + SQL->GetData(sql_handle, 21, &data, NULL); hd->vaporize = atoi(data); + SQL->FreeResult(sql_handle); hd->intimacy = cap_value(hd->intimacy, 0, 100000); hd->hunger = cap_value(hd->hunger, 0, 100); // Load Homunculus Skill - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", skill_homunculus_db, homun_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `id`,`lv` FROM `%s` WHERE `homun_id`=%d", skill_homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; } - while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + while( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { // id - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); i = atoi(data); if( i < HM_SKILLBASE || i >= HM_SKILLBASE + MAX_HOMUNSKILL ) continue;// invalid skill id @@ -218,10 +219,10 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) hd->hskill[i].id = (unsigned short)atoi(data); // lv - Sql_GetData(sql_handle, 1, &data, NULL); + SQL->GetData(sql_handle, 1, &data, NULL); hd->hskill[i].lv = (unsigned char)atoi(data); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); if( save_log ) ShowInfo("Homunculus loaded (%d - %s).\n", hd->hom_id, hd->name); @@ -231,8 +232,8 @@ bool mapif_homunculus_load(int homun_id, struct s_homunculus* hd) bool mapif_homunculus_delete(int homun_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", homunculus_db, homun_id) - || SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", skill_homunculus_db, homun_id) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", homunculus_db, homun_id) + || SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `homun_id` = '%u'", skill_homunculus_db, homun_id) ) { Sql_ShowDebug(sql_handle); return false; diff --git a/src/char/int_mail.c b/src/char/int_mail.c index 8d50c713f..9181b7db6 100644 --- a/src/char/int_mail.c +++ b/src/char/int_mail.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/malloc.h" @@ -27,54 +28,54 @@ static int mail_fromsql(int char_id, struct mail_data* md) md->amount = 0; md->full = false; - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`," + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`," "`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`,`unique_id`"); for (i = 0; i < MAX_SLOTS; i++) - StringBuf_Printf(&buf, ",`card%d`", i); + StrBuf->Printf(&buf, ",`card%d`", i); // I keep the `status` < 3 just in case someone forget to apply the sqlfix - StringBuf_Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' AND `status` < 3 ORDER BY `id` LIMIT %d", + StrBuf->Printf(&buf, " FROM `%s` WHERE `dest_id`='%d' AND `status` < 3 ORDER BY `id` LIMIT %d", mail_db, char_id, MAIL_MAX_INBOX + 1); - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf)) ) Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); - for (i = 0; i < MAIL_MAX_INBOX && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for (i = 0; i < MAIL_MAX_INBOX && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { msg = &md->msg[i]; - Sql_GetData(sql_handle, 0, &data, NULL); msg->id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH); - Sql_GetData(sql_handle, 2, &data, NULL); msg->send_id = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH); - Sql_GetData(sql_handle, 4, &data, NULL); msg->dest_id = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); - Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); - Sql_GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); msg->status = (mail_status)atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); msg->id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH); + SQL->GetData(sql_handle, 2, &data, NULL); msg->send_id = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH); + SQL->GetData(sql_handle, 4, &data, NULL); msg->dest_id = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); + SQL->GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); + SQL->GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); msg->status = (mail_status)atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); item = &msg->item; - Sql_GetData(sql_handle,10, &data, NULL); item->amount = (short)atoi(data); - Sql_GetData(sql_handle,11, &data, NULL); item->nameid = atoi(data); - Sql_GetData(sql_handle,12, &data, NULL); item->refine = atoi(data); - Sql_GetData(sql_handle,13, &data, NULL); item->attribute = atoi(data); - Sql_GetData(sql_handle,14, &data, NULL); item->identify = atoi(data); - Sql_GetData(sql_handle,15, &data, NULL); item->unique_id = strtoull(data, NULL, 10); + SQL->GetData(sql_handle,10, &data, NULL); item->amount = (short)atoi(data); + SQL->GetData(sql_handle,11, &data, NULL); item->nameid = atoi(data); + SQL->GetData(sql_handle,12, &data, NULL); item->refine = atoi(data); + SQL->GetData(sql_handle,13, &data, NULL); item->attribute = atoi(data); + SQL->GetData(sql_handle,14, &data, NULL); item->identify = atoi(data); + SQL->GetData(sql_handle,15, &data, NULL); item->unique_id = strtoull(data, NULL, 10); item->expire_time = 0; for (j = 0; j < MAX_SLOTS; j++) { - Sql_GetData(sql_handle, 16 + j, &data, NULL); + SQL->GetData(sql_handle, 16 + j, &data, NULL); item->card[j] = atoi(data); } } - md->full = ( Sql_NumRows(sql_handle) > MAIL_MAX_INBOX ); + md->full = ( SQL->NumRows(sql_handle) > MAIL_MAX_INBOX ); md->amount = i; - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); md->unchecked = 0; md->unread = 0; @@ -83,7 +84,7 @@ static int mail_fromsql(int char_id, struct mail_data* md) msg = &md->msg[i]; if( msg->status == MAIL_NEW ) { - if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_UNREAD, msg->id) ) + if ( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_UNREAD, msg->id) ) Sql_ShowDebug(sql_handle); msg->status = MAIL_UNREAD; @@ -106,15 +107,15 @@ int mail_savemessage(struct mail_message* msg) int j; // build message save query - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `status`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`, `unique_id`", mail_db); + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s` (`send_name`, `send_id`, `dest_name`, `dest_id`, `title`, `message`, `time`, `status`, `zeny`, `amount`, `nameid`, `refine`, `attribute`, `identify`, `unique_id`", mail_db); for (j = 0; j < MAX_SLOTS; j++) - StringBuf_Printf(&buf, ", `card%d`", j); - StringBuf_Printf(&buf, ") VALUES (?, '%d', ?, '%d', ?, ?, '%lu', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%"PRIu64"'", + StrBuf->Printf(&buf, ", `card%d`", j); + StrBuf->Printf(&buf, ") VALUES (?, '%d', ?, '%d', ?, ?, '%lu', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%"PRIu64"'", msg->send_id, msg->dest_id, (unsigned long)msg->timestamp, msg->status, msg->zeny, msg->item.amount, msg->item.nameid, msg->item.refine, msg->item.attribute, msg->item.identify, msg->item.unique_id); for (j = 0; j < MAX_SLOTS; j++) - StringBuf_Printf(&buf, ", '%d'", msg->item.card[j]); - StringBuf_AppendStr(&buf, ")"); + StrBuf->Printf(&buf, ", '%d'", msg->item.card[j]); + StrBuf->AppendStr(&buf, ")"); //Unique Non Stackable Item ID updateLastUid(msg->item.unique_id); @@ -122,7 +123,7 @@ int mail_savemessage(struct mail_message* msg) // prepare and execute query stmt = SqlStmt_Malloc(sql_handle); - if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StringBuf_Value(&buf)) + if( SQL_SUCCESS != SqlStmt_PrepareStr(stmt, StrBuf->Value(&buf)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, msg->send_name, strnlen(msg->send_name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, msg->dest_name, strnlen(msg->dest_name, NAME_LENGTH)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_STRING, msg->title, strnlen(msg->title, MAIL_TITLE_LENGTH)) @@ -135,7 +136,7 @@ int mail_savemessage(struct mail_message* msg) msg->id = (int)SqlStmt_LastInsertId(stmt); SqlStmt_Free(stmt); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return msg->id; } @@ -147,52 +148,52 @@ static bool mail_loadmessage(int mail_id, struct mail_message* msg) int j; StringBuf buf; - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`," + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`," "`zeny`,`amount`,`nameid`,`refine`,`attribute`,`identify`,`unique_id`"); for( j = 0; j < MAX_SLOTS; j++ ) - StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `id` = '%d'", mail_db, mail_id); + StrBuf->Printf(&buf, ",`card%d`", j); + StrBuf->Printf(&buf, " FROM `%s` WHERE `id` = '%d'", mail_db, mail_id); - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) - || SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf)) + || SQL_SUCCESS != SQL->NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); - Sql_FreeResult(sql_handle); - StringBuf_Destroy(&buf); + SQL->FreeResult(sql_handle); + StrBuf->Destroy(&buf); return false; } else { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); msg->id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH); - Sql_GetData(sql_handle, 2, &data, NULL); msg->send_id = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH); - Sql_GetData(sql_handle, 4, &data, NULL); msg->dest_id = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); - Sql_GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); - Sql_GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); msg->status = (mail_status)atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); - Sql_GetData(sql_handle,10, &data, NULL); msg->item.amount = (short)atoi(data); - Sql_GetData(sql_handle,11, &data, NULL); msg->item.nameid = atoi(data); - Sql_GetData(sql_handle,12, &data, NULL); msg->item.refine = atoi(data); - Sql_GetData(sql_handle,13, &data, NULL); msg->item.attribute = atoi(data); - Sql_GetData(sql_handle,14, &data, NULL); msg->item.identify = atoi(data); - Sql_GetData(sql_handle,15, &data, NULL); msg->item.unique_id = strtoull(data, NULL, 10); + SQL->GetData(sql_handle, 0, &data, NULL); msg->id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(msg->send_name, data, NAME_LENGTH); + SQL->GetData(sql_handle, 2, &data, NULL); msg->send_id = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); safestrncpy(msg->dest_name, data, NAME_LENGTH); + SQL->GetData(sql_handle, 4, &data, NULL); msg->dest_id = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); safestrncpy(msg->title, data, MAIL_TITLE_LENGTH); + SQL->GetData(sql_handle, 6, &data, NULL); safestrncpy(msg->body, data, MAIL_BODY_LENGTH); + SQL->GetData(sql_handle, 7, &data, NULL); msg->timestamp = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); msg->status = (mail_status)atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); msg->zeny = atoi(data); + SQL->GetData(sql_handle,10, &data, NULL); msg->item.amount = (short)atoi(data); + SQL->GetData(sql_handle,11, &data, NULL); msg->item.nameid = atoi(data); + SQL->GetData(sql_handle,12, &data, NULL); msg->item.refine = atoi(data); + SQL->GetData(sql_handle,13, &data, NULL); msg->item.attribute = atoi(data); + SQL->GetData(sql_handle,14, &data, NULL); msg->item.identify = atoi(data); + SQL->GetData(sql_handle,15, &data, NULL); msg->item.unique_id = strtoull(data, NULL, 10); msg->item.expire_time = 0; for( j = 0; j < MAX_SLOTS; j++ ) { - Sql_GetData(sql_handle,16 + j, &data, NULL); + SQL->GetData(sql_handle,16 + j, &data, NULL); msg->item.card[j] = atoi(data); } } - StringBuf_Destroy(&buf); - Sql_FreeResult(sql_handle); + StrBuf->Destroy(&buf); + SQL->FreeResult(sql_handle); return true; } @@ -226,7 +227,7 @@ static void mapif_parse_Mail_requestinbox(int fd) static void mapif_parse_Mail_read(int fd) { int mail_id = RFIFOL(fd,2); - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_READ, mail_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `status` = '%d' WHERE `id` = '%d'", mail_db, MAIL_READ, mail_id) ) Sql_ShowDebug(sql_handle); } @@ -238,21 +239,21 @@ static bool mail_DeleteAttach(int mail_id) StringBuf buf; int i; - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "UPDATE `%s` SET `zeny` = '0', `nameid` = '0', `amount` = '0', `refine` = '0', `attribute` = '0', `identify` = '0'", mail_db); + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "UPDATE `%s` SET `zeny` = '0', `nameid` = '0', `amount` = '0', `refine` = '0', `attribute` = '0', `identify` = '0'", mail_db); for (i = 0; i < MAX_SLOTS; i++) - StringBuf_Printf(&buf, ", `card%d` = '0'", i); - StringBuf_Printf(&buf, " WHERE `id` = '%d'", mail_id); + StrBuf->Printf(&buf, ", `card%d` = '0'", i); + StrBuf->Printf(&buf, " WHERE `id` = '%d'", mail_id); - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return false; } - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return true; } @@ -295,7 +296,7 @@ static void mapif_parse_Mail_getattach(int fd) static void mapif_Mail_delete(int fd, int char_id, int mail_id) { bool failed = false; - if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) + if ( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) { Sql_ShowDebug(sql_handle); failed = true; @@ -344,7 +345,7 @@ static void mapif_Mail_return(int fd, int char_id, int mail_id) { if( msg.dest_id != char_id) return; - else if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) + else if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `id` = '%d'", mail_db, mail_id) ) Sql_ShowDebug(sql_handle); else { @@ -408,21 +409,21 @@ static void mapif_parse_Mail_send(int fd) memcpy(&msg, RFIFOP(fd,8), sizeof(struct mail_message)); // Try to find the Dest Char by Name - Sql_EscapeStringLen(sql_handle, esc_name, msg.dest_name, strnlen(msg.dest_name, NAME_LENGTH)); - if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) + SQL->EscapeStringLen(sql_handle, esc_name, msg.dest_name, strnlen(msg.dest_name, NAME_LENGTH)); + if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`, `char_id` FROM `%s` WHERE `name` = '%s'", char_db, esc_name) ) Sql_ShowDebug(sql_handle); else - if ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + if ( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char *data; - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); if (atoi(data) != account_id) { // Cannot send mail to char in the same account - Sql_GetData(sql_handle, 1, &data, NULL); + SQL->GetData(sql_handle, 1, &data, NULL); msg.dest_id = atoi(data); } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); msg.status = MAIL_NEW; if( msg.dest_id > 0 ) diff --git a/src/char/int_mercenary.c b/src/char/int_mercenary.c index 3b3714416..aecb3844a 100644 --- a/src/char/int_mercenary.c +++ b/src/char/int_mercenary.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/malloc.h" @@ -19,33 +20,33 @@ bool mercenary_owner_fromsql(int char_id, struct mmo_charstatus *status) { char* data; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith` FROM `%s` WHERE `char_id` = '%d'", mercenary_owner_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith` FROM `%s` WHERE `char_id` = '%d'", mercenary_owner_db, char_id) ) { Sql_ShowDebug(sql_handle); return false; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } - Sql_GetData(sql_handle, 0, &data, NULL); status->mer_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); status->arch_calls = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); status->arch_faith = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); status->spear_calls = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); status->spear_faith = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); status->sword_calls = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); status->sword_faith = atoi(data); - Sql_FreeResult(sql_handle); + SQL->GetData(sql_handle, 0, &data, NULL); status->mer_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); status->arch_calls = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); status->arch_faith = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); status->spear_calls = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); status->spear_faith = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); status->sword_calls = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); status->sword_faith = atoi(data); + SQL->FreeResult(sql_handle); return true; } bool mercenary_owner_tosql(int char_id, struct mmo_charstatus *status) { - if( SQL_ERROR == Sql_Query(sql_handle, "REPLACE INTO `%s` (`char_id`, `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith`) VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", + if( SQL_ERROR == SQL->Query(sql_handle, "REPLACE INTO `%s` (`char_id`, `merc_id`, `arch_calls`, `arch_faith`, `spear_calls`, `spear_faith`, `sword_calls`, `sword_faith`) VALUES ('%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", mercenary_owner_db, char_id, status->mer_id, status->arch_calls, status->arch_faith, status->spear_calls, status->spear_faith, status->sword_calls, status->sword_faith) ) { Sql_ShowDebug(sql_handle); @@ -57,10 +58,10 @@ bool mercenary_owner_tosql(int char_id, struct mmo_charstatus *status) bool mercenary_owner_delete(int char_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", mercenary_owner_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", mercenary_owner_db, char_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", mercenary_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `char_id` = '%d'", mercenary_db, char_id) ) Sql_ShowDebug(sql_handle); return true; @@ -72,7 +73,7 @@ bool mapif_mercenary_save(struct s_mercenary* merc) if( merc->mercenary_id == 0 ) { // Create new DB entry - if( SQL_ERROR == Sql_Query(sql_handle, + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` (`char_id`,`class`,`hp`,`sp`,`kill_counter`,`life_time`) VALUES ('%d','%d','%d','%d','%u','%u')", mercenary_db, merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->life_time) ) { @@ -80,9 +81,9 @@ bool mapif_mercenary_save(struct s_mercenary* merc) flag = false; } else - merc->mercenary_id = (int)Sql_LastInsertId(sql_handle); + merc->mercenary_id = (int)SQL->LastInsertId(sql_handle); } - else if( SQL_ERROR == Sql_Query(sql_handle, + else if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `char_id` = '%d', `class` = '%d', `hp` = '%d', `sp` = '%d', `kill_counter` = '%u', `life_time` = '%u' WHERE `mer_id` = '%d'", mercenary_db, merc->char_id, merc->class_, merc->hp, merc->sp, merc->kill_count, merc->life_time, merc->mercenary_id) ) { // Update DB entry @@ -101,24 +102,24 @@ bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc) merc->mercenary_id = merc_id; merc->char_id = char_id; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `class`, `hp`, `sp`, `kill_counter`, `life_time` FROM `%s` WHERE `mer_id` = '%d' AND `char_id` = '%d'", mercenary_db, merc_id, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `class`, `hp`, `sp`, `kill_counter`, `life_time` FROM `%s` WHERE `mer_id` = '%d' AND `char_id` = '%d'", mercenary_db, merc_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } - Sql_GetData(sql_handle, 0, &data, NULL); merc->class_ = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); merc->hp = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); merc->sp = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); merc->kill_count = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); merc->life_time = atoi(data); - Sql_FreeResult(sql_handle); + SQL->GetData(sql_handle, 0, &data, NULL); merc->class_ = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); merc->hp = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); merc->sp = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); merc->kill_count = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); merc->life_time = atoi(data); + SQL->FreeResult(sql_handle); if( save_log ) ShowInfo("Mercenary loaded (%d - %d).\n", merc->mercenary_id, merc->char_id); @@ -127,7 +128,7 @@ bool mapif_mercenary_load(int merc_id, int char_id, struct s_mercenary *merc) bool mapif_mercenary_delete(int merc_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `mer_id` = '%d'", mercenary_db, merc_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `mer_id` = '%d'", mercenary_db, merc_id) ) { Sql_ShowDebug(sql_handle); return false; diff --git a/src/char/int_party.c b/src/char/int_party.c index a88e5c586..9cb4ccf80 100644 --- a/src/char/int_party.c +++ b/src/char/int_party.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/mmo.h" @@ -125,14 +126,14 @@ int inter_party_tosql(struct party *p, int flag, int index) #ifdef NOISY ShowInfo("Save party request ("CL_BOLD"%d"CL_RESET" - %s).\n", party_id, p->name); #endif - Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); if( flag & PS_BREAK ) {// Break the party // we'll skip name-checking and just reset everyone with the same party id [celest] - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) Sql_ShowDebug(sql_handle); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) Sql_ShowDebug(sql_handle); //Remove from memory idb_remove(party_db_, party_id); @@ -141,7 +142,7 @@ int inter_party_tosql(struct party *p, int flag, int index) if( flag & PS_CREATE ) {// Create party - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` " "(`name`, `exp`, `item`, `leader_id`, `leader_char`) " "VALUES ('%s', '%d', '%d', '%d', '%d')", party_db, esc_name, p->exp, p->item, p->member[index].account_id, p->member[index].char_id) ) @@ -149,33 +150,33 @@ int inter_party_tosql(struct party *p, int flag, int index) Sql_ShowDebug(sql_handle); return 0; } - party_id = p->party_id = (int)Sql_LastInsertId(sql_handle); + party_id = p->party_id = (int)SQL->LastInsertId(sql_handle); } if( flag & PS_BASIC ) {// Update party info. - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'", + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `name`='%s', `exp`='%d', `item`='%d' WHERE `party_id`='%d'", party_db, esc_name, p->exp, p->item, party_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_LEADER ) {// Update leader - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'", + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `leader_id`='%d', `leader_char`='%d' WHERE `party_id`='%d'", party_db, p->member[index].account_id, p->member[index].char_id, party_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_ADDMEMBER ) {// Add one party member. - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'", + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `party_id`='%d' WHERE `account_id`='%d' AND `char_id`='%d'", char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) Sql_ShowDebug(sql_handle); } if( flag & PS_DELMEMBER ) {// Remove one party member. - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'", + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d' AND `account_id`='%d' AND `char_id`='%d'", char_db, party_id, p->member[index].account_id, p->member[index].char_id) ) Sql_ShowDebug(sql_handle); } @@ -210,42 +211,42 @@ struct party_data *inter_party_fromsql(int party_id) p = party_pt; memset(p, 0, sizeof(struct party_data)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `party_id`, `name`,`exp`,`item`, `leader_id`, `leader_char` FROM `%s` WHERE `party_id`='%d'", party_db, party_id) ) { Sql_ShowDebug(sql_handle); return NULL; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) return NULL; p->party.party_id = party_id; - Sql_GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0); - Sql_GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data); - Sql_FreeResult(sql_handle); + SQL->GetData(sql_handle, 1, &data, &len); memcpy(p->party.name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 2, &data, NULL); p->party.exp = (atoi(data) ? 1 : 0); + SQL->GetData(sql_handle, 3, &data, NULL); p->party.item = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); leader_id = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); leader_char = atoi(data); + SQL->FreeResult(sql_handle); // Load members - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`,`char_id`,`name`,`base_level`,`last_map`,`online`,`class` FROM `%s` WHERE `party_id`='%d'", char_db, party_id) ) { Sql_ShowDebug(sql_handle); return NULL; } - for( i = 0; i < MAX_PARTY && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < MAX_PARTY && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { m = &p->party.member[i]; - Sql_GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); - Sql_GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data); - Sql_GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0); - Sql_GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); m->account_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); m->char_id = atoi(data); + SQL->GetData(sql_handle, 2, &data, &len); memcpy(m->name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 3, &data, NULL); m->lv = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); m->map = mapindex_name2id(data); + SQL->GetData(sql_handle, 5, &data, NULL); m->online = (atoi(data) ? 1 : 0); + SQL->GetData(sql_handle, 6, &data, NULL); m->class_ = atoi(data); m->leader = (m->account_id == leader_id && m->char_id == leader_char ? 1 : 0); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); if( save_log ) ShowInfo("Party loaded (%d - %s).\n", party_id, p->party.name); @@ -270,7 +271,7 @@ int inter_party_sql_init(void) /* Uncomment the following if you want to do a party_db cleanup (remove parties with no members) on startup.[Skotlex] ShowStatus("cleaning party table...\n"); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL", + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` USING `%s` LEFT JOIN `%s` ON `%s`.leader_id =`%s`.account_id AND `%s`.leader_char = `%s`.char_id WHERE `%s`.account_id IS NULL", party_db, party_db, char_db, party_db, char_db, party_db, char_db, char_db) ) Sql_ShowDebug(sql_handle); */ @@ -291,15 +292,14 @@ struct party_data* search_partyname(char* str) char* data; struct party_data* p = NULL; - Sql_EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) ) + SQL->EscapeStringLen(sql_handle, esc_name, str, safestrnlen(str, NAME_LENGTH)); + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `party_id` FROM `%s` WHERE `name`='%s'", party_db, esc_name) ) Sql_ShowDebug(sql_handle); - else if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) - { - Sql_GetData(sql_handle, 0, &data, NULL); + else if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { + SQL->GetData(sql_handle, 0, &data, NULL); p = inter_party_fromsql(atoi(data)); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return p; } @@ -476,6 +476,11 @@ int mapif_parse_CreateParty(int fd, char *name, int item, int item2, struct part if (char_name_option == 1) { // only letters/symbols in char_name_letters are authorised for (i = 0; i < NAME_LENGTH && name[i]; i++) if (strchr(char_name_letters, name[i]) == NULL) { + if( name[i] == '"' ) { /* client-special-char */ + normalize_name(name,"\""); + mapif_parse_CreateParty(fd,name,item,item2,leader); + return 0; + } mapif_party_created(fd,leader->account_id,leader->char_id,NULL); return 0; } @@ -592,7 +597,7 @@ int mapif_parse_PartyLeave(int fd, int party_id, int account_id, int char_id) p = inter_party_fromsql(party_id); if( p == NULL ) {// Party does not exists? - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `party_id`='0' WHERE `party_id`='%d'", char_db, party_id) ) Sql_ShowDebug(sql_handle); return 0; } @@ -777,18 +782,18 @@ int inter_party_CharOnline(int char_id, int party_id) {// Get party_id from the database char* data; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) return 0; //Eh? No party? - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); party_id = atoi(data); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } if (party_id == 0) return 0; //No party... @@ -823,18 +828,18 @@ int inter_party_CharOffline(int char_id, int party_id) { {// Get guild_id from the database char* data; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT party_id FROM `%s` WHERE char_id='%d'", char_db, char_id) ) { Sql_ShowDebug(sql_handle); return 0; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) return 0; //Eh? No party? - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); party_id = atoi(data); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } if (party_id == 0) return 0; //No party... diff --git a/src/char/int_pet.c b/src/char/int_pet.c index 114398290..2867aed77 100644 --- a/src/char/int_pet.c +++ b/src/char/int_pet.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/malloc.h" @@ -23,13 +24,13 @@ int inter_pet_tosql(int pet_id, struct s_pet* p) //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) char esc_name[NAME_LENGTH*2+1];// escaped pet name - Sql_EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_name, p->name, strnlen(p->name, NAME_LENGTH)); p->hungry = cap_value(p->hungry, 0, 100); p->intimate = cap_value(p->intimate, 0, 1000); if( pet_id == -1 ) {// New pet. - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` " + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` " "(`class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) " "VALUES ('%d', '%s', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d')", pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, @@ -38,11 +39,11 @@ int inter_pet_tosql(int pet_id, struct s_pet* p) Sql_ShowDebug(sql_handle); return 0; } - p->pet_id = (int)Sql_LastInsertId(sql_handle); + p->pet_id = (int)SQL->LastInsertId(sql_handle); } else {// Update pet. - if( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", + if( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `class`='%d',`name`='%s',`account_id`='%d',`char_id`='%d',`level`='%d',`egg_id`='%d',`equip`='%d',`intimate`='%d',`hungry`='%d',`rename_flag`='%d',`incuvate`='%d' WHERE `pet_id`='%d'", pet_db, p->class_, esc_name, p->account_id, p->char_id, p->level, p->egg_id, p->equip, p->intimate, p->hungry, p->rename_flag, p->incuvate, p->pet_id) ) { @@ -68,28 +69,28 @@ int inter_pet_fromsql(int pet_id, struct s_pet* p) //`pet` (`pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate`) - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `pet_id`, `class`,`name`,`account_id`,`char_id`,`level`,`egg_id`,`equip`,`intimate`,`hungry`,`rename_flag`,`incuvate` FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) { Sql_ShowDebug(sql_handle); return 0; } - if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { p->pet_id = pet_id; - Sql_GetData(sql_handle, 1, &data, NULL); p->class_ = atoi(data); - Sql_GetData(sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); - Sql_GetData(sql_handle, 3, &data, NULL); p->account_id = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); p->char_id = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); p->level = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); p->egg_id = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); p->equip = atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); p->intimate = atoi(data); - Sql_GetData(sql_handle, 9, &data, NULL); p->hungry = atoi(data); - Sql_GetData(sql_handle, 10, &data, NULL); p->rename_flag = atoi(data); - Sql_GetData(sql_handle, 11, &data, NULL); p->incuvate = atoi(data); - - Sql_FreeResult(sql_handle); + SQL->GetData(sql_handle, 1, &data, NULL); p->class_ = atoi(data); + SQL->GetData(sql_handle, 2, &data, &len); memcpy(p->name, data, min(len, NAME_LENGTH)); + SQL->GetData(sql_handle, 3, &data, NULL); p->account_id = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); p->char_id = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); p->level = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); p->egg_id = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); p->equip = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); p->intimate = atoi(data); + SQL->GetData(sql_handle, 9, &data, NULL); p->hungry = atoi(data); + SQL->GetData(sql_handle, 10, &data, NULL); p->rename_flag = atoi(data); + SQL->GetData(sql_handle, 11, &data, NULL); p->incuvate = atoi(data); + + SQL->FreeResult(sql_handle); p->hungry = cap_value(p->hungry, 0, 100); p->intimate = cap_value(p->intimate, 0, 1000); @@ -114,7 +115,7 @@ void inter_pet_sql_final(void){ int inter_pet_delete(int pet_id){ ShowInfo("delete pet request: %d...\n",pet_id); - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `pet_id`='%d'", pet_db, pet_id) ) Sql_ShowDebug(sql_handle); return 0; } @@ -184,7 +185,7 @@ int mapif_create_pet(int fd, int account_id, int char_id, short pet_class, short short pet_equip, short intimate, short hungry, char rename_flag, char incuvate, char *pet_name) { memset(pet_pt, 0, sizeof(struct s_pet)); - strncpy(pet_pt->name, pet_name, NAME_LENGTH); + safestrncpy(pet_pt->name, pet_name, NAME_LENGTH); if(incuvate == 1) pet_pt->account_id = pet_pt->char_id = 0; else { diff --git a/src/char/int_quest.c b/src/char/int_quest.c index 224205412..d771543cc 100644 --- a/src/char/int_quest.c +++ b/src/char/int_quest.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/db.h" @@ -55,7 +56,7 @@ int mapif_quests_fromsql(int char_id, struct quest questlog[]) //Delete a quest bool mapif_quest_delete(int char_id, int quest_id) { - if ( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id) ) + if ( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, quest_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; @@ -67,7 +68,7 @@ bool mapif_quest_delete(int char_id, int quest_id) //Add a quest to a questlog bool mapif_quest_add(int char_id, struct quest qd) { - if ( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) ) + if ( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s`(`quest_id`, `char_id`, `state`, `time`, `count1`, `count2`, `count3`) VALUES ('%d', '%d', '%d','%d', '%d', '%d', '%d')", quest_db, qd.quest_id, char_id, qd.state, qd.time, qd.count[0], qd.count[1], qd.count[2]) ) { Sql_ShowDebug(sql_handle); return false; @@ -79,7 +80,7 @@ bool mapif_quest_add(int char_id, struct quest qd) //Update a questlog bool mapif_quest_update(int char_id, struct quest qd) { - if ( SQL_ERROR == Sql_Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) ) + if ( SQL_ERROR == SQL->Query(sql_handle, "UPDATE `%s` SET `state`='%d', `count1`='%d', `count2`='%d', `count3`='%d' WHERE `quest_id` = '%d' AND `char_id` = '%d'", quest_db, qd.state, qd.count[0], qd.count[1], qd.count[2], qd.quest_id, char_id) ) { Sql_ShowDebug(sql_handle); return false; diff --git a/src/char/int_storage.c b/src/char/int_storage.c index 68b588087..429b80105 100644 --- a/src/char/int_storage.c +++ b/src/char/int_storage.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/malloc.h" @@ -37,36 +38,36 @@ int storage_fromsql(int account_id, struct storage_data* p) p->storage_amount = 0; // storage {`account_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`unique_id`"); + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`expire_time`,`unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id); + StrBuf->Printf(&buf, ",`card%d`", j); + StrBuf->Printf(&buf, " FROM `%s` WHERE `account_id`='%d' ORDER BY `nameid`", storage_db, account_id); - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf)) ) Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); - for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < MAX_STORAGE && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { item = &p->items[i]; - Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); item->expire_time = (unsigned int)atoi(data); - Sql_GetData(sql_handle, 8, &data, NULL); item->unique_id = strtoull(data, NULL, 10); + SQL->GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); item->expire_time = (unsigned int)atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); item->unique_id = strtoull(data, NULL, 10); for( j = 0; j < MAX_SLOTS; ++j ) { - Sql_GetData(sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data); + SQL->GetData(sql_handle, 9+j, &data, NULL); item->card[j] = atoi(data); } } p->storage_amount = i; - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); ShowInfo("storage load complete from DB - id: %d (total: %d)\n", account_id, p->storage_amount); return 1; @@ -94,36 +95,36 @@ int guild_storage_fromsql(int guild_id, struct guild_storage* p) p->guild_id = guild_id; // storage {`guild_id`/`id`/`nameid`/`amount`/`equip`/`identify`/`refine`/`attribute`/`card0`/`card1`/`card2`/`card3`} - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`unique_id`"); + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "SELECT `id`,`nameid`,`amount`,`equip`,`identify`,`refine`,`attribute`,`unique_id`"); for( j = 0; j < MAX_SLOTS; ++j ) - StringBuf_Printf(&buf, ",`card%d`", j); - StringBuf_Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id); + StrBuf->Printf(&buf, ",`card%d`", j); + StrBuf->Printf(&buf, " FROM `%s` WHERE `guild_id`='%d' ORDER BY `nameid`", guild_storage_db, guild_id); - if( SQL_ERROR == Sql_Query(sql_handle, StringBuf_Value(&buf)) ) + if( SQL_ERROR == SQL->Query(sql_handle, StrBuf->Value(&buf)) ) Sql_ShowDebug(sql_handle); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); - for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < MAX_GUILD_STORAGE && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { item = &p->items[i]; - Sql_GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); - Sql_GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); item->unique_id = strtoull(data, NULL, 10); + SQL->GetData(sql_handle, 0, &data, NULL); item->id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); item->nameid = atoi(data); + SQL->GetData(sql_handle, 2, &data, NULL); item->amount = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); item->equip = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); item->identify = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); item->refine = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); item->attribute = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); item->unique_id = strtoull(data, NULL, 10); item->expire_time = 0; for( j = 0; j < MAX_SLOTS; ++j ) { - Sql_GetData(sql_handle, 8+j, &data, NULL); item->card[j] = atoi(data); + SQL->GetData(sql_handle, 8+j, &data, NULL); item->card[j] = atoi(data); } } p->storage_amount = i; - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); ShowInfo("guild storage load complete from DB - id: %d (total: %d)\n", guild_id, p->storage_amount); return 0; @@ -144,13 +145,13 @@ void inter_storage_sql_final(void) // q?f[^? int inter_storage_delete(int account_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id`='%d'", storage_db, account_id) ) Sql_ShowDebug(sql_handle); return 0; } int inter_guild_storage_delete(int guild_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `guild_id`='%d'", guild_storage_db, guild_id) ) Sql_ShowDebug(sql_handle); return 0; } @@ -160,9 +161,9 @@ int inter_guild_storage_delete(int guild_id) int mapif_load_guild_storage(int fd,int account_id,int guild_id) { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) Sql_ShowDebug(sql_handle); - else if( Sql_NumRows(sql_handle) > 0 ) + else if( SQL->NumRows(sql_handle) > 0 ) {// guild exists WFIFOHEAD(fd, sizeof(struct guild_storage)+12); WFIFOW(fd,0) = 0x3818; @@ -174,7 +175,7 @@ int mapif_load_guild_storage(int fd,int account_id,int guild_id) return 0; } // guild does not exist - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); WFIFOHEAD(fd, 12); WFIFOW(fd,0) = 0x3818; WFIFOW(fd,2) = 12; @@ -219,16 +220,16 @@ int mapif_parse_SaveGuildStorage(int fd) } else { - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `guild_id` FROM `%s` WHERE `guild_id`='%d'", guild_db, guild_id) ) Sql_ShowDebug(sql_handle); - else if( Sql_NumRows(sql_handle) > 0 ) + else if( SQL->NumRows(sql_handle) > 0 ) {// guild exists - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); guild_storage_tosql(guild_id, (struct guild_storage*)RFIFOP(fd,12)); mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 0); return 0; } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } mapif_save_guild_storage_ack(fd, RFIFOL(fd,4), guild_id, 1); return 0; diff --git a/src/char/inter.c b/src/char/inter.c index 8ff10e290..a1b075a14 100644 --- a/src/char/inter.c +++ b/src/char/inter.c @@ -1,5 +1,6 @@ -// 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 #include "../common/mmo.h" #include "../common/db.h" @@ -43,7 +44,6 @@ char default_codepage[32] = ""; //Feature by irmin. static struct accreg *accreg_pt; unsigned int party_share_level = 10; -char main_chat_nick[16] = "Main"; // recv. packet list int inter_recv_packet_length[] = { @@ -446,43 +446,43 @@ void mapif_parse_accinfo(int fd) { safestrncpy(query, (char*) RFIFOP(fd,14), NAME_LENGTH); - Sql_EscapeString(sql_handle, query_esq, query); + SQL->EscapeString(sql_handle, query_esq, query); account_id = atoi(query); if (account_id < START_ACCOUNT_NUM) { // is string - if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `char` WHERE `name` LIKE '%s' LIMIT 10", query_esq) - || Sql_NumRows(sql_handle) == 0 ) { - if( Sql_NumRows(sql_handle) == 0 ) { + if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id`,`name`,`class`,`base_level`,`job_level`,`online` FROM `char` WHERE `name` LIKE '%s' LIMIT 10", query_esq) + || SQL->NumRows(sql_handle) == 0 ) { + if( SQL->NumRows(sql_handle) == 0 ) { inter_to_fd(fd, u_fd, aid, "No matches were found for your criteria, '%s'",query); } else { Sql_ShowDebug(sql_handle); inter_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it."); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return; } else { - if( Sql_NumRows(sql_handle) == 1 ) {//we found a perfect match - Sql_NextRow(sql_handle); - Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); - Sql_FreeResult(sql_handle); + if( SQL->NumRows(sql_handle) == 1 ) {//we found a perfect match + SQL->NextRow(sql_handle); + SQL->GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); + SQL->FreeResult(sql_handle); } else {// more than one, listing... [Dekamaster/Nightroad] - inter_to_fd(fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)Sql_NumRows(sql_handle)); - while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { + inter_to_fd(fd, u_fd, aid, "Your query returned the following %d results, please be more specific...",(int)SQL->NumRows(sql_handle)); + while ( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { int class_; short base_level, job_level, online; char name[NAME_LENGTH]; - Sql_GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); - Sql_GetData(sql_handle, 2, &data, NULL); class_ = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); base_level = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); job_level = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); online = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); + SQL->GetData(sql_handle, 2, &data, NULL); class_ = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); base_level = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); job_level = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); online = atoi(data); inter_to_fd(fd, u_fd, aid, "[AID: %d] %s | %s | Level: %d/%d | %s", account_id, name, job_name(class_), base_level, job_level, online?"Online":"Offline"); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return; } } @@ -490,30 +490,32 @@ void mapif_parse_accinfo(int fd) { /* it will only get here if we have a single match */ if( account_id ) { - char userid[NAME_LENGTH], user_pass[NAME_LENGTH], email[40], last_ip[20], lastlogin[30]; + char userid[NAME_LENGTH], user_pass[NAME_LENGTH], email[40], last_ip[20], lastlogin[30], pincode[5], birthdate[11]; short level = -1; int logincount = 0,state = 0; - if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `userid`, `user_pass`, `email`, `last_ip`, `group_id`, `lastlogin`, `logincount`, `state` FROM `login` WHERE `account_id` = '%d' LIMIT 1", account_id) - || Sql_NumRows(sql_handle) == 0 ) { - if( Sql_NumRows(sql_handle) == 0 ) { + if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `userid`, `user_pass`, `email`, `last_ip`, `group_id`, `lastlogin`, `logincount`, `state`,`pincode`,`birthdate` FROM `login` WHERE `account_id` = '%d' LIMIT 1", account_id) + || SQL->NumRows(sql_handle) == 0 ) { + if( SQL->NumRows(sql_handle) == 0 ) { inter_to_fd(fd, u_fd, aid, "No account with ID '%d' was found.", account_id ); } else { inter_to_fd(fd, u_fd, aid, "An error occured, bother your admin about it."); Sql_ShowDebug(sql_handle); } } else { - Sql_NextRow(sql_handle); - Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(userid, data, sizeof(userid)); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(user_pass, data, sizeof(user_pass)); - Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(email, data, sizeof(email)); - Sql_GetData(sql_handle, 3, &data, NULL); safestrncpy(last_ip, data, sizeof(last_ip)); - Sql_GetData(sql_handle, 4, &data, NULL); level = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); safestrncpy(lastlogin, data, sizeof(lastlogin)); - Sql_GetData(sql_handle, 6, &data, NULL); logincount = atoi(data); - Sql_GetData(sql_handle, 7, &data, NULL); state = atoi(data); + SQL->NextRow(sql_handle); + SQL->GetData(sql_handle, 0, &data, NULL); safestrncpy(userid, data, sizeof(userid)); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(user_pass, data, sizeof(user_pass)); + SQL->GetData(sql_handle, 2, &data, NULL); safestrncpy(email, data, sizeof(email)); + SQL->GetData(sql_handle, 3, &data, NULL); safestrncpy(last_ip, data, sizeof(last_ip)); + SQL->GetData(sql_handle, 4, &data, NULL); level = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); safestrncpy(lastlogin, data, sizeof(lastlogin)); + SQL->GetData(sql_handle, 6, &data, NULL); logincount = atoi(data); + SQL->GetData(sql_handle, 7, &data, NULL); state = atoi(data); + SQL->GetData(sql_handle, 8, &data, NULL); safestrncpy(pincode, data, sizeof(pincode)); + SQL->GetData(sql_handle, 9, &data, NULL); safestrncpy(birthdate, data, sizeof(birthdate)); } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); if (level == -1) return; @@ -521,19 +523,23 @@ void mapif_parse_accinfo(int fd) { inter_to_fd(fd, u_fd, aid, "-- Account %d --", account_id ); inter_to_fd(fd, u_fd, aid, "User: %s | GM Group: %d | State: %d", userid, level, state ); - if (level < castergroup) /* only show pass if your gm level is greater than the one you're searching for */ - inter_to_fd(fd, u_fd, aid, "Password: %s", user_pass ); + if (level < castergroup) { /* only show pass if your gm level is greater than the one you're searching for */ + if( strlen(pincode) ) + inter_to_fd(fd, u_fd, aid, "Password: %s (PIN:%s)", user_pass, pincode ); + else + inter_to_fd(fd, u_fd, aid, "Password: %s", user_pass ); + } - inter_to_fd(fd, u_fd, aid, "Account e-mail: %s", email); + inter_to_fd(fd, u_fd, aid, "Account e-mail: %s | Birthdate: %s", email, birthdate); inter_to_fd(fd, u_fd, aid, "Last IP: %s (%s)", last_ip, geoip_getcountry(str2ip(last_ip)) ); inter_to_fd(fd, u_fd, aid, "This user has logged %d times, the last time were at %s", logincount, lastlogin ); inter_to_fd(fd, u_fd, aid, "-- Character Details --" ); - if ( SQL_ERROR == Sql_Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `char` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", account_id, MAX_CHARS) - || Sql_NumRows(sql_handle) == 0 ) { + if ( SQL_ERROR == SQL->Query(sql_handle, "SELECT `char_id`, `name`, `char_num`, `class`, `base_level`, `job_level`, `online` FROM `char` WHERE `account_id` = '%d' ORDER BY `char_num` LIMIT %d", account_id, MAX_CHARS) + || SQL->NumRows(sql_handle) == 0 ) { - if( Sql_NumRows(sql_handle) == 0 ) + if( SQL->NumRows(sql_handle) == 0 ) inter_to_fd(fd, u_fd, aid,"This account doesn't have characters."); else { inter_to_fd(fd, u_fd, aid,"An error occured, bother your admin about it."); @@ -541,23 +547,23 @@ void mapif_parse_accinfo(int fd) { } } else { - while ( SQL_SUCCESS == Sql_NextRow(sql_handle) ) { + while ( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { int char_id, class_; short char_num, base_level, job_level, online; char name[NAME_LENGTH]; - Sql_GetData(sql_handle, 0, &data, NULL); char_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); - Sql_GetData(sql_handle, 2, &data, NULL); char_num = atoi(data); - Sql_GetData(sql_handle, 3, &data, NULL); class_ = atoi(data); - Sql_GetData(sql_handle, 4, &data, NULL); base_level = atoi(data); - Sql_GetData(sql_handle, 5, &data, NULL); job_level = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); online = atoi(data); + SQL->GetData(sql_handle, 0, &data, NULL); char_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(name, data, sizeof(name)); + SQL->GetData(sql_handle, 2, &data, NULL); char_num = atoi(data); + SQL->GetData(sql_handle, 3, &data, NULL); class_ = atoi(data); + SQL->GetData(sql_handle, 4, &data, NULL); base_level = atoi(data); + SQL->GetData(sql_handle, 5, &data, NULL); job_level = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); online = atoi(data); inter_to_fd(fd, u_fd, aid, "[Slot/CID: %d/%d] %s | %s | Level: %d/%d | %s", char_num, char_id, name, job_name(class_), base_level, job_level, online?"On":"Off"); } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } return; @@ -579,12 +585,12 @@ int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type switch( type ) { case 3: //Char Reg - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) Sql_ShowDebug(sql_handle); account_id = 0; break; case 2: //Account Reg - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) Sql_ShowDebug(sql_handle); char_id = 0; break; @@ -599,8 +605,8 @@ int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type if( reg->reg_num <= 0 ) return 0; - StringBuf_Init(&buf); - StringBuf_Printf(&buf, "INSERT INTO `%s` (`type`,`account_id`,`char_id`,`str`,`value`) VALUES ", reg_db); + StrBuf->Init(&buf); + StrBuf->Printf(&buf, "INSERT INTO `%s` (`type`,`account_id`,`char_id`,`str`,`value`) VALUES ", reg_db); for( i = 0; i < reg->reg_num; ++i ) { r = ®->reg[i]; @@ -609,20 +615,20 @@ int inter_accreg_tosql(int account_id, int char_id, struct accreg* reg, int type char val[256]; if( i > 0 ) - StringBuf_AppendStr(&buf, ","); + StrBuf->AppendStr(&buf, ","); - Sql_EscapeString(sql_handle, str, r->str); - Sql_EscapeString(sql_handle, val, r->value); + SQL->EscapeString(sql_handle, str, r->str); + SQL->EscapeString(sql_handle, val, r->value); - StringBuf_Printf(&buf, "('%d','%d','%d','%s','%s')", type, account_id, char_id, str, val); + StrBuf->Printf(&buf, "('%d','%d','%d','%s','%s')", type, account_id, char_id, str, val); } } - if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) ) { + if( SQL_ERROR == SQL->QueryStr(sql_handle, StrBuf->Value(&buf)) ) { Sql_ShowDebug(sql_handle); } - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); return 1; } @@ -646,11 +652,11 @@ int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int typ switch( type ) { case 3: //char reg - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=3 AND `char_id`='%d'", reg_db, char_id) ) Sql_ShowDebug(sql_handle); break; case 2: //account reg - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `str`, `value` FROM `%s` WHERE `type`=2 AND `account_id`='%d'", reg_db, account_id) ) Sql_ShowDebug(sql_handle); break; case 1: //account2 reg @@ -660,18 +666,18 @@ int inter_accreg_fromsql(int account_id,int char_id, struct accreg *reg, int typ ShowError("inter_accreg_fromsql: Invalid type %d\n", type); return 0; } - for( i = 0; i < MAX_REG_NUM && SQL_SUCCESS == Sql_NextRow(sql_handle); ++i ) + for( i = 0; i < MAX_REG_NUM && SQL_SUCCESS == SQL->NextRow(sql_handle); ++i ) { r = ®->reg[i]; // str - Sql_GetData(sql_handle, 0, &data, &len); + SQL->GetData(sql_handle, 0, &data, &len); memcpy(r->str, data, min(len, sizeof(r->str))); // value - Sql_GetData(sql_handle, 1, &data, &len); + SQL->GetData(sql_handle, 1, &data, &len); memcpy(r->value, data, min(len, sizeof(r->value))); } reg->reg_num = i; - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return 1; } @@ -726,8 +732,6 @@ static int inter_config_read(const char* cfgName) party_share_level = atoi(w2); else if(!strcmpi(w1,"log_inter")) log_inter = atoi(w2); - else if(!strcmpi(w1,"main_chat_nick")) - safestrncpy(main_chat_nick, w2, sizeof(main_chat_nick)); else if(!strcmpi(w1,"import")) inter_config_read(w2); } @@ -749,8 +753,8 @@ int inter_log(char* fmt, ...) vsnprintf(str, sizeof(str), fmt, ap); va_end(ap); - Sql_EscapeStringLen(sql_handle, esc_str, str, strnlen(str, sizeof(str))); - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')", interlog_db, esc_str) ) + SQL->EscapeStringLen(sql_handle, esc_str, str, strnlen(str, sizeof(str))); + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s` (`time`, `log`) VALUES (NOW(), '%s')", interlog_db, esc_str) ) Sql_ShowDebug(sql_handle); return 0; @@ -764,17 +768,17 @@ int inter_init_sql(const char *file) inter_config_read(file); //DB connection initialized - sql_handle = Sql_Malloc(); + sql_handle = SQL->Malloc(); ShowInfo("Connect Character DB server.... (Character Server)\n"); - if( SQL_ERROR == Sql_Connect(sql_handle, char_server_id, char_server_pw, char_server_ip, (uint16)char_server_port, char_server_db) ) + if( SQL_ERROR == SQL->Connect(sql_handle, char_server_id, char_server_pw, char_server_ip, (uint16)char_server_port, char_server_db) ) { Sql_ShowDebug(sql_handle); - Sql_Free(sql_handle); + SQL->Free(sql_handle); exit(EXIT_FAILURE); } if( *default_codepage ) { - if( SQL_ERROR == Sql_SetEncoding(sql_handle, default_codepage) ) + if( SQL_ERROR == SQL->SetEncoding(sql_handle, default_codepage) ) Sql_ShowDebug(sql_handle); } @@ -931,7 +935,7 @@ int mapif_disconnectplayer(int fd, int account_id, int char_id, int reason) int check_ttl_wisdata_sub(DBKey key, DBData *data, va_list ap) { unsigned long tick; - struct WisData *wd = db_data2ptr(data); + struct WisData *wd = DB->data2ptr(data); tick = va_arg(ap, unsigned long); if (DIFF_TICK(tick, wd->tick) > WISDATA_TTL && wis_delnum < WISDELLIST_MAX) @@ -993,12 +997,12 @@ int mapif_parse_WisRequest(int fd) safestrncpy(name, (char*)RFIFOP(fd,28), NAME_LENGTH); //Received name may be too large and not contain \0! [Skotlex] - Sql_EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) ) + SQL->EscapeStringLen(sql_handle, esc_name, name, strnlen(name, NAME_LENGTH)); + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `name` FROM `%s` WHERE `name`='%s'", char_db, esc_name) ) Sql_ShowDebug(sql_handle); // search if character exists before to ask all map-servers - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { unsigned char buf[27]; WBUFW(buf, 0) = 0x3802; @@ -1009,7 +1013,7 @@ int mapif_parse_WisRequest(int fd) else {// Character exists. So, ask all map-servers // to be sure of the correct name, rewrite it - Sql_GetData(sql_handle, 0, &data, &len); + SQL->GetData(sql_handle, 0, &data, &len); memset(name, 0, NAME_LENGTH); memcpy(name, data, min(len, NAME_LENGTH)); // if source is destination, don't ask other servers. @@ -1041,7 +1045,7 @@ int mapif_parse_WisRequest(int fd) } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return 0; } diff --git a/src/char/inter.h b/src/char/inter.h index 9f99197eb..de27b0473 100644 --- a/src/char/inter.h +++ b/src/char/inter.h @@ -1,5 +1,6 @@ -// 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 _INTER_SQL_H_ #define _INTER_SQL_H_ @@ -23,8 +24,6 @@ extern unsigned int party_share_level; extern Sql* sql_handle; extern Sql* lsql_handle; -extern char main_chat_nick[16]; - int inter_accreg_tosql(int account_id, int char_id, struct accreg *reg, int type); uint64 inter_chk_lastuid(int8 flag, uint64 value); @@ -33,7 +32,7 @@ uint64 inter_chk_lastuid(int8 flag, uint64 value); #define dbUpdateUid(handler_)\ { \ uint64 unique_id_ = inter_chk_lastuid(0, 0); \ - if (unique_id_ && SQL_ERROR == Sql_Query(handler_, "UPDATE `interreg` SET `value`='%"PRIu64"' WHERE `varname`='unique_id'", unique_id_)) \ + if (unique_id_ && SQL_ERROR == SQL->Query(handler_, "UPDATE `interreg` SET `value`='%"PRIu64"' WHERE `varname`='unique_id'", unique_id_)) \ Sql_ShowDebug(handler_);\ } #else diff --git a/src/char/pincode.c b/src/char/pincode.c new file mode 100644 index 000000000..2603df2d8 --- /dev/null +++ b/src/char/pincode.c @@ -0,0 +1,201 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#include "../common/cbasetypes.h" +#include "../common/mmo.h" +#include "../common/random.h" +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/strlib.h" +#include "char.h" +#include "pincode.h" + +#include <stdlib.h> + +int enabled = PINCODE_OK; +int changetime = 0; +int maxtry = 3; +int charselect = 0; +unsigned int multiplier = 0x3498, baseSeed = 0x881234; + +void pincode_handle ( int fd, struct char_session_data* sd ) { + struct online_char_data* character = (struct online_char_data*)idb_get(online_char_db, sd->account_id); + + if( character && character->pincode_enable > *pincode->charselect ){ + character->pincode_enable = *pincode->charselect * 2; + }else{ + pincode->sendstate( fd, sd, PINCODE_OK ); + return; + } + + if( strlen(sd->pincode) == 4 ){ + if( *pincode->changetime && time(NULL) > (sd->pincode_change+*pincode->changetime) ){ // User hasnt changed his PIN code for a long time + pincode->sendstate( fd, sd, PINCODE_EXPIRED ); + } else { // Ask user for his PIN code + pincode->sendstate( fd, sd, PINCODE_ASK ); + } + } else // No PIN code has been set yet + pincode->sendstate( fd, sd, PINCODE_NOTSET ); + + if( character ) + character->pincode_enable = -1; +} + +void pincode_check(int fd, struct char_session_data* sd) { + char pin[5] = "\0\0\0\0"; + + strncpy(pin, (char*)RFIFOP(fd, 6), 4+1); + pincode->decrypt(sd->pincode_seed, pin); + if( pincode->compare( fd, sd, pin ) ){ + struct online_char_data* character; + if( (character = (struct online_char_data*)idb_get(online_char_db, sd->account_id)) ) + character->pincode_enable = *pincode->charselect * 2; + pincode->sendstate( fd, sd, PINCODE_OK ); + } +} + +int pincode_compare(int fd, struct char_session_data* sd, char* pin) { + if( strcmp( sd->pincode, pin ) == 0 ){ + sd->pincode_try = 0; + return 1; + } else { + pincode->sendstate( fd, sd, PINCODE_WRONG ); + if( *pincode->maxtry && ++sd->pincode_try >= *pincode->maxtry ){ + pincode->error( sd->account_id ); + } + return 0; + } +} + +void pincode_change(int fd, struct char_session_data* sd) { + char oldpin[5] = "\0\0\0\0", newpin[5] = "\0\0\0\0"; + + strncpy(oldpin, (char*)RFIFOP(fd,6), sizeof(oldpin)); + pincode->decrypt(sd->pincode_seed,oldpin); + if( !pincode->compare( fd, sd, oldpin ) ) + return; + + strncpy(newpin, (char*)RFIFOP(fd,10), sizeof(newpin)); + pincode->decrypt(sd->pincode_seed,newpin); + pincode->update( sd->account_id, newpin ); + strncpy(sd->pincode, newpin, sizeof(sd->pincode)); + pincode->sendstate( fd, sd, PINCODE_ASK ); +} + +void pincode_setnew(int fd, struct char_session_data* sd) { + char newpin[5] = "\0\0\0\0"; + + strncpy(newpin, (char*)RFIFOP(fd,6), sizeof(newpin)); + pincode->decrypt(sd->pincode_seed,newpin); + pincode->update( sd->account_id, newpin ); + strncpy(sd->pincode, newpin, sizeof(sd->pincode)); + pincode->sendstate( fd, sd, PINCODE_ASK ); +} + +// 0 = pin is correct +// 1 = ask for pin - client sends 0x8b8 +// 2 = create new pin - client sends 0x8ba +// 3 = pin must be changed - client 0x8be +// 4 = create new pin ?? - client sends 0x8ba +// 5 = client shows msgstr(1896) +// 6 = client shows msgstr(1897) Unable to use your KSSN number +// 7 = char select window shows a button - client sends 0x8c5 +// 8 = pincode was incorrect +void pincode_sendstate(int fd, struct char_session_data* sd, uint16 state) { + WFIFOHEAD(fd, 12); + WFIFOW(fd, 0) = 0x8b9; + WFIFOL(fd, 2) = sd->pincode_seed = rand() % 0xFFFF; + WFIFOL(fd, 6) = sd->account_id; + WFIFOW(fd,10) = state; + WFIFOSET(fd,12); +} + +void pincode_notifyLoginPinUpdate(int account_id, char* pin) { + WFIFOHEAD(login_fd,11); + WFIFOW(login_fd,0) = 0x2738; + WFIFOL(login_fd,2) = account_id; + strncpy( (char*)WFIFOP(login_fd,6), pin, 5 ); + WFIFOSET(login_fd,11); +} + +void pincode_notifyLoginPinError(int account_id) { + WFIFOHEAD(login_fd,6); + WFIFOW(login_fd,0) = 0x2739; + WFIFOL(login_fd,2) = account_id; + WFIFOSET(login_fd,6); +} + +void pincode_decrypt(unsigned int userSeed, char* pin) { + int i, pos; + char tab[10] = {0,1,2,3,4,5,6,7,8,9}; + + for( i = 1; i < 10; i++ ){ + userSeed = *pincode->baseSeed + userSeed * *pincode->multiplier; + pos = userSeed % (i + 1); + if( i != pos ){ + tab[i] ^= tab[pos]; + tab[pos] ^= tab[i]; + tab[i] ^= tab[pos]; + } + } + + for( i = 0; i < 4; i++ ){ + pin[i] = tab[pin[i] - '0']; + } + + sprintf(pin, "%d%d%d%d", pin[0], pin[1], pin[2], pin[3]); +} + +bool pincode_config_read(char *w1, char *w2) { + + while ( true ) { + + if ( strcmpi(w1, "pincode_enabled") == 0 ) { + enabled = atoi(w2); +#if PACKETVER < 20110309 + if( enabled ) { + ShowWarning("pincode_enabled requires PACKETVER 20110309 or higher. disabling...\n"); + enabled = 0; + } +#endif + } else if ( strcmpi(w1, "pincode_changetime") == 0 ) { + changetime = atoi(w2)*60; + } else if ( strcmpi(w1, "pincode_maxtry") == 0 ) { + maxtry = atoi(w2); + if( maxtry > 3 ) { + ShowWarning("pincode_maxtry is too high (%d); maximum allowed: 3! capping to 3...\n",maxtry); + maxtry = 3; + } + } else if ( strcmpi(w1, "pincode_charselect") == 0 ) { + charselect = atoi(w2); + } else + return false; + + break; + } + + return true; +} + +void pincode_defaults(void) { + pincode = &pincode_s; + + pincode->enabled = &enabled; + pincode->changetime = &changetime; + pincode->maxtry = &maxtry; + pincode->charselect = &charselect; + pincode->multiplier = &multiplier; + pincode->baseSeed = &baseSeed; + + pincode->handle = pincode_handle; + pincode->decrypt = pincode_decrypt; + pincode->error = pincode_notifyLoginPinError; + pincode->update = pincode_notifyLoginPinUpdate; + pincode->sendstate = pincode_sendstate; + pincode->setnew = pincode_setnew; + pincode->change = pincode_change; + pincode->compare = pincode_compare; + pincode->check = pincode_check; + pincode->config_read = pincode_config_read; + +} diff --git a/src/char/pincode.h b/src/char/pincode.h new file mode 100644 index 000000000..358f21ff7 --- /dev/null +++ b/src/char/pincode.h @@ -0,0 +1,42 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#ifndef _PINCODE_H_ +#define _PINCODE_H_ + +#include "char.h" + +#define PINCODE_OK 0 +#define PINCODE_ASK 1 +#define PINCODE_NOTSET 2 +#define PINCODE_EXPIRED 3 +#define PINCODE_UNUSED 7 +#define PINCODE_WRONG 8 + +/* Pincode Interface */ +struct pincode_interface { + /* vars */ + int *enabled; + int *changetime; + int *maxtry; + int *charselect; + unsigned int *multiplier; + unsigned int *baseSeed; + /* handler */ + void (*handle) (int fd, struct char_session_data* sd); + void (*decrypt) (unsigned int userSeed, char* pin); + void (*error) (int account_id); + void (*update) (int account_id, char* pin); + void (*sendstate) (int fd, struct char_session_data* sd, uint16 state); + void (*setnew) (int fd, struct char_session_data* sd); + void (*change) (int fd, struct char_session_data* sd); + int (*compare) (int fd, struct char_session_data* sd, char* pin); + void (*check) (int fd, struct char_session_data* sd); + bool (*config_read) (char *w1, char *w2); +} pincode_s; + +struct pincode_interface *pincode; + +void pincode_defaults(void); + +#endif /* _PINCODE_H_ */ diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index e8c6c0a70..dbc30734c 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -36,6 +36,7 @@ set( COMMON_ALL_HEADERS set( COMMON_MINI_HEADERS ${COMMON_ALL_HEADERS} "${COMMON_SOURCE_DIR}/core.h" + "${COMMON_SOURCE_DIR}/console.h" "${COMMON_SOURCE_DIR}/malloc.h" "${COMMON_SOURCE_DIR}/showmsg.h" "${COMMON_SOURCE_DIR}/strlib.h" @@ -43,6 +44,7 @@ set( COMMON_MINI_HEADERS CACHE INTERNAL "" ) set( COMMON_MINI_SOURCES "${COMMON_SOURCE_DIR}/core.c" + "${COMMON_SOURCE_DIR}/console.c" "${COMMON_SOURCE_DIR}/malloc.c" "${COMMON_SOURCE_DIR}/showmsg.c" "${COMMON_SOURCE_DIR}/strlib.c" @@ -61,10 +63,13 @@ set( COMMON_BASE_HEADERS ${COMMON_ALL_HEADERS} "${COMMON_SOURCE_DIR}/conf.h" "${COMMON_SOURCE_DIR}/core.h" + "${COMMON_SOURCE_DIR}/console.h" "${COMMON_SOURCE_DIR}/db.h" "${COMMON_SOURCE_DIR}/des.h" "${COMMON_SOURCE_DIR}/ers.h" "${COMMON_SOURCE_DIR}/grfio.h" + "${COMMON_SOURCE_DIR}/HPM.h" + "${COMMON_SOURCE_DIR}/HPMi.h" "${COMMON_SOURCE_DIR}/malloc.h" "${COMMON_SOURCE_DIR}/mapindex.h" "${COMMON_SOURCE_DIR}/md5calc.h" @@ -86,10 +91,12 @@ set( COMMON_BASE_HEADERS set( COMMON_BASE_SOURCES "${COMMON_SOURCE_DIR}/conf.c" "${COMMON_SOURCE_DIR}/core.c" + "${COMMON_SOURCE_DIR}/console.c" "${COMMON_SOURCE_DIR}/db.c" "${COMMON_SOURCE_DIR}/des.c" "${COMMON_SOURCE_DIR}/ers.c" "${COMMON_SOURCE_DIR}/grfio.c" + "${COMMON_SOURCE_DIR}/HPM.c" "${COMMON_SOURCE_DIR}/malloc.c" "${COMMON_SOURCE_DIR}/mapindex.c" "${COMMON_SOURCE_DIR}/md5calc.c" diff --git a/src/common/HPM.c b/src/common/HPM.c new file mode 100644 index 000000000..28ea8f413 --- /dev/null +++ b/src/common/HPM.c @@ -0,0 +1,362 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#include "../common/cbasetypes.h" +#include "../common/mmo.h" +#include "../common/core.h" +#include "../common/malloc.h" +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/conf.h" +#include "../common/utils.h" +#include "../common/console.h" +#include "../common/strlib.h" +#include "../common/sql.h" +#include "HPM.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#ifndef WIN32 +#include <unistd.h> +#endif + +void hplugin_trigger_event(enum hp_event_types type) { + unsigned int i; + for( i = 0; i < HPM->plugin_count; i++ ) { + if( HPM->plugins[i]->hpi->event[type] != NULL ) + (HPM->plugins[i]->hpi->event[type])(); + } +} + +void hplugin_export_symbol(void *var, char *name) { + RECREATE(HPM->symbols, struct hpm_symbol *, ++HPM->symbol_count); + CREATE(HPM->symbols[HPM->symbol_count - 1] ,struct hpm_symbol, 1); + HPM->symbols[HPM->symbol_count - 1]->name = name; + HPM->symbols[HPM->symbol_count - 1]->ptr = var; +} + +void *hplugin_import_symbol(char *name) { + unsigned int i; + + for( i = 0; i < HPM->symbol_count; i++ ) { + if( strcmp(HPM->symbols[i]->name,name) == 0 ) + return HPM->symbols[i]->ptr; + } + + ShowError("HPM:get_symbol: '"CL_WHITE"%s"CL_RESET"' not found!\n",name); + return NULL; +} + +bool hplugin_iscompatible(char* version) { + unsigned int req_major = 0, req_minor = 0; + + if( version == NULL ) + return false; + + sscanf(version, "%u.%u", &req_major, &req_minor); + + return ( req_major == HPM->version[0] && req_minor <= HPM->version[1] ) ? true : false; +} + +bool hplugin_exists(const char *filename) { + unsigned int i; + for(i = 0; i < HPM->plugin_count; i++) { + if( strcmpi(HPM->plugins[i]->filename,filename) == 0 ) + return true; + } + return false; +} +struct hplugin *hplugin_create(void) { + RECREATE(HPM->plugins, struct hplugin *, ++HPM->plugin_count); + CREATE(HPM->plugins[HPM->plugin_count - 1], struct hplugin, 1); + HPM->plugins[HPM->plugin_count - 1]->idx = HPM->plugin_count - 1; + HPM->plugins[HPM->plugin_count - 1]->filename = NULL; + return HPM->plugins[HPM->plugin_count - 1]; +} +#define HPM_POP(x) { #x , x } +bool hplugin_populate(struct hplugin *plugin, const char *filename) { + void **Link; + struct { + const char* name; + void *Ref; + } ToLink[] = { + HPM_POP(ShowMessage), + HPM_POP(ShowStatus), + HPM_POP(ShowSQL), + HPM_POP(ShowInfo), + HPM_POP(ShowNotice), + HPM_POP(ShowWarning), + HPM_POP(ShowDebug), + HPM_POP(ShowError), + HPM_POP(ShowFatalError), + }; + int i, length = ARRAYLENGTH(ToLink); + + for(i = 0; i < length; i++) { + if( !( Link = plugin_import(plugin->dll, ToLink[i].name,void **) ) ) { + ShowWarning("HPM:plugin_load: failed to retrieve '%s' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", ToLink[i].name, filename); + HPM->unload(plugin); + return false; + } + *Link = ToLink[i].Ref; + } + + return true; +} +void hplugin_load(const char* filename) { + struct hplugin *plugin; + struct hplugin_info *info; + struct HPMi_interface **HPMi; + bool anyEvent = false; + void **import_symbol_ref; + Sql **sql_handle; + + if( HPM->exists(filename) ) { + ShowWarning("HPM:plugin_load: attempting to load duplicate '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + return; + } + + plugin = HPM->create(); + + if( !( plugin->dll = plugin_open(filename) ) ){ + ShowWarning("HPM:plugin_load: failed to load '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + HPM->unload(plugin); + return; + } + + if( !( info = plugin_import(plugin->dll, "pinfo",struct hplugin_info*) ) ) { + ShowDebug("HPM:plugin_load: failed to retrieve 'plugin_info' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + HPM->unload(plugin); + return; + } + + if( !(info->type & SERVER_TYPE) ) { + HPM->unload(plugin); + return; + } + + if( !HPM->iscompatible(info->req_version) ) { + ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' incompatible version '%s' -> '%s', skipping...\n", filename, info->req_version, HPM_VERSION); + HPM->unload(plugin); + return; + } + + if( !( import_symbol_ref = plugin_import(plugin->dll, "import_symbol",void **) ) ) { + ShowWarning("HPM:plugin_load: failed to retrieve 'import_symbol' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + HPM->unload(plugin); + return; + } + + *import_symbol_ref = HPM->import_symbol; + + if( !( sql_handle = plugin_import(plugin->dll, "mysql_handle",Sql **) ) ) { + ShowWarning("HPM:plugin_load: failed to retrieve 'mysql_handle' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + HPM->unload(plugin); + return; + } + + *sql_handle = HPM->import_symbol("sql_handle"); + + if( !( HPMi = plugin_import(plugin->dll, "HPMi",struct HPMi_interface **) ) ) { + ShowWarning("HPM:plugin_load: failed to retrieve 'HPMi' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + HPM->unload(plugin); + return; + } + + if( !( *HPMi = plugin_import(plugin->dll, "HPMi_s",struct HPMi_interface *) ) ) { + ShowWarning("HPM:plugin_load: failed to retrieve 'HPMi_s' for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + HPM->unload(plugin); + return; + } + plugin->hpi = *HPMi; + + if( ( plugin->hpi->event[HPET_INIT] = plugin_import(plugin->dll, "plugin_init",void (*)(void)) ) ) + anyEvent = true; + + if( ( plugin->hpi->event[HPET_FINAL] = plugin_import(plugin->dll, "plugin_final",void (*)(void)) ) ) + anyEvent = true; + + if( ( plugin->hpi->event[HPET_READY] = plugin_import(plugin->dll, "server_online",void (*)(void)) ) ) + anyEvent = true; + + if( !anyEvent ) { + ShowWarning("HPM:plugin_load: no events found for '"CL_WHITE"%s"CL_RESET"', skipping...\n", filename); + HPM->unload(plugin); + return; + } + + if( !HPM->populate(plugin,filename) ) + return; + + if( SERVER_TYPE == SERVER_TYPE_MAP ) { + plugin->hpi->addCommand = HPM->import_symbol("addCommand"); + plugin->hpi->addScript = HPM->import_symbol("addScript"); + plugin->hpi->addCPCommand = HPM->import_symbol("addCPCommand"); + } + + plugin->info = info; + plugin->filename = aStrdup(filename); + + return; +} + +void hplugin_unload(struct hplugin* plugin) { + unsigned int i = plugin->idx, cursor = 0; + + if( plugin->filename ) + aFree(plugin->filename); + if( plugin->dll ) + plugin_close(plugin->dll); + + aFree(plugin); + if( !HPM->off ) { + HPM->plugins[i] = NULL; + for(i = 0; i < HPM->plugin_count; i++) { + if( HPM->plugins[i] == NULL ) + continue; + if( cursor != i ) + HPM->plugins[cursor] = HPM->plugins[i]; + cursor++; + } + if( !(HPM->plugin_count = cursor) ) { + aFree(HPM->plugins); + HPM->plugins = NULL; + } + } +} + +void hplugins_config_read(void) { + config_t plugins_conf; + config_setting_t *plist = NULL; + const char *config_filename = "conf/plugins.conf"; // FIXME hardcoded name + + if (conf_read_file(&plugins_conf, config_filename)) + return; + + if( HPM->symbol_defaults_sub ) + HPM->symbol_defaults_sub(); + + plist = config_lookup(&plugins_conf, "plugins_list"); + + if (plist != NULL) { + int length = config_setting_length(plist), i; + char filename[60]; + for(i = 0; i < length; i++) { + snprintf(filename, 60, "plugins/%s%s", config_setting_get_string_elem(plist,i), DLL_EXT); + HPM->load(filename); + } + config_destroy(&plugins_conf); + } + + if( HPM->plugin_count ) + ShowStatus("HPM: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded, type '"CL_WHITE"plugins"CL_RESET"' to list them\n", HPM->plugin_count); +} +void hplugins_share_defaults(void) { + /* console */ + HPM->share(console->addCommand,"addCPCommand"); + /* core */ + HPM->share(&runflag,"runflag"); + HPM->share(arg_v,"arg_v"); + HPM->share(&arg_c,"arg_c"); + HPM->share(SERVER_NAME,"SERVER_NAME"); + HPM->share(&SERVER_TYPE,"SERVER_TYPE"); + HPM->share((void*)get_svn_revision,"get_svn_revision"); + HPM->share((void*)get_git_hash,"get_git_hash"); + HPM->share(DB, "DB"); + HPM->share(malloclib, "malloclib"); + /* socket */ + HPM->share(RFIFOSKIP,"RFIFOSKIP"); + HPM->share(WFIFOSET,"WFIFOSET"); + HPM->share(do_close,"do_close"); + HPM->share(make_connection,"make_connection"); + HPM->share(session,"session"); + HPM->share(&fd_max,"fd_max"); + HPM->share(addr_,"addr"); + /* strlib */ + HPM->share(strlib,"strlib"); + HPM->share(sv,"sv"); + HPM->share(StrBuf,"StrBuf"); + /* sql */ + HPM->share(SQL,"SQL"); + /* timer */ + HPM->share(gettick,"gettick"); + HPM->share(add_timer,"add_timer"); + HPM->share(add_timer_interval,"add_timer_interval"); + HPM->share(add_timer_func_list,"add_timer_func_list"); + HPM->share(delete_timer,"delete_timer"); + HPM->share(get_uptime,"get_uptime"); +} +CPCMD(plugins) { + if( HPM->plugin_count == 0 ) { + ShowInfo("HPC: there are no plugins loaded\n"); + } else { + unsigned int i; + + ShowInfo("HPC: There are '"CL_WHITE"%d"CL_RESET"' plugins loaded\n",HPM->plugin_count); + + for(i = 0; i < HPM->plugin_count; i++) { + ShowInfo("HPC: - '"CL_WHITE"%s"CL_RESET"' (%s)\n",HPM->plugins[i]->info->name,HPM->plugins[i]->filename); + } + } +} +void hpm_init(void) { + HPM->symbols = NULL; + HPM->plugins = NULL; + HPM->plugin_count = HPM->symbol_count = 0; + HPM->off = false; + + sscanf(HPM_VERSION, "%d.%d", &HPM->version[0], &HPM->version[1]); + + if( HPM->version[0] == 0 && HPM->version[1] == 0 ) { + ShowError("HPM:init:failed to retrieve HPM version!!\n"); + return; + } + HPM->symbol_defaults(); + + console->addCommand("plugins",CPCMD_A(plugins)); + + return; +} + +void hpm_final(void) { + unsigned int i; + + HPM->off = true; + + for( i = 0; i < HPM->plugin_count; i++ ) { + HPM->unload(HPM->plugins[i]); + } + + if( HPM->plugins ) + aFree(HPM->plugins); + + for( i = 0; i < HPM->symbol_count; i++ ) { + aFree(HPM->symbols[i]); + } + + if( HPM->symbols ) + aFree(HPM->symbols); + + return; +} +void hpm_defaults(void) { + HPM = &HPM_s; + + HPM->init = hpm_init; + HPM->final = hpm_final; + + HPM->create = hplugin_create; + HPM->load = hplugin_load; + HPM->unload = hplugin_unload; + HPM->event = hplugin_trigger_event; + HPM->exists = hplugin_exists; + HPM->iscompatible = hplugin_iscompatible; + HPM->import_symbol = hplugin_import_symbol; + HPM->share = hplugin_export_symbol; + HPM->symbol_defaults = hplugins_share_defaults; + HPM->config_read = hplugins_config_read; + HPM->populate = hplugin_populate; + HPM->symbol_defaults_sub = NULL; +} diff --git a/src/common/HPM.h b/src/common/HPM.h new file mode 100644 index 000000000..10b1f0e79 --- /dev/null +++ b/src/common/HPM.h @@ -0,0 +1,83 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#ifndef _HPM_H_ +#define _HPM_H_ + +#include "../common/cbasetypes.h" +#include "../common/HPMi.h" + +#ifdef WIN32 + #ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN + #endif + #include <windows.h> + #define plugin_open(x) LoadLibraryA(x) + #define plugin_import(x,y,z) (z)GetProcAddress(x,y) + #define plugin_close(x) FreeLibrary(x) + + #define DLL_EXT ".dll" + #define DLL HINSTANCE +#else + #include <dlfcn.h> + #define plugin_open(x) dlopen(x,RTLD_NOW) + #define plugin_import(x,y,z) (z)dlsym(x,y) + #define plugin_close(x) dlclose(x) + + #ifdef CYGWIN + #define DLL_EXT ".dll" + #else + #define DLL_EXT ".so" + #endif + + #define DLL void * + + #include <string.h> // size_t + +#endif + +struct hplugin { + DLL dll; + unsigned int idx; + char *filename; + struct hplugin_info *info; + struct HPMi_interface *hpi; +}; + +struct hpm_symbol { + char *name; + void *ptr; +}; + +/* Hercules Plugin Manager Interface */ +struct HPM_interface { + /* vars */ + unsigned int version[2]; + bool off; + /* data */ + struct hplugin **plugins; + unsigned int plugin_count; + struct hpm_symbol **symbols; + unsigned int symbol_count; + /* funcs */ + void (*init) (void); + void (*final) (void); + struct hplugin * (*create) (void); + void (*load) (const char* filename); + void (*unload) (struct hplugin* plugin); + bool (*exists) (const char *filename); + bool (*iscompatible) (char* version); + void (*event) (enum hp_event_types type); + void *(*import_symbol) (char *); + void (*share) (void *, char *); + void (*symbol_defaults) (void); + void (*config_read) (void); + bool (*populate) (struct hplugin *plugin,const char *filename); + void (*symbol_defaults_sub) (void); +} HPM_s; + +struct HPM_interface *HPM; + +void hpm_defaults(void); + +#endif /* _HPM_H_ */ diff --git a/src/common/HPMi.h b/src/common/HPMi.h new file mode 100644 index 000000000..3cdb804e0 --- /dev/null +++ b/src/common/HPMi.h @@ -0,0 +1,70 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#ifndef _HPMi_H_ +#define _HPMi_H_ + +#include "../common/cbasetypes.h" +#include "../common/core.h" +#include "../common/console.h" +#include "../common/sql.h" + +struct script_state; +struct AtCommandInfo; + +#ifdef WIN32 + #define HPExport __declspec(dllexport) +#else + #define HPExport +#endif + +#ifndef _SHOWMSG_H_ + HPExport void (*ShowMessage) (const char *, ...); + HPExport void (*ShowStatus) (const char *, ...); + HPExport void (*ShowSQL) (const char *, ...); + HPExport void (*ShowInfo) (const char *, ...); + HPExport void (*ShowNotice) (const char *, ...); + HPExport void (*ShowWarning) (const char *, ...); + HPExport void (*ShowDebug) (const char *, ...); + HPExport void (*ShowError) (const char *, ...); + HPExport void (*ShowFatalError) (const char *, ...); +#endif + +/* after */ +#include "../common/showmsg.h" + +#define HPM_VERSION "0.1" + +struct hplugin_info { + char* name; + enum server_types type; + char* version; + char* req_version; +}; + +HPExport void *(*import_symbol) (char *name); +HPExport Sql *mysql_handle; + +#define GET_SYMBOL(n) import_symbol(n) + +#define SERVER_TYPE_ALL SERVER_TYPE_LOGIN|SERVER_TYPE_CHAR|SERVER_TYPE_MAP + +enum hp_event_types { + HPET_INIT,/* server starts */ + HPET_FINAL,/* server is shutting down */ + HPET_READY,/* server is ready (online) */ + HPET_MAX, +}; + +/* Hercules Plugin Mananger Include Interface */ +HPExport struct HPMi_interface { + void (*event[HPET_MAX]) (void); + bool (*addCommand) (char *name, bool (*func)(const int fd, struct map_session_data* sd, const char* command, const char* message,struct AtCommandInfo *info)); + bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st)); + void (*addCPCommand) (char *name, CParseFunc func); +} HPMi_s; +#ifndef _HPM_H_ + HPExport struct HPMi_interface *HPMi; +#endif + +#endif /* _HPMi_H_ */ diff --git a/src/common/Makefile.in b/src/common/Makefile.in index c24499c02..279f82e5f 100644 --- a/src/common/Makefile.in +++ b/src/common/Makefile.in @@ -1,9 +1,10 @@ -COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o \ +COMMON_OBJ = obj_all/core.o obj_all/socket.o obj_all/timer.o obj_all/db.o obj_all/HPM.o \ obj_all/nullpo.o obj_all/malloc.o obj_all/showmsg.o obj_all/strlib.o obj_all/utils.o \ obj_all/grfio.o obj_all/mapindex.o obj_all/ers.o obj_all/md5calc.o \ obj_all/minicore.o obj_all/minisocket.o obj_all/minimalloc.o obj_all/random.o obj_all/des.o \ - obj_all/conf.o obj_all/thread.o obj_all/mutex.o obj_all/raconf.o obj_all/mempool.o + obj_all/conf.o obj_all/thread.o obj_all/mutex.o obj_all/raconf.o obj_all/mempool.o obj_all/console.o \ + obj_all/miniconsole.o COMMON_H = $(shell ls ../common/*.h) diff --git a/src/common/console.c b/src/common/console.c new file mode 100644 index 000000000..ba93b8e09 --- /dev/null +++ b/src/common/console.c @@ -0,0 +1,409 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams + +#include "../common/showmsg.h" +#include "../common/core.h" +#include "../config/core.h" +#include "console.h" + +#ifndef MINICORE + #include "../common/ers.h" + #include "../common/malloc.h" + #include "../common/atomic.h" + #include "../common/spinlock.h" + #include "../common/thread.h" + #include "../common/mutex.h" + #include "../common/timer.h" + #include "../common/strlib.h" +#endif + +#include <stdio.h> +#include <stdlib.h> +#ifndef _WIN32 + #include <unistd.h> +#else + #include "../common/winapi.h" // Console close event handling +#endif + +#ifdef CONSOLE_INPUT + #ifdef _WIN32 + #include <conio.h> /* _kbhit() */ + #endif +#endif + +struct console_interface console_s; + +/*====================================== + * CORE : Display title + *--------------------------------------*/ +void display_title(void) { + const char* svn = get_svn_revision(); + const char* git = get_git_hash(); + + ShowMessage("\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" Hercules Development Team presents "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" _ _ _ "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | | | "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | |_| | ___ _ __ ___ _ _| | ___ ___ "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | _ |/ _ \\ '__/ __| | | | |/ _ \\/ __|"CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" | | | | __/ | | (__| |_| | | __/\\__ \\"CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" \\_| |_/\\___|_| \\___|\\__,_|_|\\___||___/"CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" http://hercules.ws/board/ "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + ShowMessage(""CL_BG_RED" "CL_BT_WHITE" "CL_BG_RED""CL_CLL""CL_NORMAL"\n"); + + if( git[0] != HERC_UNKNOWN_VER ) + ShowInfo("Git Hash: '"CL_WHITE"%s"CL_RESET"'\n", git); + else if( svn[0] != HERC_UNKNOWN_VER ) + ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'\n", svn); +} +#ifdef CONSOLE_INPUT +#ifdef _WIN32 +int console_parse_key_pressed(void) { + return _kbhit(); +} +#else /* _WIN32 */ +int console_parse_key_pressed(void) { + struct timeval tv; + fd_set fds; + tv.tv_sec = 0; + tv.tv_usec = 0; + + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + + select(STDIN_FILENO+1, &fds, NULL, NULL, &tv); + + return FD_ISSET(STDIN_FILENO, &fds); +} +#endif /* _WIN32 */ +CPCMD(exit) { + runflag = 0; +} +CPCMD(ers_report) { + ers_report(); +} +CPCMD(help) { + unsigned int i = 0; + for ( i = 0; i < console->cmd_list_count; i++ ) { + if( console->cmd_list[i]->next_count ) { + ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",console->cmd_list[i]->cmd); + console->parse_list_subs(console->cmd_list[i],2); + } else { + ShowInfo("- '"CL_WHITE"%s"CL_RESET"'\n",console->cmd_list[i]->cmd); + } + } +} +/* [Ind/Hercules] */ +CPCMD(malloc_usage) { + unsigned int val = (unsigned int)malloclib->usage(); + ShowInfo("malloc_usage: %.2f MB\n",(double)(val)/1024); +} +#define CP_DEF_C(x) { #x , NULL , NULL, NULL } +#define CP_DEF_C2(x,y) { #x , NULL , #y, NULL } +#define CP_DEF_S(x,y) { #x , console_parse_ ## x , #y, NULL } +#define CP_DEF(x) { #x , console_parse_ ## x , NULL, NULL } +void console_load_defaults(void) { + struct { + char *name; + CParseFunc func; + char *connect; + struct CParseEntry *self; + } default_list[] = { + CP_DEF(help), + CP_DEF_C(server), + CP_DEF_S(ers_report,server), + CP_DEF_S(malloc_usage,server), + CP_DEF_S(exit,server), + }; + unsigned int i, len = ARRAYLENGTH(default_list); + struct CParseEntry *cmd; + + RECREATE(console->cmds,struct CParseEntry *, len); + + for(i = 0; i < len; i++) { + CREATE(cmd, struct CParseEntry, 1); + + safestrncpy(cmd->cmd, default_list[i].name, CP_CMD_LENGTH); + + if( default_list[i].func ) + cmd->u.func = default_list[i].func; + else + cmd->u.next = NULL; + + cmd->next_count = 0; + + console->cmd_count++; + console->cmds[i] = cmd; + default_list[i].self = cmd; + if( !default_list[i].connect ) { + RECREATE(console->cmd_list,struct CParseEntry *, ++console->cmd_list_count); + console->cmd_list[console->cmd_list_count - 1] = cmd; + } + } + + for(i = 0; i < len; i++) { + unsigned int k; + if( !default_list[i].connect ) + continue; + for(k = 0; k < console->cmd_count; k++) { + if( strcmpi(default_list[i].connect,console->cmds[k]->cmd) == 0 ) { + cmd = default_list[i].self; + RECREATE(console->cmds[k]->u.next, struct CParseEntry *, ++console->cmds[k]->next_count); + console->cmds[k]->u.next[console->cmds[k]->next_count - 1] = cmd; + break; + } + } + } +} +void console_parse_create(char *name, CParseFunc func) { + unsigned int i; + char *tok; + char sublist[CP_CMD_LENGTH * 5]; + struct CParseEntry *cmd; + + safestrncpy(sublist, name, CP_CMD_LENGTH * 5); + tok = strtok(sublist,":"); + + for ( i = 0; i < console->cmd_list_count; i++ ) { + if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 ) + break; + } + + if( i == console->cmd_list_count ) { + RECREATE(console->cmds,struct CParseEntry *, ++console->cmd_count); + CREATE(cmd, struct CParseEntry, 1); + safestrncpy(cmd->cmd, tok, CP_CMD_LENGTH); + cmd->next_count = 0; + console->cmds[console->cmd_count - 1] = cmd; + RECREATE(console->cmd_list,struct CParseEntry *, ++console->cmd_list_count); + console->cmd_list[console->cmd_list_count - 1] = cmd; + i = console->cmd_list_count - 1; + } + + cmd = console->cmd_list[i]; + while( ( tok = strtok(NULL, ":") ) != NULL ) { + + for(i = 0; i < cmd->next_count; i++) { + if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 ) + break; + } + + if ( i == cmd->next_count ) { + RECREATE(console->cmds,struct CParseEntry *, ++console->cmd_count); + CREATE(console->cmds[console->cmd_count-1], struct CParseEntry, 1); + safestrncpy(console->cmds[console->cmd_count-1]->cmd, tok, CP_CMD_LENGTH); + console->cmds[console->cmd_count-1]->next_count = 0; + RECREATE(cmd->u.next, struct CParseEntry *, ++cmd->next_count); + cmd->u.next[cmd->next_count - 1] = console->cmds[console->cmd_count-1]; + cmd = console->cmds[console->cmd_count-1]; + continue; + } + + } + cmd->u.func = func; +} +void console_parse_list_subs(struct CParseEntry *cmd, unsigned char depth) { + unsigned int i; + char msg[CP_CMD_LENGTH * 2]; + for( i = 0; i < cmd->next_count; i++ ) { + if( cmd->u.next[i]->next_count ) { + memset(msg, '-', depth); + snprintf(msg + depth,CP_CMD_LENGTH * 2, " '"CL_WHITE"%s"CL_RESET"'",cmd->u.next[i]->cmd); + ShowInfo("%s subs\n",msg); + console->parse_list_subs(cmd->u.next[i],depth + 1); + } else { + memset(msg, '-', depth); + snprintf(msg + depth,CP_CMD_LENGTH * 2, " %s",cmd->u.next[i]->cmd); + ShowInfo("%s\n",msg); + } + } +} +void console_parse_sub(char *line) { + struct CParseEntry *cmd; + char bline[200]; + char *tok; + char sublist[CP_CMD_LENGTH * 5]; + unsigned int i, len = 0; + memcpy(bline, line, 200); + tok = strtok(line, " "); + for ( i = 0; i < console->cmd_list_count; i++ ) { + if( strcmpi(tok,console->cmd_list[i]->cmd) == 0 ) + break; + } + + if( i == console->cmd_list_count ) { + ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known command, type '"CL_WHITE"help"CL_RESET"' to list all commands\n",line); + return; + } + + cmd = console->cmd_list[i]; + + len += snprintf(sublist,CP_CMD_LENGTH * 5,"%s", cmd->cmd) + 1; + + if( cmd->next_count == 0 && console->cmd_list[i]->u.func ) { + char *r = NULL; + if( (tok = strtok(NULL, " ")) ) { + r = bline; + r += len + 1; + } + cmd->u.func(r); + } else { + while( ( tok = strtok(NULL, " ") ) != NULL ) { + for( i = 0; i < cmd->next_count; i++ ) { + if( strcmpi(cmd->u.next[i]->cmd,tok) == 0 ) + break; + } + if( i == cmd->next_count ) { + if( strcmpi("help",tok) == 0 ) { + if( cmd->next_count ) { + ShowInfo("- '"CL_WHITE"%s"CL_RESET"' subs\n",sublist); + console->parse_list_subs(cmd,2); + } else { + ShowError("'"CL_WHITE"%s"CL_RESET"' doesn't possess any subcommands\n",sublist); + } + return; + } + ShowError("'"CL_WHITE"%s"CL_RESET"' is not a known subcommand of '"CL_WHITE"%s"CL_RESET"'\n",tok,cmd->cmd); + ShowError("type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist); + return; + } + if( cmd->u.next[i]->next_count == 0 && cmd->u.next[i]->u.func ) { + char *r = NULL; + if( (tok = strtok(NULL, " ")) ) { + r = bline; + r += len + strlen(cmd->u.next[i]->cmd) + 1; + } + cmd->u.next[i]->u.func(r); + return; + } else + cmd = cmd->u.next[i]; + len += snprintf(sublist + len,CP_CMD_LENGTH * 5,":%s", cmd->cmd); + } + ShowError("it is only a category, type '"CL_WHITE"%s help"CL_RESET"' to list its subcommands\n",sublist); + } +} +void console_parse(char* line) { + int c, i = 0, len = MAX_CONSOLE_INPUT - 1;/* we leave room for the \0 :P */ + + while( (c = fgetc(stdin)) != EOF ) { + if( --len == 0 ) + break; + if( (line[i++] = c) == '\n') { + line[i-1] = '\0';/* clear, we skip the new line */ + break;/* new line~! we leave it for the next cycle */ + } + } + + line[i++] = '\0'; +} +void *cThread_main(void *x) { + + while( console->ptstate ) {/* loopx */ + if( console->key_pressed() ) { + char input[MAX_CONSOLE_INPUT]; + + console->parse(input); + if( input[0] != '\0' ) {/* did we get something? */ + EnterSpinLock(&console->ptlock); + + if( cinput.count == CONSOLE_PARSE_SIZE ) { + LeaveSpinLock(&console->ptlock); + continue;/* drop */ + } + + safestrncpy(cinput.queue[cinput.count++],input,MAX_CONSOLE_INPUT); + LeaveSpinLock(&console->ptlock); + } + } + ramutex_lock( console->ptmutex ); + racond_wait( console->ptcond, console->ptmutex, -1 ); + ramutex_unlock( console->ptmutex ); + } + + return NULL; +} +int console_parse_timer(int tid, unsigned int tick, int id, intptr_t data) { + int i; + EnterSpinLock(&console->ptlock); + for(i = 0; i < cinput.count; i++) { + console->parse_sub(cinput.queue[i]); + } + cinput.count = 0; + LeaveSpinLock(&console->ptlock); + racond_signal(console->ptcond); + return 0; +} +void console_parse_final(void) { + if( console->ptstate ) { + InterlockedDecrement(&console->ptstate); + racond_signal(console->ptcond); + + /* wait for thread to close */ + rathread_wait(console->pthread, NULL); + + racond_destroy(console->ptcond); + ramutex_destroy(console->ptmutex); + } +} +void console_parse_init(void) { + cinput.count = 0; + + console->ptstate = 1; + + InitializeSpinLock(&console->ptlock); + + console->ptmutex = ramutex_create(); + console->ptcond = racond_create(); + + if( (console->pthread = rathread_create(console->pthread_main, NULL)) == NULL ){ + ShowFatalError("console_parse_init: failed to spawn console_parse thread.\n"); + exit(EXIT_FAILURE); + } + + add_timer_func_list(console->parse_timer, "console_parse_timer"); + add_timer_interval(gettick() + 1000, console->parse_timer, 0, 0, 500);/* start listening in 1s; re-try every 0.5s */ + +} +#endif /* CONSOLE_INPUT */ + +void console_init (void) { +#ifdef CONSOLE_INPUT + console->cmd_count = console->cmd_list_count = 0; + console->load_defaults(); + console->parse_init(); +#endif +} +void console_final(void) { +#ifdef CONSOLE_INPUT + unsigned int i; + console->parse_final(); + for( i = 0; i < console->cmd_count; i++ ) { + if( console->cmds[i]->next_count ) + aFree(console->cmds[i]->u.next); + aFree(console->cmds[i]); + } + aFree(console->cmds); + aFree(console->cmd_list); +#endif +} +void console_defaults(void) { + console = &console_s; + console->init = console_init; + console->final = console_final; + console->display_title = display_title; +#ifdef CONSOLE_INPUT + console->parse_init = console_parse_init; + console->parse_final = console_parse_final; + console->parse_timer = console_parse_timer; + console->pthread_main = cThread_main; + console->parse = console_parse; + console->parse_sub = console_parse_sub; + console->key_pressed = console_parse_key_pressed; + console->load_defaults = console_load_defaults; + console->parse_list_subs = console_parse_list_subs; + console->addCommand = console_parse_create; +#endif +} diff --git a/src/common/console.h b/src/common/console.h new file mode 100644 index 000000000..ebce013f7 --- /dev/null +++ b/src/common/console.h @@ -0,0 +1,71 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +#ifndef _CONSOLE_H_ +#define _CONSOLE_H_ + +#include "../common/thread.h" +#include "../common/mutex.h" +#include "../common/spinlock.h" +#include "../config/core.h" + +/** + * Queue Max + * why is there a limit, why not make it dynamic? - I'm playing it safe, I'd rather not play with memory management between threads + **/ +#define CONSOLE_PARSE_SIZE 10 + +typedef void (*CParseFunc)(char *line); +#define CPCMD(x) void console_parse_ ##x (char *line) +#define CPCMD_A(x) console_parse_ ##x + +#define CP_CMD_LENGTH 20 +struct CParseEntry { + char cmd[CP_CMD_LENGTH]; + union { + CParseFunc func; + struct CParseEntry **next; + } u; + unsigned short next_count; +}; + +struct { + char queue[CONSOLE_PARSE_SIZE][MAX_CONSOLE_INPUT]; + unsigned short count; +} cinput; + +struct console_interface { + void (*init) (void); + void (*final) (void); + void (*display_title) (void); +#ifdef CONSOLE_INPUT + /* vars */ + SPIN_LOCK ptlock;/* parse thread lock */ + rAthread pthread;/* parse thread */ + volatile int32 ptstate;/* parse thread state */ + ramutex ptmutex;/* parse thread mutex */ + racond ptcond;/* parse thread cond */ + /* */ + struct CParseEntry **cmd_list; + struct CParseEntry **cmds; + unsigned int cmd_count; + unsigned int cmd_list_count; + /* */ + void (*parse_init) (void); + void (*parse_final) (void); + int (*parse_timer) (int tid, unsigned int tick, int id, intptr_t data); + void *(*pthread_main) (void *x); + void (*parse) (char* line); + void (*parse_sub) (char* line); + int (*key_pressed) (void); + void (*load_defaults) (void); + void (*parse_list_subs) (struct CParseEntry *cmd, unsigned char depth); + void (*addCommand) (char *name, CParseFunc func); +#endif +}; + +struct console_interface *console; + +void console_defaults(void); + +#endif /* _CONSOLE_H_ */ diff --git a/src/common/core.c b/src/common/core.c index e1f99885b..0959e6fc9 100644 --- a/src/common/core.c +++ b/src/common/core.c @@ -1,16 +1,23 @@ -// 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 #include "../common/mmo.h" #include "../common/showmsg.h" #include "../common/malloc.h" +#include "../common/strlib.h" #include "core.h" +#include "../common/console.h" + #ifndef MINICORE -#include "../common/db.h" -#include "../common/socket.h" -#include "../common/timer.h" -#include "../common/thread.h" -#include "../common/mempool.h" + #include "../common/db.h" + #include "../common/socket.h" + #include "../common/timer.h" + #include "../common/thread.h" + #include "../common/mempool.h" + #include "../common/sql.h" + #include "../config/core.h" + #include "../common/HPM.h" #endif #include <stdio.h> @@ -23,20 +30,14 @@ #include "../common/winapi.h" // Console close event handling #endif - /// Called when a terminate signal is received. void (*shutdown_callback)(void) = NULL; -#if defined(BUILDBOT) - int buildbotflag = 0; -#endif - int runflag = CORE_ST_RUN; int arg_c = 0; char **arg_v = NULL; char *SERVER_NAME = NULL; -char SERVER_TYPE = ATHENA_SERVER_NONE; #ifndef MINICORE // minimalist Core // Added by Gabuzomeu @@ -52,8 +53,7 @@ char SERVER_TYPE = ATHENA_SERVER_NONE; #ifndef POSIX #define compat_signal(signo, func) signal(signo, func) #else -sigfunc *compat_signal(int signo, sigfunc *func) -{ +sigfunc *compat_signal(int signo, sigfunc *func) { struct sigaction sact, oact; sact.sa_handler = func; @@ -74,26 +74,23 @@ sigfunc *compat_signal(int signo, sigfunc *func) * CORE : Console events for Windows *--------------------------------------*/ #ifdef _WIN32 -static BOOL WINAPI console_handler(DWORD c_event) -{ - switch(c_event) - { - case CTRL_CLOSE_EVENT: - case CTRL_LOGOFF_EVENT: - case CTRL_SHUTDOWN_EVENT: - if( shutdown_callback != NULL ) - shutdown_callback(); - else - runflag = CORE_ST_STOP;// auto-shutdown - break; - default: - return FALSE; +static BOOL WINAPI console_handler(DWORD c_event) { + switch(c_event) { + case CTRL_CLOSE_EVENT: + case CTRL_LOGOFF_EVENT: + case CTRL_SHUTDOWN_EVENT: + if( shutdown_callback != NULL ) + shutdown_callback(); + else + runflag = CORE_ST_STOP;// auto-shutdown + break; + default: + return FALSE; } return TRUE; } -static void cevents_init() -{ +static void cevents_init() { if (SetConsoleCtrlHandler(console_handler,TRUE)==FALSE) ShowWarning ("Unable to install the console handler!\n"); } @@ -102,42 +99,40 @@ static void cevents_init() /*====================================== * CORE : Signal Sub Function *--------------------------------------*/ -static void sig_proc(int sn) -{ +static void sig_proc(int sn) { static int is_called = 0; switch (sn) { - case SIGINT: - case SIGTERM: - if (++is_called > 3) - exit(EXIT_SUCCESS); - if( shutdown_callback != NULL ) - shutdown_callback(); - else - runflag = CORE_ST_STOP;// auto-shutdown - break; - case SIGSEGV: - case SIGFPE: - do_abort(); - // Pass the signal to the system's default handler - compat_signal(sn, SIG_DFL); - raise(sn); - break; -#ifndef _WIN32 - case SIGXFSZ: - // ignore and allow it to set errno to EFBIG - ShowWarning ("Max file size reached!\n"); - //run_flag = 0; // should we quit? - break; - case SIGPIPE: - //ShowInfo ("Broken pipe found... closing socket\n"); // set to eof in socket.c - break; // does nothing here -#endif + case SIGINT: + case SIGTERM: + if (++is_called > 3) + exit(EXIT_SUCCESS); + if( shutdown_callback != NULL ) + shutdown_callback(); + else + runflag = CORE_ST_STOP;// auto-shutdown + break; + case SIGSEGV: + case SIGFPE: + do_abort(); + // Pass the signal to the system's default handler + compat_signal(sn, SIG_DFL); + raise(sn); + break; + #ifndef _WIN32 + case SIGXFSZ: + // ignore and allow it to set errno to EFBIG + ShowWarning ("Max file size reached!\n"); + //run_flag = 0; // should we quit? + break; + case SIGPIPE: + //ShowInfo ("Broken pipe found... closing socket\n"); // set to eof in socket.c + break; // does nothing here + #endif } } -void signals_init (void) -{ +void signals_init (void) { compat_signal(SIGTERM, sig_proc); compat_signal(SIGINT, sig_proc); #ifndef _DEBUG // need unhandled exceptions to debug on Windows @@ -155,13 +150,11 @@ void signals_init (void) #endif #ifdef SVNVERSION - const char *get_svn_revision(void) - { - return EXPAND_AND_QUOTE(SVNVERSION); - } +const char *get_svn_revision(void) { + return EXPAND_AND_QUOTE(SVNVERSION); +} #else// not SVNVERSION -const char* get_svn_revision(void) -{ +const char* get_svn_revision(void) { static char svn_version_buffer[16] = ""; FILE *fp; @@ -196,12 +189,10 @@ const char* get_svn_revision(void) fclose(fp); // parse buffer - for( i = prefix_len + 1; i + postfix_len <= len; ++i ) - { + for( i = prefix_len + 1; i + postfix_len <= len; ++i ) { if( buffer[i] != postfix[0] || memcmp(buffer + i, postfix, postfix_len) != 0 ) continue; // postfix missmatch - for( j = i; j > 0; --j ) - {// skip digits + for( j = i; j > 0; --j ) {// skip digits if( !ISDIGIT(buffer[j - 1]) ) break; } @@ -218,29 +209,23 @@ const char* get_svn_revision(void) } // subversion 1.6 and older? - if ((fp = fopen(".svn/entries", "r")) != NULL) - { + if ((fp = fopen(".svn/entries", "r")) != NULL) { char line[1024]; int rev; // Check the version - if (fgets(line, sizeof(line), fp)) - { - if(!ISDIGIT(line[0])) - { + if (fgets(line, sizeof(line), fp)) { + if(!ISDIGIT(line[0])) { // XML File format while (fgets(line,sizeof(line),fp)) if (strstr(line,"revision=")) break; if (sscanf(line," %*[^\"]\"%d%*[^\n]", &rev) == 1) { snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", rev); } - } - else - { + } else { // Bin File format if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get bin name\n"); } // Get the name if ( fgets(line, sizeof(line), fp) == NULL ) { printf("Can't get entries kind\n"); } // Get the entries kind - if(fgets(line, sizeof(line), fp)) // Get the rev numver - { + if(fgets(line, sizeof(line), fp)) { // Get the rev numver snprintf(svn_version_buffer, sizeof(svn_version_buffer), "%d", atoi(line)); } } @@ -252,86 +237,109 @@ const char* get_svn_revision(void) } // fallback - snprintf(svn_version_buffer, sizeof(svn_version_buffer), "Unknown"); + svn_version_buffer[0] = HERC_UNKNOWN_VER; return svn_version_buffer; } #endif - -/*====================================== - * CORE : Display title - * ASCII By CalciumKid 1/12/2011 - *--------------------------------------*/ -static void display_title(void) { - //ClearScreen(); // clear screen and go up/left (0, 0 position in text) - - ShowMessage("\n"); - ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BT_WHITE" rAthena Development Team presents "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BOLD" ___ __ __ "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BOLD" _____/ | / /_/ /_ ___ ____ ____ _ "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BOLD" / ___/ /| |/ __/ __ \\/ _ \\/ __ \\/ __ `/ "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BOLD" / / / ___ / /_/ / / / __/ / / / /_/ / "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BOLD" /_/ /_/ |_\\__/_/ /_/\\___/_/ /_/\\__,_/ "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_GREEN" http://rathena.org/board/ "CL_PASS""CL_CLL""CL_NORMAL"\n"); - ShowMessage(""CL_PASS" "CL_BOLD" "CL_PASS""CL_CLL""CL_NORMAL"\n"); - - ShowInfo("SVN Revision: '"CL_WHITE"%s"CL_RESET"'.\n", get_svn_revision()); +/* whats our origin */ +#define GIT_ORIGIN "refs/remotes/origin/master" +/* Grabs the hash from the last time the user updated his working copy (last pull) */ +const char *get_git_hash (void) { + static char HerculesGitHash[41] = "";//Sha(40) + 1 + FILE *fp; + + if( HerculesGitHash[0] != '\0' ) + return HerculesGitHash; + + if ( (fp = fopen (".git/"GIT_ORIGIN, "r")) != NULL) { + char line[64]; + char *rev = malloc (sizeof (char) * 50); + + if (fgets (line, sizeof (line), fp) && sscanf (line, "%50s", rev)) + snprintf (HerculesGitHash, sizeof (HerculesGitHash), "%s", rev); + + free (rev); + fclose (fp); + } else { + HerculesGitHash[0] = HERC_UNKNOWN_VER; + } + + if (! (*HerculesGitHash)) { + HerculesGitHash[0] = HERC_UNKNOWN_VER; + } + + return HerculesGitHash; } - // Warning if executed as superuser (root) -void usercheck(void) -{ +void usercheck(void) { #ifndef _WIN32 if (geteuid() == 0) { - ShowWarning ("You are running rAthena with root privileges, it is not necessary.\n"); + ShowWarning ("You are running Hercules with root privileges, it is not necessary.\n"); } #endif } - +void core_defaults(void) { +#ifndef MINICORE + hpm_defaults(); +#endif + console_defaults(); + strlib_defaults(); + malloc_defaults(); +#ifndef MINICORE + sql_defaults(); + timer_defaults(); + db_defaults(); +#endif +} /*====================================== * CORE : MAINROUTINE *--------------------------------------*/ -int main (int argc, char **argv) -{ +int main (int argc, char **argv) { {// initialize program arguments char *p1 = SERVER_NAME = argv[0]; char *p2 = p1; - while ((p1 = strchr(p2, '/')) != NULL || (p1 = strchr(p2, '\\')) != NULL) - { + while ((p1 = strchr(p2, '/')) != NULL || (p1 = strchr(p2, '\\')) != NULL) { SERVER_NAME = ++p1; p2 = p1; } arg_c = argc; arg_v = argv; } - - malloc_init();// needed for Show* in display_title() [FlavioJS] - + core_defaults(); + + malloclib->init();// needed for Show* in display_title() [FlavioJS] + + console->display_title(); + #ifdef MINICORE // minimalist Core - display_title(); usercheck(); do_init(argc,argv); do_final(); #else// not MINICORE set_server_type(); - display_title(); usercheck(); + Sql_Init(); rathread_init(); mempool_init(); - db_init(); + DB->init(); signals_init(); - + #ifdef _WIN32 cevents_init(); #endif timer_init(); + + console->init(); + +#ifndef MINICORE + HPM->init(); +#endif + socket_init(); do_init(argc,argv); - {// Main runtime cycle int next; while (runflag != CORE_ST_STOP) { @@ -340,16 +348,20 @@ int main (int argc, char **argv) } } + console->final(); + do_final(); - +#ifndef MINICORE + HPM->final(); +#endif timer_final(); socket_final(); - db_final(); + DB->final(); mempool_final(); rathread_final(); #endif - malloc_final(); + malloclib->final(); return 0; } diff --git a/src/common/core.h b/src/common/core.h index d48962c94..8fdcdcfc3 100644 --- a/src/common/core.h +++ b/src/common/core.h @@ -1,40 +1,46 @@ -// 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 _CORE_H_ #define _CORE_H_ +#include "../common/db.h" +#include "../common/mmo.h" +#include "../config/core.h" + +/* so that developers with --enable-debug can raise signals from any section of the code they'd like */ +#ifdef DEBUG + #include <signal.h> +#endif + extern int arg_c; extern char **arg_v; -#if defined(BUILDBOT) - extern int buildbotflag; -#endif +#define HERC_UNKNOWN_VER '\x02' /// @see E_CORE_ST extern int runflag; extern char *SERVER_NAME; -enum { - ATHENA_SERVER_NONE = 0, // not defined - ATHENA_SERVER_LOGIN = 1, // login server - ATHENA_SERVER_CHAR = 2, // char server - ATHENA_SERVER_INTER = 4, // inter server - ATHENA_SERVER_MAP = 8, // map server +enum server_types { + SERVER_TYPE_UNKNOWN = 0x0, + SERVER_TYPE_LOGIN = 0x1, + SERVER_TYPE_CHAR = 0x2, + SERVER_TYPE_MAP = 0x4, }; -extern char SERVER_TYPE; +enum server_types SERVER_TYPE; -extern int parse_console(const char* buf); -extern const char *get_svn_revision(void); +const char *get_svn_revision(void); +const char *get_git_hash (void); extern int do_init(int,char**); extern void set_server_type(void); extern void do_abort(void); extern void do_final(void); /// The main loop continues until runflag is CORE_ST_STOP -enum E_CORE_ST -{ +enum E_CORE_ST { CORE_ST_STOP = 0, CORE_ST_RUN, CORE_ST_LAST diff --git a/src/common/db.c b/src/common/db.c index 204c6d2ea..579697a99 100644 --- a/src/common/db.c +++ b/src/common/db.c @@ -1,69 +1,70 @@ /*****************************************************************************\ - * Copyright (c) Athena Dev Teams - Licensed under GNU GPL - * For more information, see LICENCE in the main folder - * - * This file is separated in five sections: - * (1) Private typedefs, enums, structures, defines and gblobal variables - * (2) Private functions - * (3) Protected functions used internally - * (4) Protected functions used in the interface of the database - * (5) Public functions - * - * The databases are structured as a hashtable of RED-BLACK trees. - * - * <B>Properties of the RED-BLACK trees being used:</B> - * 1. The value of any node is greater than the value of its left child and - * less than the value of its right child. - * 2. Every node is colored either RED or BLACK. - * 3. Every red node that is not a leaf has only black children. - * 4. Every path from the root to a leaf contains the same number of black - * nodes. - * 5. The root node is black. - * An <code>n</code> node in a RED-BLACK tree has the property that its - * height is <code>O(lg(n))</code>. - * Another important property is that after adding a node to a RED-BLACK - * tree, the tree can be readjusted in <code>O(lg(n))</code> time. - * Similarly, after deleting a node from a RED-BLACK tree, the tree can be - * readjusted in <code>O(lg(n))</code> time. - * {@link http://www.cs.mcgill.ca/~cs251/OldCourses/1997/topic18/} - * - * <B>How to add new database types:</B> - * 1. Add the identifier of the new database type to the enum DBType - * 2. If not already there, add the data type of the key to the union DBKey - * 3. If the key can be considered NULL, update the function db_is_key_null - * 4. If the key can be duplicated, update the functions db_dup_key and - * db_dup_key_free - * 5. Create a comparator and update the function db_default_cmp - * 6. Create a hasher and update the function db_default_hash - * 7. If the new database type requires or does not support some options, - * update the function db_fix_options - * - * TODO: - * - create test cases to test the database system thoroughly - * - finish this header describing the database system - * - create custom database allocator - * - make the system thread friendly - * - change the structure of the database to T-Trees - * - create a db that organizes itself by splaying - * - * HISTORY: - * 2012/03/09 - Added enum for data types (int, uint, void*) - * 2008/02/19 - Fixed db_obj_get not handling deleted entries correctly. - * 2007/11/09 - Added an iterator to the database. - * 2006/12/21 - Added 1-node cache to the database. - * 2.1 (Athena build #???#) - Portability fix - * - Fixed the portability of casting to union and added the functions - * ensure and clear to the database. - * 2.0 (Athena build 4859) - Transition version - * - Almost everything recoded with a strategy similar to objects, - * database structure is maintained. - * 1.0 (up to Athena build 4706) - * - Previous database system. - * - * @version 2006/12/21 - * @author Athena Dev team - * @encoding US-ASCII - * @see #db.h +* Copyright (c) Athena Dev Teams - Licensed under GNU GPL +* For more information, see LICENCE in the main folder +* +* This file is separated in five sections: +* (1) Private typedefs, enums, structures, defines and gblobal variables +* (2) Private functions +* (3) Protected functions used internally +* (4) Protected functions used in the interface of the database +* (5) Public functions +* +* The databases are structured as a hashtable of RED-BLACK trees. +* +* <B>Properties of the RED-BLACK trees being used:</B> +* 1. The value of any node is greater than the value of its left child and +* less than the value of its right child. +* 2. Every node is colored either RED or BLACK. +* 3. Every red node that is not a leaf has only black children. +* 4. Every path from the root to a leaf contains the same number of black +* nodes. +* 5. The root node is black. +* An <code>n</code> node in a RED-BLACK tree has the property that its +* height is <code>O(lg(n))</code>. +* Another important property is that after adding a node to a RED-BLACK +* tree, the tree can be readjusted in <code>O(lg(n))</code> time. +* Similarly, after deleting a node from a RED-BLACK tree, the tree can be +* readjusted in <code>O(lg(n))</code> time. +* {@link http://www.cs.mcgill.ca/~cs251/OldCourses/1997/topic18/} +* +* <B>How to add new database types:</B> +* 1. Add the identifier of the new database type to the enum DBType +* 2. If not already there, add the data type of the key to the union DBKey +* 3. If the key can be considered NULL, update the function db_is_key_null +* 4. If the key can be duplicated, update the functions db_dup_key and +* db_dup_key_free +* 5. Create a comparator and update the function db_default_cmp +* 6. Create a hasher and update the function db_default_hash +* 7. If the new database type requires or does not support some options, +* update the function db_fix_options +* +* TODO: +* - create test cases to test the database system thoroughly +* - finish this header describing the database system +* - create custom database allocator +* - make the system thread friendly +* - change the structure of the database to T-Trees +* - create a db that organizes itself by splaying +* +* HISTORY: +* 2013/04/27 - Added ERS to speed up iterator memory allocation [Ind/Hercules] +* 2012/03/09 - Added enum for data types (int, uint, void*) +* 2008/02/19 - Fixed db_obj_get not handling deleted entries correctly. +* 2007/11/09 - Added an iterator to the database. +* 2006/12/21 - Added 1-node cache to the database. +* 2.1 (Athena build #???#) - Portability fix +* - Fixed the portability of casting to union and added the functions +* ensure and clear to the database. +* 2.0 (Athena build 4859) - Transition version +* - Almost everything recoded with a strategy similar to objects, +* database structure is maintained. +* 1.0 (up to Athena build 4706) +* - Previous database system. +* +* @version 2006/12/21 +* @author Athena Dev team +* @encoding US-ASCII +* @see #db.h \*****************************************************************************/ #include <stdio.h> #include <stdlib.h> @@ -76,58 +77,58 @@ #include "../common/strlib.h" /*****************************************************************************\ - * (1) Private typedefs, enums, structures, defines and global variables of * - * the database system. * - * DB_ENABLE_STATS - Define to enable database statistics. * - * HASH_SIZE - Define with the size of the hashtable. * - * DBNColor - Enumeration of colors of the nodes. * - * DBNode - Structure of a node in RED-BLACK trees. * - * struct db_free - Structure that holds a deleted node to be freed. * - * DBMap_impl - Struture of the database. * - * stats - Statistics about the database system. * +* (1) Private typedefs, enums, structures, defines and global variables of * +* the database system. * +* DB_ENABLE_STATS - Define to enable database statistics. * +* HASH_SIZE - Define with the size of the hashtable. * +* DBNColor - Enumeration of colors of the nodes. * +* DBNode - Structure of a node in RED-BLACK trees. * +* struct db_free - Structure that holds a deleted node to be freed. * +* DBMap_impl - Struture of the database. * +* stats - Statistics about the database system. * \*****************************************************************************/ /** - * If defined statistics about database nodes, database creating/destruction - * and function usage are keept and displayed when finalizing the database - * system. - * WARNING: This adds overhead to every database operation (not shure how much). - * @private - * @see #DBStats - * @see #stats - * @see #db_final(void) - */ +* If defined statistics about database nodes, database creating/destruction +* and function usage are keept and displayed when finalizing the database +* system. +* WARNING: This adds overhead to every database operation (not shure how much). +* @private +* @see #DBStats +* @see #stats +* @see #db_final(void) +*/ //#define DB_ENABLE_STATS /** - * Size of the hashtable in the database. - * @private - * @see DBMap_impl#ht - */ +* Size of the hashtable in the database. +* @private +* @see DBMap_impl#ht +*/ #define HASH_SIZE (256+27) /** - * The color of individual nodes. - * @private - * @see struct dbn - */ +* The color of individual nodes. +* @private +* @see struct dbn +*/ typedef enum node_color { RED, BLACK } node_color; /** - * A node in a RED-BLACK tree of the database. - * @param parent Parent node - * @param left Left child node - * @param right Right child node - * @param key Key of this database entry - * @param data Data of this database entry - * @param deleted If the node is deleted - * @param color Color of the node - * @private - * @see DBMap_impl#ht - */ +* A node in a RED-BLACK tree of the database. +* @param parent Parent node +* @param left Left child node +* @param right Right child node +* @param key Key of this database entry +* @param data Data of this database entry +* @param deleted If the node is deleted +* @param color Color of the node +* @private +* @see DBMap_impl#ht +*/ typedef struct dbn { // Tree structure struct dbn *parent; @@ -142,39 +143,39 @@ typedef struct dbn { } *DBNode; /** - * Structure that holds a deleted node. - * @param node Deleted node - * @param root Address to the root of the tree - * @private - * @see DBMap_impl#free_list - */ +* Structure that holds a deleted node. +* @param node Deleted node +* @param root Address to the root of the tree +* @private +* @see DBMap_impl#free_list +*/ struct db_free { DBNode node; DBNode *root; }; /** - * Complete database structure. - * @param vtable Interface of the database - * @param alloc_file File where the database was allocated - * @param alloc_line Line in the file where the database was allocated - * @param free_list Array of deleted nodes to be freed - * @param free_count Number of deleted nodes in free_list - * @param free_max Current maximum capacity of free_list - * @param free_lock Lock for freeing the nodes - * @param nodes Manager of reusable tree nodes - * @param cmp Comparator of the database - * @param hash Hasher of the database - * @param release Releaser of the database - * @param ht Hashtable of RED-BLACK trees - * @param type Type of the database - * @param options Options of the database - * @param item_count Number of items in the database - * @param maxlen Maximum length of strings in DB_STRING and DB_ISTRING databases - * @param global_lock Global lock of the database - * @private - * @see #db_alloc(const char*,int,DBType,DBOptions,unsigned short) - */ +* Complete database structure. +* @param vtable Interface of the database +* @param alloc_file File where the database was allocated +* @param alloc_line Line in the file where the database was allocated +* @param free_list Array of deleted nodes to be freed +* @param free_count Number of deleted nodes in free_list +* @param free_max Current maximum capacity of free_list +* @param free_lock Lock for freeing the nodes +* @param nodes Manager of reusable tree nodes +* @param cmp Comparator of the database +* @param hash Hasher of the database +* @param release Releaser of the database +* @param ht Hashtable of RED-BLACK trees +* @param type Type of the database +* @param options Options of the database +* @param item_count Number of items in the database +* @param maxlen Maximum length of strings in DB_STRING and DB_ISTRING databases +* @param global_lock Global lock of the database +* @private +* @see #db_alloc(const char*,int,DBType,DBOptions,unsigned short) +*/ typedef struct DBMap_impl { // Database interface struct DBMap vtable; @@ -201,16 +202,16 @@ typedef struct DBMap_impl { } DBMap_impl; /** - * Complete iterator structure. - * @param vtable Interface of the iterator - * @param db Parent database - * @param ht_index Current index of the hashtable - * @param node Current node - * @private - * @see #DBIterator - * @see #DBMap_impl - * @see #DBNode - */ +* Complete iterator structure. +* @param vtable Interface of the iterator +* @param db Parent database +* @param ht_index Current index of the hashtable +* @param node Current node +* @private +* @see #DBIterator +* @see #DBMap_impl +* @see #DBNode +*/ typedef struct DBIterator_impl { // Iterator interface struct DBIterator vtable; @@ -221,11 +222,11 @@ typedef struct DBIterator_impl { #if defined(DB_ENABLE_STATS) /** - * Structure with what is counted when the database statistics are enabled. - * @private - * @see #DB_ENABLE_STATS - * @see #stats - */ +* Structure with what is counted when the database statistics are enabled. +* @private +* @see #DB_ENABLE_STATS +* @see #stats +*/ static struct db_stats { // Node alloc/free uint32 db_node_alloc; @@ -319,31 +320,35 @@ static struct db_stats { #define DB_COUNTSTAT(token) #endif /* !defined(DB_ENABLE_STATS) */ +/* [Ind/Hercules] */ +struct eri *db_iterator_ers; +struct eri *db_alloc_ers; + /*****************************************************************************\ - * (2) Section of private functions used by the database system. * - * db_rotate_left - Rotate a tree node to the left. * - * db_rotate_right - Rotate a tree node to the right. * - * db_rebalance - Rebalance the tree. * - * db_rebalance_erase - Rebalance the tree after a BLACK node was erased. * - * db_is_key_null - Returns not 0 if the key is considered NULL. * - * db_dup_key - Duplicate a key for internal use. * - * db_dup_key_free - Free the duplicated key. * - * db_free_add - Add a node to the free_list of a database. * - * db_free_remove - Remove a node from the free_list of a database. * - * db_free_lock - Increment the free_lock of a database. * - * db_free_unlock - Decrement the free_lock of a database. * - * If it was the last lock, frees the nodes in free_list. * - * NOTE: Keeps the database trees balanced. * +* (2) Section of private functions used by the database system. * +* db_rotate_left - Rotate a tree node to the left. * +* db_rotate_right - Rotate a tree node to the right. * +* db_rebalance - Rebalance the tree. * +* db_rebalance_erase - Rebalance the tree after a BLACK node was erased. * +* db_is_key_null - Returns not 0 if the key is considered NULL. * +* db_dup_key - Duplicate a key for internal use. * +* db_dup_key_free - Free the duplicated key. * +* db_free_add - Add a node to the free_list of a database. * +* db_free_remove - Remove a node from the free_list of a database. * +* db_free_lock - Increment the free_lock of a database. * +* db_free_unlock - Decrement the free_lock of a database. * +* If it was the last lock, frees the nodes in free_list. * +* NOTE: Keeps the database trees balanced. * \*****************************************************************************/ /** - * Rotate a node to the left. - * @param node Node to be rotated - * @param root Pointer to the root of the tree - * @private - * @see #db_rebalance(DBNode,DBNode *) - * @see #db_rebalance_erase(DBNode,DBNode *) - */ +* Rotate a node to the left. +* @param node Node to be rotated +* @param root Pointer to the root of the tree +* @private +* @see #db_rebalance(DBNode,DBNode *) +* @see #db_rebalance_erase(DBNode,DBNode *) +*/ static void db_rotate_left(DBNode node, DBNode *root) { DBNode y = node->right; @@ -368,13 +373,13 @@ static void db_rotate_left(DBNode node, DBNode *root) } /** - * Rotate a node to the right - * @param node Node to be rotated - * @param root Pointer to the root of the tree - * @private - * @see #db_rebalance(DBNode,DBNode *) - * @see #db_rebalance_erase(DBNode,DBNode *) - */ +* Rotate a node to the right +* @param node Node to be rotated +* @param root Pointer to the root of the tree +* @private +* @see #db_rebalance(DBNode,DBNode *) +* @see #db_rebalance_erase(DBNode,DBNode *) +*/ static void db_rotate_right(DBNode node, DBNode *root) { DBNode y = node->left; @@ -399,15 +404,15 @@ static void db_rotate_right(DBNode node, DBNode *root) } /** - * Rebalance the RED-BLACK tree. - * Called when the node and it's parent are both RED. - * @param node Node to be rebalanced - * @param root Pointer to the root of the tree - * @private - * @see #db_rotate_left(DBNode,DBNode *) - * @see #db_rotate_right(DBNode,DBNode *) - * @see #db_obj_put(DBMap*,DBKey,DBData) - */ +* Rebalance the RED-BLACK tree. +* Called when the node and it's parent are both RED. +* @param node Node to be rebalanced +* @param root Pointer to the root of the tree +* @private +* @see #db_rotate_left(DBNode,DBNode *) +* @see #db_rotate_right(DBNode,DBNode *) +* @see #db_obj_put(DBMap*,DBKey,DBData) +*/ static void db_rebalance(DBNode node, DBNode *root) { DBNode y; @@ -462,14 +467,14 @@ static void db_rebalance(DBNode node, DBNode *root) } /** - * Erase a node from the RED-BLACK tree, keeping the tree balanced. - * @param node Node to be erased from the tree - * @param root Root of the tree - * @private - * @see #db_rotate_left(DBNode,DBNode *) - * @see #db_rotate_right(DBNode,DBNode *) - * @see #db_free_unlock(DBMap_impl*) - */ +* Erase a node from the RED-BLACK tree, keeping the tree balanced. +* @param node Node to be erased from the tree +* @param root Root of the tree +* @private +* @see #db_rotate_left(DBNode,DBNode *) +* @see #db_rotate_right(DBNode,DBNode *) +* @see #db_free_unlock(DBMap_impl*) +*/ static void db_rebalance_erase(DBNode node, DBNode *root) { DBNode y = node; @@ -505,7 +510,7 @@ static void db_rebalance_erase(DBNode node, DBNode *root) // put the right of 'node' in 'y' y->right = node->right; node->right->parent = y; - // 'y' is a direct child of 'node' + // 'y' is a direct child of 'node' } else { x_parent = y; } @@ -553,9 +558,9 @@ static void db_rebalance_erase(DBNode node, DBNode *root) } if ((w->left == NULL || w->left->color == BLACK) && (w->right == NULL || w->right->color == BLACK)) { - w->color = RED; - x = x_parent; - x_parent = x_parent->parent; + w->color = RED; + x = x_parent; + x_parent = x_parent->parent; } else { if (w->right == NULL || w->right->color == BLACK) { if (w->left) w->left->color = BLACK; @@ -579,9 +584,9 @@ static void db_rebalance_erase(DBNode node, DBNode *root) } if ((w->right == NULL || w->right->color == BLACK) && (w->left == NULL || w->left->color == BLACK)) { - w->color = RED; - x = x_parent; - x_parent = x_parent->parent; + w->color = RED; + x = x_parent; + x_parent = x_parent->parent; } else { if (w->left == NULL || w->left->color == BLACK) { if (w->right) w->right->color = BLACK; @@ -602,39 +607,39 @@ static void db_rebalance_erase(DBNode node, DBNode *root) } /** - * Returns not 0 if the key is considered to be NULL. - * @param type Type of database - * @param key Key being tested - * @return not 0 if considered NULL, 0 otherwise - * @private - * @see #db_obj_get(DBMap*,DBKey) - * @see #db_obj_put(DBMap*,DBKey,DBData) - * @see #db_obj_remove(DBMap*,DBKey) - */ +* Returns not 0 if the key is considered to be NULL. +* @param type Type of database +* @param key Key being tested +* @return not 0 if considered NULL, 0 otherwise +* @private +* @see #db_obj_get(DBMap*,DBKey) +* @see #db_obj_put(DBMap*,DBKey,DBData) +* @see #db_obj_remove(DBMap*,DBKey) +*/ static int db_is_key_null(DBType type, DBKey key) { DB_COUNTSTAT(db_is_key_null); switch (type) { - case DB_STRING: - case DB_ISTRING: - return (key.str == NULL); + case DB_STRING: + case DB_ISTRING: + return (key.str == NULL); - default: // Not a pointer - return 0; + default: // Not a pointer + return 0; } } /** - * Duplicate the key used in the database. - * @param db Database the key is being used in - * @param key Key to be duplicated - * @param Duplicated key - * @private - * @see #db_free_add(DBMap_impl*,DBNode,DBNode *) - * @see #db_free_remove(DBMap_impl*,DBNode) - * @see #db_obj_put(DBMap*,DBKey,void *) - * @see #db_dup_key_free(DBMap_impl*,DBKey) - */ +* Duplicate the key used in the database. +* @param db Database the key is being used in +* @param key Key to be duplicated +* @param Duplicated key +* @private +* @see #db_free_add(DBMap_impl*,DBNode,DBNode *) +* @see #db_free_remove(DBMap_impl*,DBNode) +* @see #db_obj_put(DBMap*,DBKey,void *) +* @see #db_dup_key_free(DBMap_impl*,DBKey) +*/ static DBKey db_dup_key(DBMap_impl* db, DBKey key) { char *str; @@ -642,56 +647,56 @@ static DBKey db_dup_key(DBMap_impl* db, DBKey key) DB_COUNTSTAT(db_dup_key); switch (db->type) { - case DB_STRING: - case DB_ISTRING: - len = strnlen(key.str, db->maxlen); - str = (char*)aMalloc(len + 1); - memcpy(str, key.str, len); - str[len] = '\0'; - key.str = str; - return key; - - default: - return key; + case DB_STRING: + case DB_ISTRING: + len = strnlen(key.str, db->maxlen); + str = (char*)aMalloc(len + 1); + memcpy(str, key.str, len); + str[len] = '\0'; + key.str = str; + return key; + + default: + return key; } } /** - * Free a key duplicated by db_dup_key. - * @param db Database the key is being used in - * @param key Key to be freed - * @private - * @see #db_dup_key(DBMap_impl*,DBKey) - */ +* Free a key duplicated by db_dup_key. +* @param db Database the key is being used in +* @param key Key to be freed +* @private +* @see #db_dup_key(DBMap_impl*,DBKey) +*/ static void db_dup_key_free(DBMap_impl* db, DBKey key) { DB_COUNTSTAT(db_dup_key_free); switch (db->type) { - case DB_STRING: - case DB_ISTRING: - aFree((char*)key.str); - return; + case DB_STRING: + case DB_ISTRING: + aFree((char*)key.str); + return; - default: - return; + default: + return; } } /** - * Add a node to the free_list of the database. - * Marks the node as deleted. - * If the key isn't duplicated, the key is duplicated and released. - * @param db Target database - * @param root Root of the tree from the node - * @param node Target node - * @private - * @see #struct db_free - * @see DBMap_impl#free_list - * @see DBMap_impl#free_count - * @see DBMap_impl#free_max - * @see #db_obj_remove(DBMap*,DBKey) - * @see #db_free_remove(DBMap_impl*,DBNode) - */ +* Add a node to the free_list of the database. +* Marks the node as deleted. +* If the key isn't duplicated, the key is duplicated and released. +* @param db Target database +* @param root Root of the tree from the node +* @param node Target node +* @private +* @see #struct db_free +* @see DBMap_impl#free_list +* @see DBMap_impl#free_count +* @see DBMap_impl#free_max +* @see #db_obj_remove(DBMap*,DBKey) +* @see #db_free_remove(DBMap_impl*,DBNode) +*/ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) { DBKey old_key; @@ -699,8 +704,8 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) DB_COUNTSTAT(db_free_add); if (db->free_lock == (unsigned int)~0) { ShowFatalError("db_free_add: free_lock overflow\n" - "Database allocated at %s:%d\n", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->alloc_file, db->alloc_line); exit(EXIT_FAILURE); } if (!(db->options&DB_OPT_DUP_KEY)) { // Make sure we have a key until the node is freed @@ -713,8 +718,8 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) if (db->free_max <= db->free_count) { if (db->free_count == (unsigned int)~0) { ShowFatalError("db_free_add: free_count overflow\n" - "Database allocated at %s:%d\n", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->alloc_file, db->alloc_line); exit(EXIT_FAILURE); } db->free_max = (unsigned int)~0; @@ -729,18 +734,18 @@ static void db_free_add(DBMap_impl* db, DBNode node, DBNode *root) } /** - * Remove a node from the free_list of the database. - * Marks the node as not deleted. - * NOTE: Frees the duplicated key of the node. - * @param db Target database - * @param node Node being removed from free_list - * @private - * @see #struct db_free - * @see DBMap_impl#free_list - * @see DBMap_impl#free_count - * @see #db_obj_put(DBMap*,DBKey,DBData) - * @see #db_free_add(DBMap_impl*,DBNode*,DBNode) - */ +* Remove a node from the free_list of the database. +* Marks the node as not deleted. +* NOTE: Frees the duplicated key of the node. +* @param db Target database +* @param node Node being removed from free_list +* @private +* @see #struct db_free +* @see DBMap_impl#free_list +* @see DBMap_impl#free_count +* @see #db_obj_put(DBMap*,DBKey,DBData) +* @see #db_free_add(DBMap_impl*,DBNode*,DBNode) +*/ static void db_free_remove(DBMap_impl* db, DBNode node) { unsigned int i; @@ -764,35 +769,35 @@ static void db_free_remove(DBMap_impl* db, DBNode node) } /** - * Increment the free_lock of the database. - * @param db Target database - * @private - * @see DBMap_impl#free_lock - * @see #db_unlock(DBMap_impl*) - */ +* Increment the free_lock of the database. +* @param db Target database +* @private +* @see DBMap_impl#free_lock +* @see #db_unlock(DBMap_impl*) +*/ static void db_free_lock(DBMap_impl* db) { DB_COUNTSTAT(db_free_lock); if (db->free_lock == (unsigned int)~0) { ShowFatalError("db_free_lock: free_lock overflow\n" - "Database allocated at %s:%d\n", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->alloc_file, db->alloc_line); exit(EXIT_FAILURE); } db->free_lock++; } /** - * Decrement the free_lock of the database. - * If it was the last lock, frees the nodes of the database. - * Keeps the tree balanced. - * NOTE: Frees the duplicated keys of the nodes - * @param db Target database - * @private - * @see DBMap_impl#free_lock - * @see #db_free_dbn(DBNode) - * @see #db_lock(DBMap_impl*) - */ +* Decrement the free_lock of the database. +* If it was the last lock, frees the nodes of the database. +* Keeps the tree balanced. +* NOTE: Frees the duplicated keys of the nodes +* @param db Target database +* @private +* @see DBMap_impl#free_lock +* @see #db_free_dbn(DBNode) +* @see #db_lock(DBMap_impl*) +*/ static void db_free_unlock(DBMap_impl* db) { unsigned int i; @@ -800,8 +805,8 @@ static void db_free_unlock(DBMap_impl* db) DB_COUNTSTAT(db_free_unlock); if (db->free_lock == 0) { ShowWarning("db_free_unlock: free_lock was already 0\n" - "Database allocated at %s:%d\n", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->alloc_file, db->alloc_line); } else { db->free_lock--; } @@ -818,36 +823,36 @@ static void db_free_unlock(DBMap_impl* db) } /*****************************************************************************\ - * (3) Section of protected functions used internally. * - * NOTE: the protected functions used in the database interface are in the * - * next section. * - * db_int_cmp - Default comparator for DB_INT databases. * - * db_uint_cmp - Default comparator for DB_UINT databases. * - * db_string_cmp - Default comparator for DB_STRING databases. * - * db_istring_cmp - Default comparator for DB_ISTRING databases. * - * db_int_hash - Default hasher for DB_INT databases. * - * db_uint_hash - Default hasher for DB_UINT databases. * - * db_string_hash - Default hasher for DB_STRING databases. * - * db_istring_hash - Default hasher for DB_ISTRING databases. * - * db_release_nothing - Releaser that releases nothing. * - * db_release_key - Releaser that only releases the key. * - * db_release_data - Releaser that only releases the data. * - * db_release_both - Releaser that releases key and data. * +* (3) Section of protected functions used internally. * +* NOTE: the protected functions used in the database interface are in the * +* next section. * +* db_int_cmp - Default comparator for DB_INT databases. * +* db_uint_cmp - Default comparator for DB_UINT databases. * +* db_string_cmp - Default comparator for DB_STRING databases. * +* db_istring_cmp - Default comparator for DB_ISTRING databases. * +* db_int_hash - Default hasher for DB_INT databases. * +* db_uint_hash - Default hasher for DB_UINT databases. * +* db_string_hash - Default hasher for DB_STRING databases. * +* db_istring_hash - Default hasher for DB_ISTRING databases. * +* db_release_nothing - Releaser that releases nothing. * +* db_release_key - Releaser that only releases the key. * +* db_release_data - Releaser that only releases the data. * +* db_release_both - Releaser that releases key and data. * \*****************************************************************************/ /** - * Default comparator for DB_INT databases. - * Compares key1 to key2. - * Return 0 if equal, negative if lower and positive if higher. - * <code>maxlen</code> is ignored. - * @param key1 Key to be compared - * @param key2 Key being compared to - * @param maxlen Maximum length of the key to hash - * @return 0 if equal, negative if lower and positive if higher - * @see DBType#DB_INT - * @see #DBComparator - * @see #db_default_cmp(DBType) - */ +* Default comparator for DB_INT databases. +* Compares key1 to key2. +* Return 0 if equal, negative if lower and positive if higher. +* <code>maxlen</code> is ignored. +* @param key1 Key to be compared +* @param key2 Key being compared to +* @param maxlen Maximum length of the key to hash +* @return 0 if equal, negative if lower and positive if higher +* @see DBType#DB_INT +* @see #DBComparator +* @see #db_default_cmp(DBType) +*/ static int db_int_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { (void)maxlen;//not used @@ -858,18 +863,18 @@ static int db_int_cmp(DBKey key1, DBKey key2, unsigned short maxlen) } /** - * Default comparator for DB_UINT databases. - * Compares key1 to key2. - * Return 0 if equal, negative if lower and positive if higher. - * <code>maxlen</code> is ignored. - * @param key1 Key to be compared - * @param key2 Key being compared to - * @param maxlen Maximum length of the key to hash - * @return 0 if equal, negative if lower and positive if higher - * @see DBType#DB_UINT - * @see #DBComparator - * @see #db_default_cmp(DBType) - */ +* Default comparator for DB_UINT databases. +* Compares key1 to key2. +* Return 0 if equal, negative if lower and positive if higher. +* <code>maxlen</code> is ignored. +* @param key1 Key to be compared +* @param key2 Key being compared to +* @param maxlen Maximum length of the key to hash +* @return 0 if equal, negative if lower and positive if higher +* @see DBType#DB_UINT +* @see #DBComparator +* @see #db_default_cmp(DBType) +*/ static int db_uint_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { (void)maxlen;//not used @@ -880,17 +885,17 @@ static int db_uint_cmp(DBKey key1, DBKey key2, unsigned short maxlen) } /** - * Default comparator for DB_STRING databases. - * Compares key1 to key2. - * Return 0 if equal, negative if lower and positive if higher. - * @param key1 Key to be compared - * @param key2 Key being compared to - * @param maxlen Maximum length of the key to hash - * @return 0 if equal, negative if lower and positive if higher - * @see DBType#DB_STRING - * @see #DBComparator - * @see #db_default_cmp(DBType) - */ +* Default comparator for DB_STRING databases. +* Compares key1 to key2. +* Return 0 if equal, negative if lower and positive if higher. +* @param key1 Key to be compared +* @param key2 Key being compared to +* @param maxlen Maximum length of the key to hash +* @return 0 if equal, negative if lower and positive if higher +* @see DBType#DB_STRING +* @see #DBComparator +* @see #db_default_cmp(DBType) +*/ static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { DB_COUNTSTAT(db_string_cmp); @@ -898,17 +903,17 @@ static int db_string_cmp(DBKey key1, DBKey key2, unsigned short maxlen) } /** - * Default comparator for DB_ISTRING databases. - * Compares key1 to key2 case insensitively. - * Return 0 if equal, negative if lower and positive if higher. - * @param key1 Key to be compared - * @param key2 Key being compared to - * @param maxlen Maximum length of the key to hash - * @return 0 if equal, negative if lower and positive if higher - * @see DBType#DB_ISTRING - * @see #DBComparator - * @see #db_default_cmp(DBType) - */ +* Default comparator for DB_ISTRING databases. +* Compares key1 to key2 case insensitively. +* Return 0 if equal, negative if lower and positive if higher. +* @param key1 Key to be compared +* @param key2 Key being compared to +* @param maxlen Maximum length of the key to hash +* @return 0 if equal, negative if lower and positive if higher +* @see DBType#DB_ISTRING +* @see #DBComparator +* @see #db_default_cmp(DBType) +*/ static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen) { DB_COUNTSTAT(db_istring_cmp); @@ -916,16 +921,16 @@ static int db_istring_cmp(DBKey key1, DBKey key2, unsigned short maxlen) } /** - * Default hasher for DB_INT databases. - * Returns the value of the key as an unsigned int. - * <code>maxlen</code> is ignored. - * @param key Key to be hashed - * @param maxlen Maximum length of the key to hash - * @return hash of the key - * @see DBType#DB_INT - * @see #DBHasher - * @see #db_default_hash(DBType) - */ +* Default hasher for DB_INT databases. +* Returns the value of the key as an unsigned int. +* <code>maxlen</code> is ignored. +* @param key Key to be hashed +* @param maxlen Maximum length of the key to hash +* @return hash of the key +* @see DBType#DB_INT +* @see #DBHasher +* @see #db_default_hash(DBType) +*/ static unsigned int db_int_hash(DBKey key, unsigned short maxlen) { (void)maxlen;//not used @@ -934,16 +939,16 @@ static unsigned int db_int_hash(DBKey key, unsigned short maxlen) } /** - * Default hasher for DB_UINT databases. - * Just returns the value of the key. - * <code>maxlen</code> is ignored. - * @param key Key to be hashed - * @param maxlen Maximum length of the key to hash - * @return hash of the key - * @see DBType#DB_UINT - * @see #DBHasher - * @see #db_default_hash(DBType) - */ +* Default hasher for DB_UINT databases. +* Just returns the value of the key. +* <code>maxlen</code> is ignored. +* @param key Key to be hashed +* @param maxlen Maximum length of the key to hash +* @return hash of the key +* @see DBType#DB_UINT +* @see #DBHasher +* @see #db_default_hash(DBType) +*/ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen) { (void)maxlen;//not used @@ -952,14 +957,14 @@ static unsigned int db_uint_hash(DBKey key, unsigned short maxlen) } /** - * Default hasher for DB_STRING databases. - * @param key Key to be hashed - * @param maxlen Maximum length of the key to hash - * @return hash of the key - * @see DBType#DB_STRING - * @see #DBHasher - * @see #db_default_hash(DBType) - */ +* Default hasher for DB_STRING databases. +* @param key Key to be hashed +* @param maxlen Maximum length of the key to hash +* @return hash of the key +* @see DBType#DB_STRING +* @see #DBHasher +* @see #db_default_hash(DBType) +*/ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) { const char *k = key.str; @@ -979,13 +984,13 @@ static unsigned int db_string_hash(DBKey key, unsigned short maxlen) } /** - * Default hasher for DB_ISTRING databases. - * @param key Key to be hashed - * @param maxlen Maximum length of the key to hash - * @return hash of the key - * @see DBType#DB_ISTRING - * @see #db_default_hash(DBType) - */ +* Default hasher for DB_ISTRING databases. +* @param key Key to be hashed +* @param maxlen Maximum length of the key to hash +* @return hash of the key +* @see DBType#DB_ISTRING +* @see #db_default_hash(DBType) +*/ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen) { const char *k = key.str; @@ -1005,14 +1010,14 @@ static unsigned int db_istring_hash(DBKey key, unsigned short maxlen) } /** - * Releaser that releases nothing. - * @param key Key of the database entry - * @param data Data of the database entry - * @param which What is being requested to be released - * @protected - * @see #DBReleaser - * @see #db_default_releaser(DBType,DBOptions) - */ +* Releaser that releases nothing. +* @param key Key of the database entry +* @param data Data of the database entry +* @param which What is being requested to be released +* @protected +* @see #DBReleaser +* @see #db_default_releaser(DBType,DBOptions) +*/ static void db_release_nothing(DBKey key, DBData data, DBRelease which) { (void)key;(void)data;(void)which;//not used @@ -1020,14 +1025,14 @@ static void db_release_nothing(DBKey key, DBData data, DBRelease which) } /** - * Releaser that only releases the key. - * @param key Key of the database entry - * @param data Data of the database entry - * @param which What is being requested to be released - * @protected - * @see #DBReleaser - * @see #db_default_release(DBType,DBOptions) - */ +* Releaser that only releases the key. +* @param key Key of the database entry +* @param data Data of the database entry +* @param which What is being requested to be released +* @protected +* @see #DBReleaser +* @see #db_default_release(DBType,DBOptions) +*/ static void db_release_key(DBKey key, DBData data, DBRelease which) { (void)data;//not used @@ -1036,16 +1041,16 @@ static void db_release_key(DBKey key, DBData data, DBRelease which) } /** - * Releaser that only releases the data. - * @param key Key of the database entry - * @param data Data of the database entry - * @param which What is being requested to be released - * @protected - * @see #DBData - * @see #DBRelease - * @see #DBReleaser - * @see #db_default_release(DBType,DBOptions) - */ +* Releaser that only releases the data. +* @param key Key of the database entry +* @param data Data of the database entry +* @param which What is being requested to be released +* @protected +* @see #DBData +* @see #DBRelease +* @see #DBReleaser +* @see #db_default_release(DBType,DBOptions) +*/ static void db_release_data(DBKey key, DBData data, DBRelease which) { (void)key;//not used @@ -1054,17 +1059,17 @@ static void db_release_data(DBKey key, DBData data, DBRelease which) } /** - * Releaser that releases both key and data. - * @param key Key of the database entry - * @param data Data of the database entry - * @param which What is being requested to be released - * @protected - * @see #DBKey - * @see #DBData - * @see #DBRelease - * @see #DBReleaser - * @see #db_default_release(DBType,DBOptions) - */ +* Releaser that releases both key and data. +* @param key Key of the database entry +* @param data Data of the database entry +* @param which What is being requested to be released +* @protected +* @see #DBKey +* @see #DBData +* @see #DBRelease +* @see #DBReleaser +* @see #db_default_release(DBType,DBOptions) +*/ static void db_release_both(DBKey key, DBData data, DBRelease which) { DB_COUNTSTAT(db_release_both); @@ -1073,52 +1078,52 @@ static void db_release_both(DBKey key, DBData data, DBRelease which) } /*****************************************************************************\ - * (4) Section with protected functions used in the interface of the * - * database and interface of the iterator. * - * dbit_obj_first - Fetches the first entry from the database. * - * dbit_obj_last - Fetches the last entry from the database. * - * dbit_obj_next - Fetches the next entry from the database. * - * dbit_obj_prev - Fetches the previous entry from the database. * - * dbit_obj_exists - Returns true if the current entry exists. * - * dbit_obj_remove - Remove the current entry from the database. * - * dbit_obj_destroy - Destroys the iterator, unlocking the database and * - * freeing used memory. * - * db_obj_iterator - Return a new database iterator. * - * db_obj_exists - Checks if an entry exists. * - * db_obj_get - Get the data identified by the key. * - * db_obj_vgetall - Get the data of the matched entries. * - * db_obj_getall - Get the data of the matched entries. * - * db_obj_vensure - Get the data identified by the key, creating if it * - * doesn't exist yet. * - * db_obj_ensure - Get the data identified by the key, creating if it * - * doesn't exist yet. * - * db_obj_put - Put data identified by the key in the database. * - * db_obj_remove - Remove an entry from the database. * - * db_obj_vforeach - Apply a function to every entry in the database. * - * db_obj_foreach - Apply a function to every entry in the database. * - * db_obj_vclear - Remove all entries from the database. * - * db_obj_clear - Remove all entries from the database. * - * db_obj_vdestroy - Destroy the database, freeing all the used memory. * - * db_obj_destroy - Destroy the database, freeing all the used memory. * - * db_obj_size - Return the size of the database. * - * db_obj_type - Return the type of the database. * - * db_obj_options - Return the options of the database. * +* (4) Section with protected functions used in the interface of the * +* database and interface of the iterator. * +* dbit_obj_first - Fetches the first entry from the database. * +* dbit_obj_last - Fetches the last entry from the database. * +* dbit_obj_next - Fetches the next entry from the database. * +* dbit_obj_prev - Fetches the previous entry from the database. * +* dbit_obj_exists - Returns true if the current entry exists. * +* dbit_obj_remove - Remove the current entry from the database. * +* dbit_obj_destroy - Destroys the iterator, unlocking the database and * +* freeing used memory. * +* db_obj_iterator - Return a new database iterator. * +* db_obj_exists - Checks if an entry exists. * +* db_obj_get - Get the data identified by the key. * +* db_obj_vgetall - Get the data of the matched entries. * +* db_obj_getall - Get the data of the matched entries. * +* db_obj_vensure - Get the data identified by the key, creating if it * +* doesn't exist yet. * +* db_obj_ensure - Get the data identified by the key, creating if it * +* doesn't exist yet. * +* db_obj_put - Put data identified by the key in the database. * +* db_obj_remove - Remove an entry from the database. * +* db_obj_vforeach - Apply a function to every entry in the database. * +* db_obj_foreach - Apply a function to every entry in the database. * +* db_obj_vclear - Remove all entries from the database. * +* db_obj_clear - Remove all entries from the database. * +* db_obj_vdestroy - Destroy the database, freeing all the used memory. * +* db_obj_destroy - Destroy the database, freeing all the used memory. * +* db_obj_size - Return the size of the database. * +* db_obj_type - Return the type of the database. * +* db_obj_options - Return the options of the database. * \*****************************************************************************/ /** - * Fetches the first entry in the database. - * Returns the data of the entry. - * Puts the key in out_key, if out_key is not NULL. - * @param self Iterator - * @param out_key Key of the entry - * @return Data of the entry - * @protected - * @see DBIterator#first - */ +* Fetches the first entry in the database. +* Returns the data of the entry. +* Puts the key in out_key, if out_key is not NULL. +* @param self Iterator +* @param out_key Key of the entry +* @return Data of the entry +* @protected +* @see DBIterator#first +*/ DBData* dbit_obj_first(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; - + DB_COUNTSTAT(dbit_first); // position before the first entry it->ht_index = -1; @@ -1128,19 +1133,19 @@ DBData* dbit_obj_first(DBIterator* self, DBKey* out_key) } /** - * Fetches the last entry in the database. - * Returns the data of the entry. - * Puts the key in out_key, if out_key is not NULL. - * @param self Iterator - * @param out_key Key of the entry - * @return Data of the entry - * @protected - * @see DBIterator#last - */ +* Fetches the last entry in the database. +* Returns the data of the entry. +* Puts the key in out_key, if out_key is not NULL. +* @param self Iterator +* @param out_key Key of the entry +* @return Data of the entry +* @protected +* @see DBIterator#last +*/ DBData* dbit_obj_last(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; - + DB_COUNTSTAT(dbit_last); // position after the last entry it->ht_index = HASH_SIZE; @@ -1150,15 +1155,15 @@ DBData* dbit_obj_last(DBIterator* self, DBKey* out_key) } /** - * Fetches the next entry in the database. - * Returns the data of the entry. - * Puts the key in out_key, if out_key is not NULL. - * @param self Iterator - * @param out_key Key of the entry - * @return Data of the entry - * @protected - * @see DBIterator#next - */ +* Fetches the next entry in the database. +* Returns the data of the entry. +* Puts the key in out_key, if out_key is not NULL. +* @param self Iterator +* @param out_key Key of the entry +* @return Data of the entry +* @protected +* @see DBIterator#next +*/ DBData* dbit_obj_next(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; @@ -1226,15 +1231,15 @@ DBData* dbit_obj_next(DBIterator* self, DBKey* out_key) } /** - * Fetches the previous entry in the database. - * Returns the data of the entry. - * Puts the key in out_key, if out_key is not NULL. - * @param self Iterator - * @param out_key Key of the entry - * @return Data of the entry - * @protected - * @see DBIterator#prev - */ +* Fetches the previous entry in the database. +* Returns the data of the entry. +* Puts the key in out_key, if out_key is not NULL. +* @param self Iterator +* @param out_key Key of the entry +* @return Data of the entry +* @protected +* @see DBIterator#prev +*/ DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) { DBIterator_impl* it = (DBIterator_impl*)self; @@ -1262,7 +1267,7 @@ DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) node = &fake; } - + while( node ) {// next node if( node->left ) @@ -1303,14 +1308,14 @@ DBData* dbit_obj_prev(DBIterator* self, DBKey* out_key) } /** - * Returns true if the fetched entry exists. - * The databases entries might have NULL data, so use this to to test if - * the iterator is done. - * @param self Iterator - * @return true if the entry exists - * @protected - * @see DBIterator#exists - */ +* Returns true if the fetched entry exists. +* The databases entries might have NULL data, so use this to to test if +* the iterator is done. +* @param self Iterator +* @return true if the entry exists +* @protected +* @see DBIterator#exists +*/ bool dbit_obj_exists(DBIterator* self) { DBIterator_impl* it = (DBIterator_impl*)self; @@ -1320,17 +1325,17 @@ bool dbit_obj_exists(DBIterator* self) } /** - * Removes the current entry from the database. - * NOTE: {@link DBIterator#exists} will return false until another entry - * is fetched - * Puts data of the removed entry in out_data, if out_data is not NULL. - * @param self Iterator - * @param out_data Data of the removed entry. - * @return 1 if entry was removed, 0 otherwise - * @protected - * @see DBMap#remove - * @see DBIterator#remove - */ +* Removes the current entry from the database. +* NOTE: {@link DBIterator#exists} will return false until another entry +* is fetched +* Puts data of the removed entry in out_data, if out_data is not NULL. +* @param self Iterator +* @param out_data Data of the removed entry. +* @return 1 if entry was removed, 0 otherwise +* @protected +* @see DBMap#remove +* @see DBIterator#remove +*/ int dbit_obj_remove(DBIterator* self, DBData *out_data) { DBIterator_impl* it = (DBIterator_impl*)self; @@ -1354,10 +1359,10 @@ int dbit_obj_remove(DBIterator* self, DBData *out_data) } /** - * Destroys this iterator and unlocks the database. - * @param self Iterator - * @protected - */ +* Destroys this iterator and unlocks the database. +* @param self Iterator +* @protected +*/ void dbit_obj_destroy(DBIterator* self) { DBIterator_impl* it = (DBIterator_impl*)self; @@ -1366,25 +1371,25 @@ void dbit_obj_destroy(DBIterator* self) // unlock the database db_free_unlock(it->db); // free iterator - aFree(self); + ers_free(db_iterator_ers,self); } /** - * Returns a new iterator for this database. - * The iterator keeps the database locked until it is destroyed. - * The database will keep functioning normally but will only free internal - * memory when unlocked, so destroy the iterator as soon as possible. - * @param self Database - * @return New iterator - * @protected - */ +* Returns a new iterator for this database. +* The iterator keeps the database locked until it is destroyed. +* The database will keep functioning normally but will only free internal +* memory when unlocked, so destroy the iterator as soon as possible. +* @param self Database +* @return New iterator +* @protected +*/ static DBIterator* db_obj_iterator(DBMap* self) { DBMap_impl* db = (DBMap_impl*)self; DBIterator_impl* it; DB_COUNTSTAT(db_iterator); - CREATE(it, struct DBIterator_impl, 1); + it = ers_alloc(db_iterator_ers, struct DBIterator_impl); /* Interface of the iterator **/ it->vtable.first = dbit_obj_first; it->vtable.last = dbit_obj_last; @@ -1403,13 +1408,13 @@ static DBIterator* db_obj_iterator(DBMap* self) } /** - * Returns true if the entry exists. - * @param self Interface of the database - * @param key Key that identifies the entry - * @return true is the entry exists - * @protected - * @see DBMap#exists - */ +* Returns true if the entry exists. +* @param self Interface of the database +* @param key Key that identifies the entry +* @return true is the entry exists +* @protected +* @see DBMap#exists +*/ static bool db_obj_exists(DBMap* self, DBKey key) { DBMap_impl* db = (DBMap_impl*)self; @@ -1454,13 +1459,13 @@ static bool db_obj_exists(DBMap* self, DBKey key) } /** - * Get the data of the entry identified by the key. - * @param self Interface of the database - * @param key Key that identifies the entry - * @return Data of the entry or NULL if not found - * @protected - * @see DBMap#get - */ +* Get the data of the entry identified by the key. +* @param self Interface of the database +* @param key Key that identifies the entry +* @return Data of the entry or NULL if not found +* @protected +* @see DBMap#get +*/ static DBData* db_obj_get(DBMap* self, DBKey key) { DBMap_impl* db = (DBMap_impl*)self; @@ -1506,21 +1511,21 @@ static DBData* db_obj_get(DBMap* self, DBKey key) } /** - * Get the data of the entries matched by <code>match</code>. - * It puts a maximum of <code>max</code> entries into <code>buf</code>. - * If <code>buf</code> is NULL, it only counts the matches. - * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the - * first <code>max</code> entries found are put into the buffer. - * @param self Interface of the database - * @param buf Buffer to put the data of the matched entries - * @param max Maximum number of data entries to be put into buf - * @param match Function that matches the database entries - * @param ... Extra arguments for match - * @return The number of entries that matched - * @protected - * @see DBMap#vgetall - */ +* Get the data of the entries matched by <code>match</code>. +* It puts a maximum of <code>max</code> entries into <code>buf</code>. +* If <code>buf</code> is NULL, it only counts the matches. +* Returns the number of entries that matched. +* NOTE: if the value returned is greater than <code>max</code>, only the +* first <code>max</code> entries found are put into the buffer. +* @param self Interface of the database +* @param buf Buffer to put the data of the matched entries +* @param max Maximum number of data entries to be put into buf +* @param match Function that matches the database entries +* @param ... Extra arguments for match +* @return The number of entries that matched +* @protected +* @see DBMap#vgetall +*/ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, DBMatcher match, va_list args) { DBMap_impl* db = (DBMap_impl*)self; @@ -1549,17 +1554,17 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, } va_end(argscopy); } - + if (node->left) { node = node->left; continue; } - + if (node->right) { node = node->right; continue; } - + while (node) { parent = node->parent; if (parent && parent->right && parent->left == node) { @@ -1576,23 +1581,23 @@ static unsigned int db_obj_vgetall(DBMap* self, DBData **buf, unsigned int max, } /** - * Just calls {@link DBMap#vgetall}. - * Get the data of the entries matched by <code>match</code>. - * It puts a maximum of <code>max</code> entries into <code>buf</code>. - * If <code>buf</code> is NULL, it only counts the matches. - * Returns the number of entries that matched. - * NOTE: if the value returned is greater than <code>max</code>, only the - * first <code>max</code> entries found are put into the buffer. - * @param self Interface of the database - * @param buf Buffer to put the data of the matched entries - * @param max Maximum number of data entries to be put into buf - * @param match Function that matches the database entries - * @param ... Extra arguments for match - * @return The number of entries that matched - * @protected - * @see DBMap#vgetall - * @see DBMap#getall - */ +* Just calls {@link DBMap#vgetall}. +* Get the data of the entries matched by <code>match</code>. +* It puts a maximum of <code>max</code> entries into <code>buf</code>. +* If <code>buf</code> is NULL, it only counts the matches. +* Returns the number of entries that matched. +* NOTE: if the value returned is greater than <code>max</code>, only the +* first <code>max</code> entries found are put into the buffer. +* @param self Interface of the database +* @param buf Buffer to put the data of the matched entries +* @param max Maximum number of data entries to be put into buf +* @param match Function that matches the database entries +* @param ... Extra arguments for match +* @return The number of entries that matched +* @protected +* @see DBMap#vgetall +* @see DBMap#getall +*/ static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, DBMatcher match, ...) { va_list args; @@ -1608,17 +1613,17 @@ static unsigned int db_obj_getall(DBMap* self, DBData **buf, unsigned int max, D } /** - * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by - * <code>create</code>. - * @param self Interface of the database - * @param key Key that identifies the entry - * @param create Function used to create the data if the entry doesn't exist - * @param args Extra arguments for create - * @return Data of the entry - * @protected - * @see DBMap#vensure - */ +* Get the data of the entry identified by the key. +* If the entry does not exist, an entry is added with the data returned by +* <code>create</code>. +* @param self Interface of the database +* @param key Key that identifies the entry +* @param create Function used to create the data if the entry doesn't exist +* @param args Extra arguments for create +* @return Data of the entry +* @protected +* @see DBMap#vensure +*/ static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_list args) { DBMap_impl* db = (DBMap_impl*)self; @@ -1661,9 +1666,9 @@ static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_li va_list argscopy; if (db->item_count == UINT32_MAX) { ShowError("db_vensure: item_count overflow, aborting item insertion.\n" - "Database allocated at %s:%d", - db->alloc_file, db->alloc_line); - return NULL; + "Database allocated at %s:%d", + db->alloc_file, db->alloc_line); + return NULL; } DB_COUNTSTAT(db_node_alloc); node = ers_alloc(db->nodes, struct dbn); @@ -1706,19 +1711,19 @@ static DBData* db_obj_vensure(DBMap* self, DBKey key, DBCreateData create, va_li } /** - * Just calls {@link DBMap#vensure}. - * Get the data of the entry identified by the key. - * If the entry does not exist, an entry is added with the data returned by - * <code>create</code>. - * @param self Interface of the database - * @param key Key that identifies the entry - * @param create Function used to create the data if the entry doesn't exist - * @param ... Extra arguments for create - * @return Data of the entry - * @protected - * @see DBMap#vensure - * @see DBMap#ensure - */ +* Just calls {@link DBMap#vensure}. +* Get the data of the entry identified by the key. +* If the entry does not exist, an entry is added with the data returned by +* <code>create</code>. +* @param self Interface of the database +* @param key Key that identifies the entry +* @param create Function used to create the data if the entry doesn't exist +* @param ... Extra arguments for create +* @return Data of the entry +* @protected +* @see DBMap#vensure +* @see DBMap#ensure +*/ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) { va_list args; @@ -1734,18 +1739,18 @@ static DBData* db_obj_ensure(DBMap* self, DBKey key, DBCreateData create, ...) } /** - * Put the data identified by the key in the database. - * Puts the previous data in out_data, if out_data is not NULL. - * NOTE: Uses the new key, the old one is released. - * @param self Interface of the database - * @param key Key that identifies the data - * @param data Data to be put in the database - * @param out_data Previous data if the entry exists - * @return 1 if if the entry already exists, 0 otherwise - * @protected - * @see #db_malloc_dbn(void) - * @see DBMap#put - */ +* Put the data identified by the key in the database. +* Puts the previous data in out_data, if out_data is not NULL. +* NOTE: Uses the new key, the old one is released. +* @param self Interface of the database +* @param key Key that identifies the data +* @param data Data to be put in the database +* @param out_data Previous data if the entry exists +* @return 1 if if the entry already exists, 0 otherwise +* @protected +* @see #db_malloc_dbn(void) +* @see DBMap#put +*/ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; @@ -1758,8 +1763,8 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) if (db == NULL) return 0; // nullpo candidate if (db->global_lock) { ShowError("db_put: Database is being destroyed, aborting entry insertion.\n" - "Database allocated at %s:%d\n", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->alloc_file, db->alloc_line); return 0; // nullpo candidate } if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) { @@ -1773,8 +1778,8 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) if (db->item_count == UINT32_MAX) { ShowError("db_put: item_count overflow, aborting item insertion.\n" - "Database allocated at %s:%d", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d", + db->alloc_file, db->alloc_line); return 0; } // search for an equal node @@ -1840,17 +1845,17 @@ static int db_obj_put(DBMap* self, DBKey key, DBData data, DBData *out_data) } /** - * Remove an entry from the database. - * Puts the previous data in out_data, if out_data is not NULL. - * NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode,DBNode *)}. - * @param self Interface of the database - * @param key Key that identifies the entry - * @param out_data Previous data if the entry exists - * @return 1 if if the entry already exists, 0 otherwise - * @protected - * @see #db_free_add(DBMap_impl*,DBNode,DBNode *) - * @see DBMap#remove - */ +* Remove an entry from the database. +* Puts the previous data in out_data, if out_data is not NULL. +* NOTE: The key (of the database) is released in {@link #db_free_add(DBMap_impl*,DBNode,DBNode *)}. +* @param self Interface of the database +* @param key Key that identifies the entry +* @param out_data Previous data if the entry exists +* @return 1 if if the entry already exists, 0 otherwise +* @protected +* @see #db_free_add(DBMap_impl*,DBNode,DBNode *) +* @see DBMap#remove +*/ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) { DBMap_impl* db = (DBMap_impl*)self; @@ -1862,8 +1867,8 @@ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) if (db == NULL) return 0; // nullpo candidate if (db->global_lock) { ShowError("db_remove: Database is being destroyed. Aborting entry deletion.\n" - "Database allocated at %s:%d\n", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->alloc_file, db->alloc_line); return 0; // nullpo candidate } if (!(db->options&DB_OPT_ALLOW_NULL_KEY) && db_is_key_null(db->type, key)) { @@ -1897,15 +1902,15 @@ static int db_obj_remove(DBMap* self, DBKey key, DBData *out_data) } /** - * Apply <code>func</code> to every entry in the database. - * Returns the sum of values returned by func. - * @param self Interface of the database - * @param func Function to be applied - * @param args Extra arguments for func - * @return Sum of the values returned by func - * @protected - * @see DBMap#vforeach - */ +* Apply <code>func</code> to every entry in the database. +* Returns the sum of values returned by func. +* @param self Interface of the database +* @param func Function to be applied +* @param args Extra arguments for func +* @return Sum of the values returned by func +* @protected +* @see DBMap#vforeach +*/ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args) { DBMap_impl* db = (DBMap_impl*)self; @@ -1955,17 +1960,17 @@ static int db_obj_vforeach(DBMap* self, DBApply func, va_list args) } /** - * Just calls {@link DBMap#vforeach}. - * Apply <code>func</code> to every entry in the database. - * Returns the sum of values returned by func. - * @param self Interface of the database - * @param func Function to be applyed - * @param ... Extra arguments for func - * @return Sum of the values returned by func - * @protected - * @see DBMap#vforeach - * @see DBMap#foreach - */ +* Just calls {@link DBMap#vforeach}. +* Apply <code>func</code> to every entry in the database. +* Returns the sum of values returned by func. +* @param self Interface of the database +* @param func Function to be applyed +* @param ... Extra arguments for func +* @return Sum of the values returned by func +* @protected +* @see DBMap#vforeach +* @see DBMap#foreach +*/ static int db_obj_foreach(DBMap* self, DBApply func, ...) { va_list args; @@ -1981,17 +1986,17 @@ static int db_obj_foreach(DBMap* self, DBApply func, ...) } /** - * Removes all entries from the database. - * Before deleting an entry, func is applied to it. - * Releases the key and the data. - * Returns the sum of values returned by func, if it exists. - * @param self Interface of the database - * @param func Function to be applied to every entry before deleting - * @param args Extra arguments for func - * @return Sum of values returned by func - * @protected - * @see DBMap#vclear - */ +* Removes all entries from the database. +* Before deleting an entry, func is applied to it. +* Releases the key and the data. +* Returns the sum of values returned by func, if it exists. +* @param self Interface of the database +* @param func Function to be applied to every entry before deleting +* @param args Extra arguments for func +* @return Sum of values returned by func +* @protected +* @see DBMap#vclear +*/ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) { DBMap_impl* db = (DBMap_impl*)self; @@ -2051,21 +2056,21 @@ static int db_obj_vclear(DBMap* self, DBApply func, va_list args) } /** - * Just calls {@link DBMap#vclear}. - * Removes all entries from the database. - * Before deleting an entry, func is applied to it. - * Releases the key and the data. - * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove - * a database entry will give an error and be aborted (except for clearing). - * @param self Interface of the database - * @param func Function to be applied to every entry before deleting - * @param ... Extra arguments for func - * @return Sum of values returned by func - * @protected - * @see DBMap#vclear - * @see DBMap#clear - */ +* Just calls {@link DBMap#vclear}. +* Removes all entries from the database. +* Before deleting an entry, func is applied to it. +* Releases the key and the data. +* Returns the sum of values returned by func, if it exists. +* NOTE: This locks the database globally. Any attempt to insert or remove +* a database entry will give an error and be aborted (except for clearing). +* @param self Interface of the database +* @param func Function to be applied to every entry before deleting +* @param ... Extra arguments for func +* @return Sum of values returned by func +* @protected +* @see DBMap#vclear +* @see DBMap#clear +*/ static int db_obj_clear(DBMap* self, DBApply func, ...) { va_list args; @@ -2081,18 +2086,18 @@ static int db_obj_clear(DBMap* self, DBApply func, ...) } /** - * Finalize the database, feeing all the memory it uses. - * Before deleting an entry, func is applied to it. - * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove - * a database entry will give an error and be aborted (except for clearing). - * @param self Interface of the database - * @param func Function to be applied to every entry before deleting - * @param args Extra arguments for func - * @return Sum of values returned by func - * @protected - * @see DBMap#vdestroy - */ +* Finalize the database, feeing all the memory it uses. +* Before deleting an entry, func is applied to it. +* Returns the sum of values returned by func, if it exists. +* NOTE: This locks the database globally. Any attempt to insert or remove +* a database entry will give an error and be aborted (except for clearing). +* @param self Interface of the database +* @param func Function to be applied to every entry before deleting +* @param args Extra arguments for func +* @return Sum of values returned by func +* @protected +* @see DBMap#vdestroy +*/ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args) { DBMap_impl* db = (DBMap_impl*)self; @@ -2102,21 +2107,21 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args) if (db == NULL) return 0; // nullpo candidate if (db->global_lock) { ShowError("db_vdestroy: Database is already locked for destruction. Aborting second database destruction.\n" - "Database allocated at %s:%d\n", - db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->alloc_file, db->alloc_line); return 0; } if (db->free_lock) ShowWarning("db_vdestroy: Database is still in use, %u lock(s) left. Continuing database destruction.\n" - "Database allocated at %s:%d\n", - db->free_lock, db->alloc_file, db->alloc_line); + "Database allocated at %s:%d\n", + db->free_lock, db->alloc_file, db->alloc_line); #ifdef DB_ENABLE_STATS switch (db->type) { - case DB_INT: DB_COUNTSTAT(db_int_destroy); break; - case DB_UINT: DB_COUNTSTAT(db_uint_destroy); break; - case DB_STRING: DB_COUNTSTAT(db_string_destroy); break; - case DB_ISTRING: DB_COUNTSTAT(db_istring_destroy); break; + case DB_INT: DB_COUNTSTAT(db_int_destroy); break; + case DB_UINT: DB_COUNTSTAT(db_uint_destroy); break; + case DB_STRING: DB_COUNTSTAT(db_string_destroy); break; + case DB_ISTRING: DB_COUNTSTAT(db_istring_destroy); break; } #endif /* DB_ENABLE_STATS */ db_free_lock(db); @@ -2127,26 +2132,26 @@ static int db_obj_vdestroy(DBMap* self, DBApply func, va_list args) db->free_max = 0; ers_destroy(db->nodes); db_free_unlock(db); - aFree(db); + ers_free(db_alloc_ers, db); return sum; } /** - * Just calls {@link DBMap#db_vdestroy}. - * Finalize the database, feeing all the memory it uses. - * Before deleting an entry, func is applied to it. - * Releases the key and the data. - * Returns the sum of values returned by func, if it exists. - * NOTE: This locks the database globally. Any attempt to insert or remove - * a database entry will give an error and be aborted. - * @param self Database - * @param func Function to be applied to every entry before deleting - * @param ... Extra arguments for func - * @return Sum of values returned by func - * @protected - * @see DBMap#vdestroy - * @see DBMap#destroy - */ +* Just calls {@link DBMap#db_vdestroy}. +* Finalize the database, feeing all the memory it uses. +* Before deleting an entry, func is applied to it. +* Releases the key and the data. +* Returns the sum of values returned by func, if it exists. +* NOTE: This locks the database globally. Any attempt to insert or remove +* a database entry will give an error and be aborted. +* @param self Database +* @param func Function to be applied to every entry before deleting +* @param ... Extra arguments for func +* @return Sum of values returned by func +* @protected +* @see DBMap#vdestroy +* @see DBMap#destroy +*/ static int db_obj_destroy(DBMap* self, DBApply func, ...) { va_list args; @@ -2162,13 +2167,13 @@ static int db_obj_destroy(DBMap* self, DBApply func, ...) } /** - * Return the size of the database (number of items in the database). - * @param self Interface of the database - * @return Size of the database - * @protected - * @see DBMap_impl#item_count - * @see DBMap#size - */ +* Return the size of the database (number of items in the database). +* @param self Interface of the database +* @return Size of the database +* @protected +* @see DBMap_impl#item_count +* @see DBMap#size +*/ static unsigned int db_obj_size(DBMap* self) { DBMap_impl* db = (DBMap_impl*)self; @@ -2185,13 +2190,13 @@ static unsigned int db_obj_size(DBMap* self) } /** - * Return the type of database. - * @param self Interface of the database - * @return Type of the database - * @protected - * @see DBMap_impl#type - * @see DBMap#type - */ +* Return the type of database. +* @param self Interface of the database +* @return Type of the database +* @protected +* @see DBMap_impl#type +* @see DBMap#type +*/ static DBType db_obj_type(DBMap* self) { DBMap_impl* db = (DBMap_impl*)self; @@ -2208,13 +2213,13 @@ static DBType db_obj_type(DBMap* self) } /** - * Return the options of the database. - * @param self Interface of the database - * @return Options of the database - * @protected - * @see DBMap_impl#options - * @see DBMap#options - */ +* Return the options of the database. +* @param self Interface of the database +* @return Options of the database +* @protected +* @see DBMap_impl#options +* @see DBMap#options +*/ static DBOptions db_obj_options(DBMap* self) { DBMap_impl* db = (DBMap_impl*)self; @@ -2231,120 +2236,121 @@ static DBOptions db_obj_options(DBMap* self) } /*****************************************************************************\ - * (5) Section with public functions. - * db_fix_options - Apply database type restrictions to the options. - * db_default_cmp - Get the default comparator for a type of database. - * db_default_hash - Get the default hasher for a type of database. - * db_default_release - Get the default releaser for a type of database with the specified options. - * db_custom_release - Get a releaser that behaves a certains way. - * db_alloc - Allocate a new database. - * db_i2key - Manual cast from 'int' to 'DBKey'. - * db_ui2key - Manual cast from 'unsigned int' to 'DBKey'. - * db_str2key - Manual cast from 'unsigned char *' to 'DBKey'. - * db_i2data - Manual cast from 'int' to 'DBData'. - * db_ui2data - Manual cast from 'unsigned int' to 'DBData'. - * db_ptr2data - Manual cast from 'void*' to 'DBData'. - * db_data2i - Gets 'int' value from 'DBData'. - * db_data2ui - Gets 'unsigned int' value from 'DBData'. - * db_data2ptr - Gets 'void*' value from 'DBData'. - * db_init - Initializes the database system. - * db_final - Finalizes the database system. +* (5) Section with public functions. +* db_fix_options - Apply database type restrictions to the options. +* db_default_cmp - Get the default comparator for a type of database. +* db_default_hash - Get the default hasher for a type of database. +* db_default_release - Get the default releaser for a type of database with the specified options. +* db_custom_release - Get a releaser that behaves a certains way. +* db_alloc - Allocate a new database. +* db_i2key - Manual cast from 'int' to 'DBKey'. +* db_ui2key - Manual cast from 'unsigned int' to 'DBKey'. +* db_str2key - Manual cast from 'unsigned char *' to 'DBKey'. +* db_i2data - Manual cast from 'int' to 'DBData'. +* db_ui2data - Manual cast from 'unsigned int' to 'DBData'. +* db_ptr2data - Manual cast from 'void*' to 'DBData'. +* db_data2i - Gets 'int' value from 'DBData'. +* db_data2ui - Gets 'unsigned int' value from 'DBData'. +* db_data2ptr - Gets 'void*' value from 'DBData'. +* db_init - Initializes the database system. +* db_final - Finalizes the database system. \*****************************************************************************/ /** - * Returns the fixed options according to the database type. - * Sets required options and unsets unsupported options. - * For numeric databases DB_OPT_DUP_KEY and DB_OPT_RELEASE_KEY are unset. - * @param type Type of the database - * @param options Original options of the database - * @return Fixed options of the database - * @private - * @see #db_default_release(DBType,DBOptions) - * @see #db_alloc(const char *,int,DBType,DBOptions,unsigned short) - */ +* Returns the fixed options according to the database type. +* Sets required options and unsets unsupported options. +* For numeric databases DB_OPT_DUP_KEY and DB_OPT_RELEASE_KEY are unset. +* @param type Type of the database +* @param options Original options of the database +* @return Fixed options of the database +* @private +* @see #db_default_release(DBType,DBOptions) +* @see #db_alloc(const char *,int,DBType,DBOptions,unsigned short) +*/ DBOptions db_fix_options(DBType type, DBOptions options) { DB_COUNTSTAT(db_fix_options); switch (type) { - case DB_INT: - case DB_UINT: // Numeric database, do nothing with the keys - return (DBOptions)(options&~(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY)); - - default: - ShowError("db_fix_options: Unknown database type %u with options %x\n", type, options); - case DB_STRING: - case DB_ISTRING: // String databases, no fix required - return options; + case DB_INT: + case DB_UINT: // Numeric database, do nothing with the keys + return (DBOptions)(options&~(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY)); + + default: + ShowError("db_fix_options: Unknown database type %u with options %x\n", type, options); + case DB_STRING: + case DB_ISTRING: // String databases, no fix required + return options; } } + /** - * Returns the default comparator for the specified type of database. - * @param type Type of database - * @return Comparator for the type of database or NULL if unknown database - * @public - * @see #db_int_cmp(DBKey,DBKey,unsigned short) - * @see #db_uint_cmp(DBKey,DBKey,unsigned short) - * @see #db_string_cmp(DBKey,DBKey,unsigned short) - * @see #db_istring_cmp(DBKey,DBKey,unsigned short) - */ +* Returns the default comparator for the specified type of database. +* @param type Type of database +* @return Comparator for the type of database or NULL if unknown database +* @public +* @see #db_int_cmp(DBKey,DBKey,unsigned short) +* @see #db_uint_cmp(DBKey,DBKey,unsigned short) +* @see #db_string_cmp(DBKey,DBKey,unsigned short) +* @see #db_istring_cmp(DBKey,DBKey,unsigned short) +*/ DBComparator db_default_cmp(DBType type) { DB_COUNTSTAT(db_default_cmp); switch (type) { - case DB_INT: return &db_int_cmp; - case DB_UINT: return &db_uint_cmp; - case DB_STRING: return &db_string_cmp; - case DB_ISTRING: return &db_istring_cmp; - default: - ShowError("db_default_cmp: Unknown database type %u\n", type); - return NULL; + case DB_INT: return &db_int_cmp; + case DB_UINT: return &db_uint_cmp; + case DB_STRING: return &db_string_cmp; + case DB_ISTRING: return &db_istring_cmp; + default: + ShowError("db_default_cmp: Unknown database type %u\n", type); + return NULL; } } /** - * Returns the default hasher for the specified type of database. - * @param type Type of database - * @return Hasher of the type of database or NULL if unknown database - * @public - * @see #db_int_hash(DBKey,unsigned short) - * @see #db_uint_hash(DBKey,unsigned short) - * @see #db_string_hash(DBKey,unsigned short) - * @see #db_istring_hash(DBKey,unsigned short) - */ +* Returns the default hasher for the specified type of database. +* @param type Type of database +* @return Hasher of the type of database or NULL if unknown database +* @public +* @see #db_int_hash(DBKey,unsigned short) +* @see #db_uint_hash(DBKey,unsigned short) +* @see #db_string_hash(DBKey,unsigned short) +* @see #db_istring_hash(DBKey,unsigned short) +*/ DBHasher db_default_hash(DBType type) { DB_COUNTSTAT(db_default_hash); switch (type) { - case DB_INT: return &db_int_hash; - case DB_UINT: return &db_uint_hash; - case DB_STRING: return &db_string_hash; - case DB_ISTRING: return &db_istring_hash; - default: - ShowError("db_default_hash: Unknown database type %u\n", type); - return NULL; + case DB_INT: return &db_int_hash; + case DB_UINT: return &db_uint_hash; + case DB_STRING: return &db_string_hash; + case DB_ISTRING: return &db_istring_hash; + default: + ShowError("db_default_hash: Unknown database type %u\n", type); + return NULL; } } /** - * Returns the default releaser for the specified type of database with the - * specified options. - * NOTE: the options are fixed with {@link #db_fix_options(DBType,DBOptions)} - * before choosing the releaser. - * @param type Type of database - * @param options Options of the database - * @return Default releaser for the type of database with the specified options - * @public - * @see #db_release_nothing(DBKey,DBData,DBRelease) - * @see #db_release_key(DBKey,DBData,DBRelease) - * @see #db_release_data(DBKey,DBData,DBRelease) - * @see #db_release_both(DBKey,DBData,DBRelease) - * @see #db_custom_release(DBRelease) - */ +* Returns the default releaser for the specified type of database with the +* specified options. +* NOTE: the options are fixed with {@link #db_fix_options(DBType,DBOptions)} +* before choosing the releaser. +* @param type Type of database +* @param options Options of the database +* @return Default releaser for the type of database with the specified options +* @public +* @see #db_release_nothing(DBKey,DBData,DBRelease) +* @see #db_release_key(DBKey,DBData,DBRelease) +* @see #db_release_data(DBKey,DBData,DBRelease) +* @see #db_release_both(DBKey,DBData,DBRelease) +* @see #db_custom_release(DBRelease) +*/ DBReleaser db_default_release(DBType type, DBOptions options) { DB_COUNTSTAT(db_default_release); - options = db_fix_options(type, options); + options = DB->fix_options(type, options); if (options&DB_OPT_RELEASE_DATA) { // Release data, what about the key? if (options&(DB_OPT_DUP_KEY|DB_OPT_RELEASE_KEY)) return &db_release_both; // Release both key and data @@ -2356,45 +2362,45 @@ DBReleaser db_default_release(DBType type, DBOptions options) } /** - * Returns the releaser that releases the specified release options. - * @param which Options that specified what the releaser releases - * @return Releaser for the specified release options - * @public - * @see #db_release_nothing(DBKey,DBData,DBRelease) - * @see #db_release_key(DBKey,DBData,DBRelease) - * @see #db_release_data(DBKey,DBData,DBRelease) - * @see #db_release_both(DBKey,DBData,DBRelease) - * @see #db_default_release(DBType,DBOptions) - */ +* Returns the releaser that releases the specified release options. +* @param which Options that specified what the releaser releases +* @return Releaser for the specified release options +* @public +* @see #db_release_nothing(DBKey,DBData,DBRelease) +* @see #db_release_key(DBKey,DBData,DBRelease) +* @see #db_release_data(DBKey,DBData,DBRelease) +* @see #db_release_both(DBKey,DBData,DBRelease) +* @see #db_default_release(DBType,DBOptions) +*/ DBReleaser db_custom_release(DBRelease which) { DB_COUNTSTAT(db_custom_release); switch (which) { - case DB_RELEASE_NOTHING: return &db_release_nothing; - case DB_RELEASE_KEY: return &db_release_key; - case DB_RELEASE_DATA: return &db_release_data; - case DB_RELEASE_BOTH: return &db_release_both; - default: - ShowError("db_custom_release: Unknown release options %u\n", which); - return NULL; + case DB_RELEASE_NOTHING: return &db_release_nothing; + case DB_RELEASE_KEY: return &db_release_key; + case DB_RELEASE_DATA: return &db_release_data; + case DB_RELEASE_BOTH: return &db_release_both; + default: + ShowError("db_custom_release: Unknown release options %u\n", which); + return NULL; } } /** - * Allocate a new database of the specified type. - * NOTE: the options are fixed by {@link #db_fix_options(DBType,DBOptions)} - * before creating the database. - * @param file File where the database is being allocated - * @param line Line of the file where the database is being allocated - * @param type Type of database - * @param options Options of the database - * @param maxlen Maximum length of the string to be used as key in string - * databases. If 0, the maximum number of maxlen is used (64K). - * @return The interface of the database - * @public - * @see #DBMap_impl - * @see #db_fix_options(DBType,DBOptions) - */ +* Allocate a new database of the specified type. +* NOTE: the options are fixed by {@link #db_fix_options(DBType,DBOptions)} +* before creating the database. +* @param file File where the database is being allocated +* @param line Line of the file where the database is being allocated +* @param type Type of database +* @param options Options of the database +* @param maxlen Maximum length of the string to be used as key in string +* databases. If 0, the maximum number of maxlen is used (64K). +* @return The interface of the database +* @public +* @see #DBMap_impl +* @see #db_fix_options(DBType,DBOptions) +*/ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen) { DBMap_impl* db; @@ -2403,15 +2409,15 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi #ifdef DB_ENABLE_STATS DB_COUNTSTAT(db_alloc); switch (type) { - case DB_INT: DB_COUNTSTAT(db_int_alloc); break; - case DB_UINT: DB_COUNTSTAT(db_uint_alloc); break; - case DB_STRING: DB_COUNTSTAT(db_string_alloc); break; - case DB_ISTRING: DB_COUNTSTAT(db_istring_alloc); break; + case DB_INT: DB_COUNTSTAT(db_int_alloc); break; + case DB_UINT: DB_COUNTSTAT(db_uint_alloc); break; + case DB_STRING: DB_COUNTSTAT(db_string_alloc); break; + case DB_ISTRING: DB_COUNTSTAT(db_istring_alloc); break; } #endif /* DB_ENABLE_STATS */ - CREATE(db, struct DBMap_impl, 1); + db = ers_alloc(db_alloc_ers, struct DBMap_impl); - options = db_fix_options(type, options); + options = DB->fix_options(type, options); /* Interface of the database */ db->vtable.iterator = db_obj_iterator; db->vtable.exists = db_obj_exists; @@ -2441,9 +2447,9 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi db->free_lock = 0; /* Other */ db->nodes = ers_new(sizeof(struct dbn),"db.c::db_alloc",ERS_OPT_NONE); - db->cmp = db_default_cmp(type); - db->hash = db_default_hash(type); - db->release = db_default_release(type, options); + db->cmp = DB->default_cmp(type); + db->hash = DB->default_hash(type); + db->release = DB->default_release(type, options); for (i = 0; i < HASH_SIZE; i++) db->ht[i] = NULL; db->cache = NULL; @@ -2460,11 +2466,11 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi } /** - * Manual cast from 'int' to the union DBKey. - * @param key Key to be casted - * @return The key as a DBKey union - * @public - */ +* Manual cast from 'int' to the union DBKey. +* @param key Key to be casted +* @return The key as a DBKey union +* @public +*/ DBKey db_i2key(int key) { DBKey ret; @@ -2475,11 +2481,11 @@ DBKey db_i2key(int key) } /** - * Manual cast from 'unsigned int' to the union DBKey. - * @param key Key to be casted - * @return The key as a DBKey union - * @public - */ +* Manual cast from 'unsigned int' to the union DBKey. +* @param key Key to be casted +* @return The key as a DBKey union +* @public +*/ DBKey db_ui2key(unsigned int key) { DBKey ret; @@ -2490,11 +2496,11 @@ DBKey db_ui2key(unsigned int key) } /** - * Manual cast from 'const char *' to the union DBKey. - * @param key Key to be casted - * @return The key as a DBKey union - * @public - */ +* Manual cast from 'const char *' to the union DBKey. +* @param key Key to be casted +* @return The key as a DBKey union +* @public +*/ DBKey db_str2key(const char *key) { DBKey ret; @@ -2505,11 +2511,11 @@ DBKey db_str2key(const char *key) } /** - * Manual cast from 'int' to the struct DBData. - * @param data Data to be casted - * @return The data as a DBData struct - * @public - */ +* Manual cast from 'int' to the struct DBData. +* @param data Data to be casted +* @return The data as a DBData struct +* @public +*/ DBData db_i2data(int data) { DBData ret; @@ -2521,11 +2527,11 @@ DBData db_i2data(int data) } /** - * Manual cast from 'unsigned int' to the struct DBData. - * @param data Data to be casted - * @return The data as a DBData struct - * @public - */ +* Manual cast from 'unsigned int' to the struct DBData. +* @param data Data to be casted +* @return The data as a DBData struct +* @public +*/ DBData db_ui2data(unsigned int data) { DBData ret; @@ -2537,11 +2543,11 @@ DBData db_ui2data(unsigned int data) } /** - * Manual cast from 'void *' to the struct DBData. - * @param data Data to be casted - * @return The data as a DBData struct - * @public - */ +* Manual cast from 'void *' to the struct DBData. +* @param data Data to be casted +* @return The data as a DBData struct +* @public +*/ DBData db_ptr2data(void *data) { DBData ret; @@ -2553,12 +2559,12 @@ DBData db_ptr2data(void *data) } /** - * Gets int type data from struct DBData. - * If data is not int type, returns 0. - * @param data Data - * @return Integer value of the data. - * @public - */ +* Gets int type data from struct DBData. +* If data is not int type, returns 0. +* @param data Data +* @return Integer value of the data. +* @public +*/ int db_data2i(DBData *data) { DB_COUNTSTAT(db_data2i); @@ -2568,12 +2574,12 @@ int db_data2i(DBData *data) } /** - * Gets unsigned int type data from struct DBData. - * If data is not unsigned int type, returns 0. - * @param data Data - * @return Unsigned int value of the data. - * @public - */ +* Gets unsigned int type data from struct DBData. +* If data is not unsigned int type, returns 0. +* @param data Data +* @return Unsigned int value of the data. +* @public +*/ unsigned int db_data2ui(DBData *data) { DB_COUNTSTAT(db_data2ui); @@ -2583,12 +2589,12 @@ unsigned int db_data2ui(DBData *data) } /** - * Gets void* type data from struct DBData. - * If data is not void* type, returns NULL. - * @param data Data - * @return Void* value of the data. - * @public - */ +* Gets void* type data from struct DBData. +* If data is not void* type, returns NULL. +* @param data Data +* @return Void* value of the data. +* @public +*/ void* db_data2ptr(DBData *data) { DB_COUNTSTAT(db_data2ptr); @@ -2598,104 +2604,107 @@ void* db_data2ptr(DBData *data) } /** - * Initializes the database system. - * @public - * @see #db_final(void) - */ -void db_init(void) -{ +* Initializes the database system. +* @public +* @see #db_final(void) +*/ +void db_init(void) { + db_iterator_ers = ers_new(sizeof(struct DBIterator_impl),"db.c::db_iterator_ers",ERS_OPT_NONE); + db_alloc_ers = ers_new(sizeof(struct DBMap_impl),"db.c::db_alloc_ers",ERS_OPT_NONE); DB_COUNTSTAT(db_init); } /** - * Finalizes the database system. - * @public - * @see #db_init(void) - */ +* Finalizes the database system. +* @public +* @see #db_init(void) +*/ void db_final(void) { #ifdef DB_ENABLE_STATS DB_COUNTSTAT(db_final); ShowInfo(CL_WHITE"Database nodes"CL_RESET":\n" - "allocated %u, freed %u\n", - stats.db_node_alloc, stats.db_node_free); + "allocated %u, freed %u\n", + stats.db_node_alloc, stats.db_node_free); ShowInfo(CL_WHITE"Database types"CL_RESET":\n" - "DB_INT : allocated %10u, destroyed %10u\n" - "DB_UINT : allocated %10u, destroyed %10u\n" - "DB_STRING : allocated %10u, destroyed %10u\n" - "DB_ISTRING : allocated %10u, destroyed %10u\n", - stats.db_int_alloc, stats.db_int_destroy, - stats.db_uint_alloc, stats.db_uint_destroy, - stats.db_string_alloc, stats.db_string_destroy, - stats.db_istring_alloc, stats.db_istring_destroy); + "DB_INT : allocated %10u, destroyed %10u\n" + "DB_UINT : allocated %10u, destroyed %10u\n" + "DB_STRING : allocated %10u, destroyed %10u\n" + "DB_ISTRING : allocated %10u, destroyed %10u\n", + stats.db_int_alloc, stats.db_int_destroy, + stats.db_uint_alloc, stats.db_uint_destroy, + stats.db_string_alloc, stats.db_string_destroy, + stats.db_istring_alloc, stats.db_istring_destroy); ShowInfo(CL_WHITE"Database function counters"CL_RESET":\n" - "db_rotate_left %10u, db_rotate_right %10u,\n" - "db_rebalance %10u, db_rebalance_erase %10u,\n" - "db_is_key_null %10u,\n" - "db_dup_key %10u, db_dup_key_free %10u,\n" - "db_free_add %10u, db_free_remove %10u,\n" - "db_free_lock %10u, db_free_unlock %10u,\n" - "db_int_cmp %10u, db_uint_cmp %10u,\n" - "db_string_cmp %10u, db_istring_cmp %10u,\n" - "db_int_hash %10u, db_uint_hash %10u,\n" - "db_string_hash %10u, db_istring_hash %10u,\n" - "db_release_nothing %10u, db_release_key %10u,\n" - "db_release_data %10u, db_release_both %10u,\n" - "dbit_first %10u, dbit_last %10u,\n" - "dbit_next %10u, dbit_prev %10u,\n" - "dbit_exists %10u, dbit_remove %10u,\n" - "dbit_destroy %10u, db_iterator %10u,\n" - "db_exits %10u, db_get %10u,\n" - "db_getall %10u, db_vgetall %10u,\n" - "db_ensure %10u, db_vensure %10u,\n" - "db_put %10u, db_remove %10u,\n" - "db_foreach %10u, db_vforeach %10u,\n" - "db_clear %10u, db_vclear %10u,\n" - "db_destroy %10u, db_vdestroy %10u,\n" - "db_size %10u, db_type %10u,\n" - "db_options %10u, db_fix_options %10u,\n" - "db_default_cmp %10u, db_default_hash %10u,\n" - "db_default_release %10u, db_custom_release %10u,\n" - "db_alloc %10u, db_i2key %10u,\n" - "db_ui2key %10u, db_str2key %10u,\n" - "db_i2data %10u, db_ui2data %10u,\n" - "db_ptr2data %10u, db_data2i %10u,\n" - "db_data2ui %10u, db_data2ptr %10u,\n" - "db_init %10u, db_final %10u\n", - stats.db_rotate_left, stats.db_rotate_right, - stats.db_rebalance, stats.db_rebalance_erase, - stats.db_is_key_null, - stats.db_dup_key, stats.db_dup_key_free, - stats.db_free_add, stats.db_free_remove, - stats.db_free_lock, stats.db_free_unlock, - stats.db_int_cmp, stats.db_uint_cmp, - stats.db_string_cmp, stats.db_istring_cmp, - stats.db_int_hash, stats.db_uint_hash, - stats.db_string_hash, stats.db_istring_hash, - stats.db_release_nothing, stats.db_release_key, - stats.db_release_data, stats.db_release_both, - stats.dbit_first, stats.dbit_last, - stats.dbit_next, stats.dbit_prev, - stats.dbit_exists, stats.dbit_remove, - stats.dbit_destroy, stats.db_iterator, - stats.db_exists, stats.db_get, - stats.db_getall, stats.db_vgetall, - stats.db_ensure, stats.db_vensure, - stats.db_put, stats.db_remove, - stats.db_foreach, stats.db_vforeach, - stats.db_clear, stats.db_vclear, - stats.db_destroy, stats.db_vdestroy, - stats.db_size, stats.db_type, - stats.db_options, stats.db_fix_options, - stats.db_default_cmp, stats.db_default_hash, - stats.db_default_release, stats.db_custom_release, - stats.db_alloc, stats.db_i2key, - stats.db_ui2key, stats.db_str2key, - stats.db_i2data, stats.db_ui2data, - stats.db_ptr2data, stats.db_data2i, - stats.db_data2ui, stats.db_data2ptr, - stats.db_init, stats.db_final); + "db_rotate_left %10u, db_rotate_right %10u,\n" + "db_rebalance %10u, db_rebalance_erase %10u,\n" + "db_is_key_null %10u,\n" + "db_dup_key %10u, db_dup_key_free %10u,\n" + "db_free_add %10u, db_free_remove %10u,\n" + "db_free_lock %10u, db_free_unlock %10u,\n" + "db_int_cmp %10u, db_uint_cmp %10u,\n" + "db_string_cmp %10u, db_istring_cmp %10u,\n" + "db_int_hash %10u, db_uint_hash %10u,\n" + "db_string_hash %10u, db_istring_hash %10u,\n" + "db_release_nothing %10u, db_release_key %10u,\n" + "db_release_data %10u, db_release_both %10u,\n" + "dbit_first %10u, dbit_last %10u,\n" + "dbit_next %10u, dbit_prev %10u,\n" + "dbit_exists %10u, dbit_remove %10u,\n" + "dbit_destroy %10u, db_iterator %10u,\n" + "db_exits %10u, db_get %10u,\n" + "db_getall %10u, db_vgetall %10u,\n" + "db_ensure %10u, db_vensure %10u,\n" + "db_put %10u, db_remove %10u,\n" + "db_foreach %10u, db_vforeach %10u,\n" + "db_clear %10u, db_vclear %10u,\n" + "db_destroy %10u, db_vdestroy %10u,\n" + "db_size %10u, db_type %10u,\n" + "db_options %10u, db_fix_options %10u,\n" + "db_default_cmp %10u, db_default_hash %10u,\n" + "db_default_release %10u, db_custom_release %10u,\n" + "db_alloc %10u, db_i2key %10u,\n" + "db_ui2key %10u, db_str2key %10u,\n" + "db_i2data %10u, db_ui2data %10u,\n" + "db_ptr2data %10u, db_data2i %10u,\n" + "db_data2ui %10u, db_data2ptr %10u,\n" + "db_init %10u, db_final %10u\n", + stats.db_rotate_left, stats.db_rotate_right, + stats.db_rebalance, stats.db_rebalance_erase, + stats.db_is_key_null, + stats.db_dup_key, stats.db_dup_key_free, + stats.db_free_add, stats.db_free_remove, + stats.db_free_lock, stats.db_free_unlock, + stats.db_int_cmp, stats.db_uint_cmp, + stats.db_string_cmp, stats.db_istring_cmp, + stats.db_int_hash, stats.db_uint_hash, + stats.db_string_hash, stats.db_istring_hash, + stats.db_release_nothing, stats.db_release_key, + stats.db_release_data, stats.db_release_both, + stats.dbit_first, stats.dbit_last, + stats.dbit_next, stats.dbit_prev, + stats.dbit_exists, stats.dbit_remove, + stats.dbit_destroy, stats.db_iterator, + stats.db_exists, stats.db_get, + stats.db_getall, stats.db_vgetall, + stats.db_ensure, stats.db_vensure, + stats.db_put, stats.db_remove, + stats.db_foreach, stats.db_vforeach, + stats.db_clear, stats.db_vclear, + stats.db_destroy, stats.db_vdestroy, + stats.db_size, stats.db_type, + stats.db_options, stats.db_fix_options, + stats.db_default_cmp, stats.db_default_hash, + stats.db_default_release, stats.db_custom_release, + stats.db_alloc, stats.db_i2key, + stats.db_ui2key, stats.db_str2key, + stats.db_i2data, stats.db_ui2data, + stats.db_ptr2data, stats.db_data2i, + stats.db_data2ui, stats.db_data2ptr, + stats.db_init, stats.db_final); #endif /* DB_ENABLE_STATS */ + ers_destroy(db_iterator_ers); + ers_destroy(db_alloc_ers); } // Link DB System - jAthena @@ -2820,3 +2829,25 @@ void linkdb_final( struct linkdb_node** head ) } *head = NULL; } + +void db_defaults(void) +{ + DB = &DB_s; + DB->alloc = db_alloc; + DB->custom_release = db_custom_release; + DB->data2i = db_data2i; + DB->data2ptr = db_data2ptr; + DB->data2ui = db_data2ui; + DB->default_cmp = db_default_cmp; + DB->default_hash = db_default_hash; + DB->default_release = db_default_release; + DB->final = db_final; + DB->fix_options = db_fix_options; + DB->i2data = db_i2data; + DB->i2key = db_i2key; + DB->init = db_init; + DB->ptr2data = db_ptr2data; + DB->str2key = db_str2key; + DB->ui2data = db_ui2data; + DB->ui2key = db_ui2key; +}
\ No newline at end of file diff --git a/src/common/db.h b/src/common/db.h index 4fe6a93d6..f1f6146be 100644 --- a/src/common/db.h +++ b/src/common/db.h @@ -599,73 +599,73 @@ struct DBMap { // For easy access to the common functions. #define db_exists(db,k) ( (db)->exists((db),(k)) ) -#define idb_exists(db,k) ( (db)->exists((db),db_i2key(k)) ) -#define uidb_exists(db,k) ( (db)->exists((db),db_ui2key(k)) ) -#define strdb_exists(db,k) ( (db)->exists((db),db_str2key(k)) ) +#define idb_exists(db,k) ( (db)->exists((db),DB->i2key(k)) ) +#define uidb_exists(db,k) ( (db)->exists((db),DB->ui2key(k)) ) +#define strdb_exists(db,k) ( (db)->exists((db),DB->str2key(k)) ) // Get pointer-type data from DBMaps of various key types -#define db_get(db,k) ( db_data2ptr((db)->get((db),(k))) ) -#define idb_get(db,k) ( db_data2ptr((db)->get((db),db_i2key(k))) ) -#define uidb_get(db,k) ( db_data2ptr((db)->get((db),db_ui2key(k))) ) -#define strdb_get(db,k) ( db_data2ptr((db)->get((db),db_str2key(k))) ) +#define db_get(db,k) ( DB->data2ptr((db)->get((db),(k))) ) +#define idb_get(db,k) ( DB->data2ptr((db)->get((db),DB->i2key(k))) ) +#define uidb_get(db,k) ( DB->data2ptr((db)->get((db),DB->ui2key(k))) ) +#define strdb_get(db,k) ( DB->data2ptr((db)->get((db),DB->str2key(k))) ) // Get int-type data from DBMaps of various key types -#define db_iget(db,k) ( db_data2i((db)->get((db),(k))) ) -#define idb_iget(db,k) ( db_data2i((db)->get((db),db_i2key(k))) ) -#define uidb_iget(db,k) ( db_data2i((db)->get((db),db_ui2key(k))) ) -#define strdb_iget(db,k) ( db_data2i((db)->get((db),db_str2key(k))) ) +#define db_iget(db,k) ( DB->data2i((db)->get((db),(k))) ) +#define idb_iget(db,k) ( DB->data2i((db)->get((db),DB->i2key(k))) ) +#define uidb_iget(db,k) ( DB->data2i((db)->get((db),DB->ui2key(k))) ) +#define strdb_iget(db,k) ( DB->data2i((db)->get((db),DB->str2key(k))) ) // Get uint-type data from DBMaps of various key types -#define db_uiget(db,k) ( db_data2ui((db)->get((db),(k))) ) -#define idb_uiget(db,k) ( db_data2ui((db)->get((db),db_i2key(k))) ) -#define uidb_uiget(db,k) ( db_data2ui((db)->get((db),db_ui2key(k))) ) -#define strdb_uiget(db,k) ( db_data2ui((db)->get((db),db_str2key(k))) ) +#define db_uiget(db,k) ( DB->data2ui((db)->get((db),(k))) ) +#define idb_uiget(db,k) ( DB->data2ui((db)->get((db),DB->i2key(k))) ) +#define uidb_uiget(db,k) ( DB->data2ui((db)->get((db),DB->ui2key(k))) ) +#define strdb_uiget(db,k) ( DB->data2ui((db)->get((db),DB->str2key(k))) ) // Put pointer-type data into DBMaps of various key types -#define db_put(db,k,d) ( (db)->put((db),(k),db_ptr2data(d),NULL) ) -#define idb_put(db,k,d) ( (db)->put((db),db_i2key(k),db_ptr2data(d),NULL) ) -#define uidb_put(db,k,d) ( (db)->put((db),db_ui2key(k),db_ptr2data(d),NULL) ) -#define strdb_put(db,k,d) ( (db)->put((db),db_str2key(k),db_ptr2data(d),NULL) ) +#define db_put(db,k,d) ( (db)->put((db),(k),DB->ptr2data(d),NULL) ) +#define idb_put(db,k,d) ( (db)->put((db),DB->i2key(k),DB->ptr2data(d),NULL) ) +#define uidb_put(db,k,d) ( (db)->put((db),DB->ui2key(k),DB->ptr2data(d),NULL) ) +#define strdb_put(db,k,d) ( (db)->put((db),DB->str2key(k),DB->ptr2data(d),NULL) ) // Put int-type data into DBMaps of various key types -#define db_iput(db,k,d) ( (db)->put((db),(k),db_i2data(d),NULL) ) -#define idb_iput(db,k,d) ( (db)->put((db),db_i2key(k),db_i2data(d),NULL) ) -#define uidb_iput(db,k,d) ( (db)->put((db),db_ui2key(k),db_i2data(d),NULL) ) -#define strdb_iput(db,k,d) ( (db)->put((db),db_str2key(k),db_i2data(d),NULL) ) +#define db_iput(db,k,d) ( (db)->put((db),(k),DB->i2data(d),NULL) ) +#define idb_iput(db,k,d) ( (db)->put((db),DB->i2key(k),DB->i2data(d),NULL) ) +#define uidb_iput(db,k,d) ( (db)->put((db),DB->ui2key(k),DB->i2data(d),NULL) ) +#define strdb_iput(db,k,d) ( (db)->put((db),DB->str2key(k),DB->i2data(d),NULL) ) // Put uint-type data into DBMaps of various key types -#define db_uiput(db,k,d) ( (db)->put((db),(k),db_ui2data(d),NULL) ) -#define idb_uiput(db,k,d) ( (db)->put((db),db_i2key(k),db_ui2data(d),NULL) ) -#define uidb_uiput(db,k,d) ( (db)->put((db),db_ui2key(k),db_ui2data(d),NULL) ) -#define strdb_uiput(db,k,d) ( (db)->put((db),db_str2key(k),db_ui2data(d),NULL) ) +#define db_uiput(db,k,d) ( (db)->put((db),(k),DB->ui2data(d),NULL) ) +#define idb_uiput(db,k,d) ( (db)->put((db),DB->i2key(k),DB->ui2data(d),NULL) ) +#define uidb_uiput(db,k,d) ( (db)->put((db),DB->ui2key(k),DB->ui2data(d),NULL) ) +#define strdb_uiput(db,k,d) ( (db)->put((db),DB->str2key(k),DB->ui2data(d),NULL) ) // Remove entry from DBMaps of various key types #define db_remove(db,k) ( (db)->remove((db),(k),NULL) ) -#define idb_remove(db,k) ( (db)->remove((db),db_i2key(k),NULL) ) -#define uidb_remove(db,k) ( (db)->remove((db),db_ui2key(k),NULL) ) -#define strdb_remove(db,k) ( (db)->remove((db),db_str2key(k),NULL) ) +#define idb_remove(db,k) ( (db)->remove((db),DB->i2key(k),NULL) ) +#define uidb_remove(db,k) ( (db)->remove((db),DB->ui2key(k),NULL) ) +#define strdb_remove(db,k) ( (db)->remove((db),DB->str2key(k),NULL) ) //These are discarding the possible vargs you could send to the function, so those //that require vargs must not use these defines. -#define db_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),(k),(f))) ) -#define idb_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),db_i2key(k),(f))) ) -#define uidb_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),db_ui2key(k),(f))) ) -#define strdb_ensure(db,k,f) ( db_data2ptr((db)->ensure((db),db_str2key(k),(f))) ) +#define db_ensure(db,k,f) ( DB->data2ptr((db)->ensure((db),(k),(f))) ) +#define idb_ensure(db,k,f) ( DB->data2ptr((db)->ensure((db),DB->i2key(k),(f))) ) +#define uidb_ensure(db,k,f) ( DB->data2ptr((db)->ensure((db),DB->ui2key(k),(f))) ) +#define strdb_ensure(db,k,f) ( DB->data2ptr((db)->ensure((db),DB->str2key(k),(f))) ) // Database creation and destruction macros -#define idb_alloc(opt) db_alloc(__FILE__,__LINE__,DB_INT,(opt),sizeof(int)) -#define uidb_alloc(opt) db_alloc(__FILE__,__LINE__,DB_UINT,(opt),sizeof(unsigned int)) -#define strdb_alloc(opt,maxlen) db_alloc(__FILE__,__LINE__,DB_STRING,(opt),(maxlen)) -#define stridb_alloc(opt,maxlen) db_alloc(__FILE__,__LINE__,DB_ISTRING,(opt),(maxlen)) +#define idb_alloc(opt) DB->alloc(__FILE__,__LINE__,DB_INT,(opt),sizeof(int)) +#define uidb_alloc(opt) DB->alloc(__FILE__,__LINE__,DB_UINT,(opt),sizeof(unsigned int)) +#define strdb_alloc(opt,maxlen) DB->alloc(__FILE__,__LINE__,DB_STRING,(opt),(maxlen)) +#define stridb_alloc(opt,maxlen) DB->alloc(__FILE__,__LINE__,DB_ISTRING,(opt),(maxlen)) #define db_destroy(db) ( (db)->destroy((db),NULL) ) // Other macros #define db_clear(db) ( (db)->clear(db,NULL) ) #define db_size(db) ( (db)->size(db) ) #define db_iterator(db) ( (db)->iterator(db) ) -#define dbi_first(dbi) ( db_data2ptr((dbi)->first(dbi,NULL)) ) -#define dbi_last(dbi) ( db_data2ptr((dbi)->last(dbi,NULL)) ) -#define dbi_next(dbi) ( db_data2ptr((dbi)->next(dbi,NULL)) ) -#define dbi_prev(dbi) ( db_data2ptr((dbi)->prev(dbi,NULL)) ) +#define dbi_first(dbi) ( DB->data2ptr((dbi)->first(dbi,NULL)) ) +#define dbi_last(dbi) ( DB->data2ptr((dbi)->last(dbi,NULL)) ) +#define dbi_next(dbi) ( DB->data2ptr((dbi)->next(dbi,NULL)) ) +#define dbi_prev(dbi) ( DB->data2ptr((dbi)->prev(dbi,NULL)) ) #define dbi_remove(dbi) ( (dbi)->remove(dbi,NULL) ) #define dbi_exists(dbi) ( (dbi)->exists(dbi) ) #define dbi_destroy(dbi) ( (dbi)->destroy(dbi) ) @@ -692,6 +692,7 @@ struct DBMap { * db_final - Finalizes the database system. * \*****************************************************************************/ +struct db_interface { /** * Returns the fixed options according to the database type. * Sets required options and unsets unsupported options. @@ -704,7 +705,7 @@ struct DBMap { * @see #DBOptions * @see #db_default_release(DBType,DBOptions) */ -DBOptions db_fix_options(DBType type, DBOptions options); +DBOptions (*fix_options) (DBType type, DBOptions options); /** * Returns the default comparator for the type of database. @@ -714,7 +715,7 @@ DBOptions db_fix_options(DBType type, DBOptions options); * @see #DBType * @see #DBComparator */ -DBComparator db_default_cmp(DBType type); +DBComparator (*default_cmp) (DBType type); /** * Returns the default hasher for the specified type of database. @@ -724,7 +725,7 @@ DBComparator db_default_cmp(DBType type); * @see #DBType * @see #DBHasher */ -DBHasher db_default_hash(DBType type); +DBHasher (*default_hash) (DBType type); /** * Returns the default releaser for the specified type of database with the @@ -741,7 +742,7 @@ DBHasher db_default_hash(DBType type); * @see #db_fix_options(DBType,DBOptions) * @see #db_custom_release(DBRelease) */ -DBReleaser db_default_release(DBType type, DBOptions options); +DBReleaser (*default_release) (DBType type, DBOptions options); /** * Returns the releaser that behaves as <code>which</code> specifies. @@ -752,7 +753,7 @@ DBReleaser db_default_release(DBType type, DBOptions options); * @see #DBReleaser * @see #db_default_release(DBType,DBOptions) */ -DBReleaser db_custom_release(DBRelease which); +DBReleaser (*custom_release) (DBRelease which); /** * Allocate a new database of the specified type. @@ -775,7 +776,7 @@ DBReleaser db_custom_release(DBRelease which); * @see #db_default_release(DBType,DBOptions) * @see #db_fix_options(DBType,DBOptions) */ -DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsigned short maxlen); +DBMap* (*alloc) (const char *file, int line, DBType type, DBOptions options, unsigned short maxlen); /** * Manual cast from 'int' to the union DBKey. @@ -783,7 +784,7 @@ DBMap* db_alloc(const char *file, int line, DBType type, DBOptions options, unsi * @return The key as a DBKey union * @public */ -DBKey db_i2key(int key); +DBKey (*i2key) (int key); /** * Manual cast from 'unsigned int' to the union DBKey. @@ -791,7 +792,7 @@ DBKey db_i2key(int key); * @return The key as a DBKey union * @public */ -DBKey db_ui2key(unsigned int key); +DBKey (*ui2key) (unsigned int key); /** * Manual cast from 'unsigned char *' to the union DBKey. @@ -799,7 +800,7 @@ DBKey db_ui2key(unsigned int key); * @return The key as a DBKey union * @public */ -DBKey db_str2key(const char *key); +DBKey (*str2key) (const char *key); /** * Manual cast from 'int' to the struct DBData. @@ -807,7 +808,7 @@ DBKey db_str2key(const char *key); * @return The data as a DBData struct * @public */ -DBData db_i2data(int data); +DBData (*i2data) (int data); /** * Manual cast from 'unsigned int' to the struct DBData. @@ -815,7 +816,7 @@ DBData db_i2data(int data); * @return The data as a DBData struct * @public */ -DBData db_ui2data(unsigned int data); +DBData (*ui2data) (unsigned int data); /** * Manual cast from 'void *' to the struct DBData. @@ -823,7 +824,7 @@ DBData db_ui2data(unsigned int data); * @return The data as a DBData struct * @public */ -DBData db_ptr2data(void *data); +DBData (*ptr2data) (void *data); /** * Gets int type data from struct DBData. @@ -832,7 +833,7 @@ DBData db_ptr2data(void *data); * @return Integer value of the data. * @public */ -int db_data2i(DBData *data); +int (*data2i) (DBData *data); /** * Gets unsigned int type data from struct DBData. @@ -841,7 +842,7 @@ int db_data2i(DBData *data); * @return Unsigned int value of the data. * @public */ -unsigned int db_data2ui(DBData *data); +unsigned int (*data2ui) (DBData *data); /** * Gets void* type data from struct DBData. @@ -850,14 +851,14 @@ unsigned int db_data2ui(DBData *data); * @return Void* value of the data. * @public */ -void* db_data2ptr(DBData *data); +void* (*data2ptr) (DBData *data); /** * Initialize the database system. * @public * @see #db_final(void) */ -void db_init(void); +void (*init) (void); /** * Finalize the database system. @@ -865,8 +866,12 @@ void db_init(void); * @public * @see #db_init(void) */ -void db_final(void); +void (*final) (void); +} DB_s; +struct db_interface *DB; + +void db_defaults(void); // Link DB System - From jAthena struct linkdb_node { struct linkdb_node *next; diff --git a/src/common/ers.c b/src/common/ers.c index b94b0888d..13e54b393 100644 --- a/src/common/ers.c +++ b/src/common/ers.c @@ -1,7 +1,7 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Portions Copyright (c) Athena Dev Teams /*****************************************************************************\ - * Copyright (c) Athena Dev Teams - Licensed under GNU GPL * - * For more information, see LICENCE in the main folder * - * * * <H1>Entry Reusage System</H1> * * * * There are several root entry managers, each with a different entry size. * @@ -48,8 +48,7 @@ #ifndef DISABLE_ERS -#define ERS_ROOT_SIZE 256 -#define ERS_BLOCK_ENTRIES 4096 +#define ERS_BLOCK_ENTRIES 2048 struct ers_list { @@ -278,7 +277,16 @@ ERS ers_new(uint32 size, char *name, enum ERSOptions options) void ers_report(void) { - // FIXME: Someone use this? Is it really needed? + ers_cache_t *cache; + int i = 0; + for (cache = CacheList; cache; cache = cache->Next) { + ShowMessage(CL_BOLD"[Entry manager #%u report]\n"CL_NORMAL, ++i); + ShowMessage("\tinstances : %u\n", cache->ReferenceCount); + ShowMessage("\tblock array size : %u\n", cache->ObjectSize); + ShowMessage("\tallocated blocks : %u\n", cache->Free+cache->Used); + ShowMessage("\tentries being used : %u\n", cache->Used); + ShowMessage("\tunused entries : %u\n", cache->Free); + } } void ers_force_destroy_all(void) diff --git a/src/common/grfio.c b/src/common/grfio.c index 8f430cfb9..bf66dba52 100644 --- a/src/common/grfio.c +++ b/src/common/grfio.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/des.h" @@ -250,8 +251,12 @@ int decode_zip(void* dest, unsigned long* destLen, const void* source, unsigned /// zlib compress -int encode_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) { + if( *destLen == 0 ) /* [Ind/Hercules] */ + *destLen = compressBound(sourceLen); + if( dest == NULL ) { /* [Ind/Hercules] */ + CREATE(dest, unsigned char, *destLen); + } return compress((Bytef*)dest, destLen, (const Bytef*)source, sourceLen); } @@ -393,12 +398,12 @@ void* grfio_reads(const char* fname, int* size) FILELIST* entry = filelist_find(fname); if( entry == NULL || entry->gentry <= 0 ) {// LocalFileCheck char lfname[256]; - int declen; FILE* in; grfio_localpath_create(lfname, sizeof(lfname), ( entry && entry->fnd ) ? entry->fnd : fname); in = fopen(lfname, "rb"); if( in != NULL ) { + int declen; fseek(in,0,SEEK_END); declen = ftell(in); fseek(in,0,SEEK_SET); @@ -475,14 +480,14 @@ static char* decode_filename(unsigned char* buf, int len) /// @return true if the file should undergo full mode 0 decryption, and true otherwise. static bool isFullEncrypt(const char* fname) { - static const char extensions[4][5] = { ".gnd", ".gat", ".act", ".str" }; - size_t i; - const char* ext = strrchr(fname, '.'); - if( ext != NULL ) + if( ext != NULL ) { + static const char extensions[4][5] = { ".gnd", ".gat", ".act", ".str" }; + size_t i; for( i = 0; i < ARRAYLENGTH(extensions); ++i ) if( strcmpi(ext, extensions[i]) == 0 ) return false; + } return true; } @@ -492,7 +497,7 @@ static bool isFullEncrypt(const char* fname) /// @param gentry index of the grf file name in the gentry_table static int grfio_entryread(const char* grfname, int gentry) { - long grf_size,list_size; + long grf_size; unsigned char grf_header[0x2e]; int entry,entrys,ofs,grf_version; unsigned char *grf_filelist; @@ -518,6 +523,7 @@ static int grfio_entryread(const char* grfname, int gentry) grf_version = getlong(grf_header+0x2a) >> 8; if( grf_version == 0x01 ) {// ****** Grf version 01xx ****** + long list_size; list_size = grf_size - ftell(fp); grf_filelist = (unsigned char *) aMalloc(list_size); if(fread(grf_filelist,1,list_size,fp) != list_size) { ShowError("Couldn't read all grf_filelist element of %s \n", grfname); } @@ -678,7 +684,7 @@ static bool grfio_parse_restable_row(const char* row) static void grfio_resourcecheck(void) { char restable[256]; - char *ptr, *buf; + char *buf; int size; FILE* fp; int i = 0; @@ -705,6 +711,7 @@ static void grfio_resourcecheck(void) buf = (char *)grfio_reads("data\\resnametable.txt", &size); if( buf != NULL ) { + char *ptr; buf[size] = '\0'; ptr = buf; diff --git a/src/common/malloc.c b/src/common/malloc.c index 9976a28d5..77eef2508 100644 --- a/src/common/malloc.c +++ b/src/common/malloc.c @@ -1,5 +1,6 @@ -// 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 #include "../common/malloc.h" #include "../common/core.h" @@ -129,49 +130,49 @@ void aFree_(void *p, const char *file, int line, const char *func) /* USE_MEMMGR */ /* - * ƒƒ‚ƒŠƒ}ƒl[ƒWƒƒ - * malloc , free ‚̈—‚ðŒø—¦“I‚Éo—ˆ‚邿‚¤‚É‚µ‚½‚à‚ÌB - * •¡ŽG‚Ȉ—‚ðs‚Á‚Ä‚¢‚é‚Ì‚ÅAŽáбd‚‚Ȃ邩‚à‚µ‚ê‚Ü‚¹‚ñB - * - * ƒf[ƒ^\‘¢‚È‚Çià–¾‰ºŽè‚Å‚·‚¢‚Ü‚¹‚ñ^^; j - * Eƒƒ‚ƒŠ‚ð•¡”‚ÌuƒuƒƒbƒNv‚É•ª‚¯‚ÄA‚³‚ç‚ɃuƒƒbƒN‚ð•¡”‚Ìuƒ†ƒjƒbƒgv - * ‚É•ª‚¯‚Ä‚¢‚Ü‚·Bƒ†ƒjƒbƒg‚̃TƒCƒY‚ÍA‚PƒuƒƒbƒN‚Ì—e—ʂ𕡔ŒÂ‚ɋϓ™”z•ª - * ‚µ‚½‚à‚̂ł·B‚½‚Æ‚¦‚ÎA‚Pƒ†ƒjƒbƒg32KB‚Ìê‡AƒuƒƒbƒN‚P‚‚Í32Byte‚̃† - * ƒjƒbƒg‚ªA1024ŒÂW‚Ü‚Á‚Äo—ˆ‚Ä‚¢‚½‚èA64Byte‚̃†ƒjƒbƒg‚ª 512ŒÂW‚Ü‚Á‚Ä - * o—ˆ‚Ä‚¢‚½‚肵‚Ü‚·Bipadding,unit_head ‚ðœ‚j - * - * EƒuƒƒbƒN“¯Žm‚ÍƒŠƒ“ƒNƒŠƒXƒg(block_prev,block_next) ‚ł‚Ȃª‚èA“¯‚¶ƒTƒC - * ƒY‚ðŽ‚ÂƒuƒƒbƒN“¯Žm‚àƒŠƒ“ƒNƒŠƒXƒg(hash_prev,hash_nect) ‚Å‚Â‚È - * ‚ª‚Á‚Ä‚¢‚Ü‚·B‚»‚ê‚É‚æ‚èA•s—v‚ƂȂÁ‚½ƒƒ‚ƒŠ‚ÌÄ—˜—p‚ªŒø—¦“I‚És‚¦‚Ü‚·B - */ - -/* ƒuƒƒbƒN‚̃Aƒ‰ƒCƒƒ“ƒg */ +* Memory manager +* able to handle malloc and free efficiently +* Since the complex processing, I might be slightly heavier. +* +* (I'm sorry for the poor description ^ ^;) such as data structures +* Divided into "blocks" of a plurality of memory, "unit" of a plurality of blocks further +* I have to divide. Size of the unit, a plurality of distribution equal to the capacity of one block +* That's what you have. For example, if one unit of 32KB, one block 1 Yu 32Byte +* Knit, or are able to gather 1024, gathered 512 units 64Byte +* I can be or have. (Excluding padding, the unit_head) +* +* Lead-linked list (block_prev, block_next) in each other is the same size block +* Linked list (hash_prev, hash_nect) even among such one in the block with the figure +* I like to have. Thus, reuse of memory no longer needed can be performed efficiently. +*/ + +/* Alignment of the block */ #define BLOCK_ALIGNMENT1 16 #define BLOCK_ALIGNMENT2 64 -/* ƒuƒƒbƒN‚É“ü‚éƒf[ƒ^—Ê */ +/* Amount of data entering a block */ #define BLOCK_DATA_COUNT1 128 #define BLOCK_DATA_COUNT2 608 -/* ƒuƒƒbƒN‚̑傫‚³: 16*128 + 64*576 = 40KB */ +/* The size of the block: 16*128 + 64*576 = 40KB */ #define BLOCK_DATA_SIZE1 ( BLOCK_ALIGNMENT1 * BLOCK_DATA_COUNT1 ) #define BLOCK_DATA_SIZE2 ( BLOCK_ALIGNMENT2 * BLOCK_DATA_COUNT2 ) #define BLOCK_DATA_SIZE ( BLOCK_DATA_SIZE1 + BLOCK_DATA_SIZE2 ) -/* ˆê“x‚ÉŠm•Û‚·‚éƒuƒƒbƒN‚Ì”B */ +/* The number of blocks to be allocated at a time. */ #define BLOCK_ALLOC 104 -/* ƒuƒƒbƒN */ +/* block */ struct block { - struct block* block_next; /* ŽŸ‚ÉŠm•Û‚µ‚½—̈æ */ - struct block* unfill_prev; /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */ - struct block* unfill_next; /* ŽŸ‚Ì–„‚Ü‚Á‚Ä‚¢‚È‚¢—̈æ */ - unsigned short unit_size; /* ƒ†ƒjƒbƒg‚̑傫‚³ */ - unsigned short unit_hash; /* ƒ†ƒjƒbƒg‚̃nƒbƒVƒ… */ - unsigned short unit_count; /* ƒ†ƒjƒbƒg‚̌” */ - unsigned short unit_used; /* Žg—pƒ†ƒjƒbƒg” */ - unsigned short unit_unfill; /* –¢Žg—pƒ†ƒjƒbƒg‚ÌêŠ */ - unsigned short unit_maxused; /* Žg—pƒ†ƒjƒbƒg‚ÌÅ‘å’l */ + struct block* block_next; /* Then the allocated area */ + struct block* unfill_prev; /* The previous area not filled */ + struct block* unfill_next; /* The next area not filled */ + unsigned short unit_size; /* The size of the unit */ + unsigned short unit_hash; /* The hash of the unit */ + unsigned short unit_count; /* The number of units */ + unsigned short unit_used; /* The number of used units */ + unsigned short unit_unfill; /* The number of unused units */ + unsigned short unit_maxused; /* The maximum value of units used */ char data[ BLOCK_DATA_SIZE ]; }; @@ -186,7 +187,7 @@ struct unit_head { static struct block* hash_unfill[BLOCK_DATA_COUNT1 + BLOCK_DATA_COUNT2 + 1]; static struct block* block_first, *block_last, block_head; -/* ƒƒ‚ƒŠ‚ðŽg‚¢‰ñ‚¹‚È‚¢—̈æ—p‚̃f[ƒ^ */ +/* Data for areas that do not use the memory be turned */ struct unit_head_large { size_t size; struct unit_head_large* prev; @@ -209,9 +210,9 @@ static unsigned short size2hash( size_t size ) return (unsigned short)(size + BLOCK_ALIGNMENT1 - 1) / BLOCK_ALIGNMENT1; } else if( size <= BLOCK_DATA_SIZE ){ return (unsigned short)(size - BLOCK_DATA_SIZE1 + BLOCK_ALIGNMENT2 - 1) / BLOCK_ALIGNMENT2 - + BLOCK_DATA_COUNT1; + + BLOCK_DATA_COUNT1; } else { - return 0xffff; // ƒuƒƒbƒN’·‚ð’´‚¦‚éê‡‚Í hash ‚É‚µ‚È‚¢ + return 0xffff; // If it exceeds the block length hash I do not } } @@ -234,14 +235,14 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) ShowError("_mmalloc: %d\n", size); return NULL; } - + if(size == 0) { return NULL; } memmgr_usage_bytes += size; - /* ƒuƒƒbƒN’·‚ð’´‚¦‚é—̈æ‚ÌŠm•Û‚É‚ÍAmalloc() ‚ð—p‚¢‚é */ - /* ‚»‚ÌÛAunit_head.block ‚É NULL ‚ð‘ã“ü‚µ‚Ä‹æ•Ê‚·‚é */ + /* To ensure the area that exceeds the length of the block, using malloc () to */ + /* At that time, the distinction by assigning NULL to unit_head.block */ if(hash2size(size_hash) > BLOCK_DATA_SIZE - sizeof(struct unit_head)) { struct unit_head_large* p = (struct unit_head_large*)MALLOC(sizeof(struct unit_head_large)+size,file,line,func); if(p != NULL) { @@ -266,7 +267,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) } } - /* “¯ˆêƒTƒCƒY‚̃uƒƒbƒN‚ªŠm•Û‚³‚ê‚Ä‚¢‚È‚¢ŽžAV‚½‚ÉŠm•Û‚·‚é */ + /* When a block of the same size is not ensured, to ensure a new */ if(hash_unfill[size_hash]) { block = hash_unfill[size_hash]; } else { @@ -274,7 +275,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) } if( block->unit_unfill == 0xFFFF ) { - // freeςݗ̈悪Žc‚Á‚Ä‚¢‚È‚¢ + // there are no more free space that memmgr_assert(block->unit_used < block->unit_count); memmgr_assert(block->unit_used == block->unit_maxused); head = block2unit(block, block->unit_maxused); @@ -287,7 +288,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) } if( block->unit_unfill == 0xFFFF && block->unit_maxused >= block->unit_count) { - // ƒ†ƒjƒbƒg‚ðŽg‚¢‰Ê‚½‚µ‚½‚Ì‚ÅAunfillƒŠƒXƒg‚©‚çíœ + // Since I ran out of the unit, removed from the list unfill if( block->unfill_prev == &block_head) { hash_unfill[ size_hash ] = block->unfill_next; } else { @@ -331,7 +332,7 @@ void* _mmalloc(size_t size, const char *file, int line, const char *func ) void* _mcalloc(size_t num, size_t size, const char *file, int line, const char *func ) { - void *p = _mmalloc(num * size,file,line,func); + void *p = malloclib->malloc(num * size,file,line,func); memset(p,0,num * size); return p; } @@ -340,7 +341,7 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c { size_t old_size; if(memblock == NULL) { - return _mmalloc(size,file,line,func); + return malloclib->malloc(size,file,line,func); } old_size = ((struct unit_head *)((char *)memblock - sizeof(struct unit_head) + sizeof(long)))->size; @@ -348,15 +349,15 @@ void* _mrealloc(void *memblock, size_t size, const char *file, int line, const c old_size = ((struct unit_head_large *)((char *)memblock - sizeof(struct unit_head_large) + sizeof(long)))->size; } if(old_size > size) { - // ƒTƒCƒYk¬ -> ‚»‚̂܂ܕԂ·iŽè”²‚«j + // Size reduction - return> as it is (negligence) return memblock; } else { - // ƒTƒCƒYŠg‘å - void *p = _mmalloc(size,file,line,func); + // Size Large + void *p = malloclib->malloc(size,file,line,func); if(p != NULL) { memcpy(p,memblock,old_size); } - _mfree(memblock,file,line,func); + malloclib->free(memblock,file,line,func); return p; } } @@ -367,7 +368,7 @@ char* _mstrdup(const char *p, const char *file, int line, const char *func ) return NULL; } else { size_t len = strlen(p); - char *string = (char *)_mmalloc(len + 1,file,line,func); + char *string = (char *)malloclib->malloc(len + 1,file,line,func); memcpy(string,p,len+1); return string; } @@ -382,7 +383,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) head = (struct unit_head *)((char *)ptr - sizeof(struct unit_head) + sizeof(long)); if(head->size == 0) { - /* malloc() ‚Å’¼‚ÉŠm•Û‚³‚ꂽ—̈æ */ + /* area that is directly secured by malloc () */ struct unit_head_large *head_large = (struct unit_head_large *)((char *)ptr - sizeof(struct unit_head_large) + sizeof(long)); if( *(long*)((char*)head_large + sizeof(struct unit_head_large) - sizeof(long) + head_large->size) @@ -407,7 +408,7 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) FREE(head_large,file,line,func); } } else { - /* ƒ†ƒjƒbƒg‰ð•ú */ + /* Release unit */ struct block *block = head->block; if( (char*)head - (char*)block > sizeof(struct block) ) { ShowError("Memory manager: args of aFree 0x%p is invalid pointer %s line %d\n", ptr, file, line); @@ -425,11 +426,11 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) #endif memmgr_assert( block->unit_used > 0 ); if(--block->unit_used == 0) { - /* ƒuƒƒbƒN‚̉ð•ú */ + /* Release of the block */ block_free(block); } else { if( block->unfill_prev == NULL) { - // unfill ƒŠƒXƒg‚ɒljÁ + // add to unfill list if( hash_unfill[ block->unit_hash ] ) { hash_unfill[ block->unit_hash ]->unfill_prev = block; } @@ -444,17 +445,17 @@ void _mfree(void *ptr, const char *file, int line, const char *func ) } } -/* ƒuƒƒbƒN‚ðŠm•Û‚·‚é */ +/* Allocating blocks */ static struct block* block_malloc(unsigned short hash) { int i; struct block *p; if(hash_unfill[0] != NULL) { - /* ƒuƒƒbƒN—p‚̗̈æ‚ÍŠm•ÛÏ‚Ý */ + /* Space for the block has already been secured */ p = hash_unfill[0]; hash_unfill[0] = hash_unfill[0]->unfill_next; } else { - /* ƒuƒƒbƒN—p‚̗̈æ‚ðV‚½‚ÉŠm•Û‚·‚é */ + /* Newly allocated space for the block */ p = (struct block*)MALLOC(sizeof(struct block) * (BLOCK_ALLOC), __FILE__, __LINE__, __func__ ); if(p == NULL) { ShowFatalError("Memory manager::block_alloc failed.\n"); @@ -462,17 +463,17 @@ static struct block* block_malloc(unsigned short hash) } if(block_first == NULL) { - /* ‰‰ñŠm•Û */ + /* First ensure */ block_first = p; } else { block_last->block_next = p; } block_last = &p[BLOCK_ALLOC - 1]; block_last->block_next = NULL; - /* ƒuƒƒbƒN‚ð˜AŒ‹‚³‚¹‚é */ + /* Linking the block */ for(i=0;i<BLOCK_ALLOC;i++) { if(i != 0) { - // p[0] ‚Í‚±‚ê‚©‚çŽg‚¤‚Ì‚ÅƒŠƒ“ƒN‚ɂ͉Á‚¦‚È‚¢ + // I do not add the link p [0], so we will use p[i].unfill_next = hash_unfill[0]; hash_unfill[0] = &p[i]; p[i].unfill_prev = NULL; @@ -484,7 +485,7 @@ static struct block* block_malloc(unsigned short hash) } } - // unfill ‚ɒljÁ + // Add to unfill memmgr_assert(hash_unfill[ hash ] == NULL); hash_unfill[ hash ] = p; p->unfill_prev = &block_head; @@ -530,18 +531,20 @@ static FILE *log_fp; static void memmgr_log (char *buf) { - if( !log_fp ) - { + if( !log_fp ) { time_t raw; struct tm* t; + const char* svn = get_svn_revision(); + const char* git = get_git_hash(); log_fp = fopen(memmer_logfile,"at"); if (!log_fp) log_fp = stdout; time(&raw); t = localtime(&raw); - fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (Revision %s).\n", - (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, get_svn_revision()); + fprintf(log_fp, "\nMemory manager: Memory leaks found at %d/%02d/%02d %02dh%02dm%02ds (rev %s).\n", + (t->tm_year+1900), (t->tm_mon+1), t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec, + git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown"); } fprintf(log_fp, "%s", buf); return; @@ -618,7 +621,7 @@ static void memmgr_final (void) memmgr_log (buf); #endif /* LOG_MEMMGR */ // get block pointer and free it [celest] - _mfree(ptr, ALC_MARK); + malloclib->free(ptr, ALC_MARK); } } } @@ -660,9 +663,9 @@ static void memmgr_init (void) /*====================================== - * Initialise - *-------------------------------------- - */ +* Initialise +*-------------------------------------- +*/ /// Tests the memory for errors and memory leaks. @@ -716,3 +719,28 @@ void malloc_init (void) memmgr_init (); #endif } + +void malloc_defaults() +{ + malloclib = &malloclib_s; + malloclib->init = malloc_init; + malloclib->final = malloc_final; + malloclib->memory_check = malloc_memory_check; + malloclib->usage = malloc_usage; + malloclib->verify_ptr = malloc_verify_ptr; + +// Athena's built-in Memory Manager +#ifdef USE_MEMMGR + malloclib->malloc = _mmalloc; + malloclib->calloc = _mcalloc; + malloclib->realloc = _mrealloc; + malloclib->strdup = _mstrdup; + malloclib->free = _mfree; +#else + malloclib->malloc = aMalloc_; + malloclib->calloc = aCalloc_; + malloclib->realloc = aRealloc_; + malloclib->strdup = aStrdup_; + malloclib->free = aFree_; +#endif +} diff --git a/src/common/malloc.h b/src/common/malloc.h index 6b4e8e5c4..2e745481f 100644 --- a/src/common/malloc.h +++ b/src/common/malloc.h @@ -22,9 +22,6 @@ ////////////////////////////////////////////////////////////////////// -// Athena's built-in Memory Manager -#ifdef USE_MEMMGR - // Enable memory manager logging by default #define LOG_MEMMGR @@ -33,46 +30,24 @@ #undef LOG_MEMMGR #endif -# define aMalloc(n) _mmalloc(n,ALC_MARK) -# define aCalloc(m,n) _mcalloc(m,n,ALC_MARK) -# define aRealloc(p,n) _mrealloc(p,n,ALC_MARK) -# define aStrdup(p) _mstrdup(p,ALC_MARK) -# define aFree(p) _mfree(p,ALC_MARK) - - void* _mmalloc (size_t size, const char *file, int line, const char *func); - void* _mcalloc (size_t num, size_t size, const char *file, int line, const char *func); - void* _mrealloc (void *p, size_t size, const char *file, int line, const char *func); - char* _mstrdup (const char *p, const char *file, int line, const char *func); - void _mfree (void *p, const char *file, int line, const char *func); - -#else - -# define aMalloc(n) aMalloc_((n),ALC_MARK) -# define aCalloc(m,n) aCalloc_((m),(n),ALC_MARK) -# define aRealloc(p,n) aRealloc_(p,n,ALC_MARK) -# define aStrdup(p) aStrdup_(p,ALC_MARK) -# define aFree(p) aFree_(p,ALC_MARK) - - void* aMalloc_ (size_t size, const char *file, int line, const char *func); - void* aCalloc_ (size_t num, size_t size, const char *file, int line, const char *func); - void* aRealloc_ (void *p, size_t size, const char *file, int line, const char *func); - char* aStrdup_ (const char *p, const char *file, int line, const char *func); - void aFree_ (void *p, const char *file, int line, const char *func); - -#endif +# define aMalloc(n) malloclib->malloc (n,ALC_MARK) +# define aCalloc(m,n) malloclib->calloc (m,n,ALC_MARK) +# define aRealloc(p,n) malloclib->realloc (p,n,ALC_MARK) +# define aStrdup(p) malloclib->strdup (p,ALC_MARK) +# define aFree(p) malloclib->free (p,ALC_MARK) /////////////// Buffer Creation ///////////////// // Full credit for this goes to Shinomori [Ajarn] #ifdef __GNUC__ // GCC has variable length arrays - #define CREATE_BUFFER(name, type, size) type name[size] - #define DELETE_BUFFER(name) +#define CREATE_BUFFER(name, type, size) type name[size] +#define DELETE_BUFFER(name) #else // others don't, so we emulate them - #define CREATE_BUFFER(name, type, size) type *name = (type *) aCalloc (size, sizeof(type)) - #define DELETE_BUFFER(name) aFree(name) +#define CREATE_BUFFER(name, type, size) type *name = (type *) aCalloc (size, sizeof(type)) +#define DELETE_BUFFER(name) aFree(name) #endif @@ -83,10 +58,27 @@ //////////////////////////////////////////////// -void malloc_memory_check(void); -bool malloc_verify_ptr(void* ptr); -size_t malloc_usage (void); -void malloc_init (void); -void malloc_final (void); - +//void malloc_memory_check(void); +//bool malloc_verify_ptr(void* ptr); +//size_t malloc_usage (void); +//void malloc_init (void); +//void malloc_final (void); + +void malloc_defaults(void); + +struct malloc_interface { + void* (*malloc )(size_t size, const char *file, int line, const char *func); + void* (*calloc )(size_t num, size_t size, const char *file, int line, const char *func); + void* (*realloc )(void *p, size_t size, const char *file, int line, const char *func); + char* (*strdup )(const char *p, const char *file, int line, const char *func); + void (*free ) (void *p, const char *file, int line, const char *func); + + void (*memory_check)(void); + bool (*verify_ptr)(void* ptr); + size_t (*usage) (void); + void (*init) (void); + void (*final) (void); +} malloclib_s; + +struct malloc_interface *malloclib; #endif /* _MALLOC_H_ */ diff --git a/src/common/mapindex.c b/src/common/mapindex.c index d46047833..4649e299d 100644 --- a/src/common/mapindex.c +++ b/src/common/mapindex.c @@ -1,10 +1,12 @@ -// 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 #include "../common/mmo.h" #include "../common/showmsg.h" #include "../common/malloc.h" #include "../common/strlib.h" +#include "../common/db.h" #include "mapindex.h" #include <string.h> @@ -20,11 +22,9 @@ int max_index = 0; char mapindex_cfgfile[80] = "db/map_index.txt"; #define mapindex_exists(id) (indexes[id].name[0] != '\0') - /// Retrieves the map name from 'string' (removing .gat extension if present). /// Result gets placed either into 'buf' or in a static local buffer. -const char* mapindex_getmapname(const char* string, char* output) -{ +const char* mapindex_getmapname(const char* string, char* output) { static char buf[MAP_NAME_LENGTH]; char* dest = (output != NULL) ? output : buf; @@ -37,7 +37,7 @@ const char* mapindex_getmapname(const char* string, char* output) len -= 4; // strip .gat extension len = min(len, MAP_NAME_LENGTH-1); - strncpy(dest, string, len+1); + safestrncpy(dest, string, len+1); memset(&dest[len], '\0', MAP_NAME_LENGTH-len); return dest; @@ -45,8 +45,7 @@ const char* mapindex_getmapname(const char* string, char* output) /// Retrieves the map name from 'string' (adding .gat extension if not already present). /// Result gets placed either into 'buf' or in a static local buffer. -const char* mapindex_getmapname_ext(const char* string, char* output) -{ +const char* mapindex_getmapname_ext(const char* string, char* output) { static char buf[MAP_NAME_LENGTH_EXT]; char* dest = (output != NULL) ? output : buf; @@ -61,7 +60,7 @@ const char* mapindex_getmapname_ext(const char* string, char* output) ShowWarning("(mapindex_normalize_name) Map name '%*s' is too long!\n", 2*MAP_NAME_LENGTH, buf); len--; } - strncpy(dest, buf, len+1); + safestrncpy(dest, buf, len+1); if (len < 4 || stricmp(&dest[len-4], ".gat") != 0) { strcpy(&dest[len], ".gat"); @@ -75,13 +74,11 @@ const char* mapindex_getmapname_ext(const char* string, char* output) /// Adds a map to the specified index /// Returns 1 if successful, 0 oherwise -int mapindex_addmap(int index, const char* name) -{ +int mapindex_addmap(int index, const char* name) { char map_name[MAP_NAME_LENGTH]; if (index == -1){ - for (index = 1; index < max_index; index++) - { + for (index = 1; index < max_index; index++) { //if (strcmp(indexes[index].name,"#CLEARED#")==0) if (indexes[index].name[0] == '\0') break; @@ -105,63 +102,58 @@ int mapindex_addmap(int index, const char* name) return 0; } - if (mapindex_exists(index)) + if (mapindex_exists(index)) { ShowWarning("(mapindex_add) Overriding index %d: map \"%s\" -> \"%s\"\n", index, indexes[index].name, map_name); + strdb_remove(mapindex_db, indexes[index].name); + } safestrncpy(indexes[index].name, map_name, MAP_NAME_LENGTH); + strdb_iput(mapindex_db, map_name, index); if (max_index <= index) max_index = index+1; return index; } -unsigned short mapindex_name2id(const char* name) -{ - //TODO: Perhaps use a db to speed this up? [Skotlex] +unsigned short mapindex_name2id(const char* name) { int i; - char map_name[MAP_NAME_LENGTH]; + mapindex_getmapname(name, map_name); - for (i = 1; i < max_index; i++) - { - if (strcmpi(indexes[i].name,map_name)==0) - return i; - } + if( (i = strdb_iget(mapindex_db, map_name)) ) + return i; + ShowDebug("mapindex_name2id: Map \"%s\" not found in index list!\n", map_name); return 0; } -const char* mapindex_id2name(unsigned short id) -{ +const char* mapindex_id2name_sub(unsigned short id,const char *file, int line, const char *func) { if (id > MAX_MAPINDEX || !mapindex_exists(id)) { - ShowDebug("mapindex_id2name: Requested name for non-existant map index [%d] in cache.\n", id); + ShowDebug("mapindex_id2name: Requested name for non-existant map index [%d] in cache. %s:%s:%d\n", id,file,func,line); return indexes[0].name; // dummy empty string so that the callee doesn't crash } return indexes[id].name; } -void mapindex_init(void) -{ +void mapindex_init(void) { FILE *fp; char line[1024]; int last_index = -1; int index; - char map_name[1024]; + char map_name[12]; - memset (&indexes, 0, sizeof (indexes)); - fp=fopen(mapindex_cfgfile,"r"); - if(fp==NULL){ + if( ( fp = fopen(mapindex_cfgfile,"r") ) == NULL ){ ShowFatalError("Unable to read mapindex config file %s!\n", mapindex_cfgfile); exit(EXIT_FAILURE); //Server can't really run without this file. } - while(fgets(line, sizeof(line), fp)) - { + memset (&indexes, 0, sizeof (indexes)); + mapindex_db = strdb_alloc(DB_RELEASE_KEY, MAP_NAME_LENGTH); + while(fgets(line, sizeof(line), fp)) { if(line[0] == '/' && line[1] == '/') continue; - switch (sscanf(line, "%1023s\t%d", map_name, &index)) - { + switch (sscanf(line, "%12s\t%d", map_name, &index)) { case 1: //Map with no ID given, auto-assign index = last_index+1; case 2: //Map with ID given @@ -173,6 +165,10 @@ void mapindex_init(void) last_index = index; } fclose(fp); + + if( !strdb_iget(mapindex_db, MAP_DEFAULT) ) { + ShowError("mapindex_init: MAP_DEFAULT '%s' not found in cache! update mapindex.h MAP_DEFAULT var!!!\n",MAP_DEFAULT); + } } int mapindex_removemap(int index){ @@ -180,6 +176,6 @@ int mapindex_removemap(int index){ return 0; } -void mapindex_final(void) -{ +void mapindex_final(void) { + db_destroy(mapindex_db); } diff --git a/src/common/mapindex.h b/src/common/mapindex.h index 75cb254c0..d35d9899c 100644 --- a/src/common/mapindex.h +++ b/src/common/mapindex.h @@ -1,9 +1,18 @@ -// 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 _MAPINDEX_H_ #define _MAPINDEX_H_ +#include "../common/db.h" + +/* when a map index search fails, return results from what map? default:prontera */ +#define MAP_DEFAULT "prontera" +#define MAP_DEFAULT_X 150 +#define MAP_DEFAULT_Y 150 +DBMap *mapindex_db; + //File in charge of assigning a numberic ID to each map in existance for space saving when passing map info between servers. extern char mapindex_cfgfile[80]; @@ -50,7 +59,8 @@ extern char mapindex_cfgfile[80]; const char* mapindex_getmapname(const char* string, char* output); const char* mapindex_getmapname_ext(const char* string, char* output); unsigned short mapindex_name2id(const char*); -const char* mapindex_id2name(unsigned short); +#define mapindex_id2name(n) mapindex_id2name_sub(n,__FILE__, __LINE__, __func__) +const char* mapindex_id2name_sub(unsigned short,const char *file, int line, const char *func); void mapindex_init(void); void mapindex_final(void); diff --git a/src/common/mmo.h b/src/common/mmo.h index 493f87691..d45dea212 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -1,10 +1,12 @@ -// 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 _MMO_H_ #define _MMO_H_ #include "cbasetypes.h" +#include "../common/db.h" #include <time.h> // server->client protocol version @@ -46,10 +48,12 @@ // 20120307 - 2012-03-07aRagexeRE+ - 0x970 #ifndef PACKETVER - #define PACKETVER 20120410 - //#define PACKETVER 20111116 + #define PACKETVER 20120418 #endif +/// comment following line if your client is NOT ragexeRE (required because of conflicting packets in ragexe vs ragexeRE) +#define PACKETVER_RE + //Remove/Comment this line to disable sc_data saving. [Skotlex] #define ENABLE_SC_SAVING //Remove/Comment this line to disable server-side hot-key saving support [Skotlex] @@ -79,7 +83,8 @@ #define MAX_ZENY 1000000000 #define MAX_FAME 1000000000 #define MAX_CART 100 -#define MAX_SKILL 3100 +#define MAX_SKILL 1477 +#define MAX_SKILL_ID 10015 //[Ind/Hercules] max used skill id #define GLOBAL_REG_NUM 256 // max permanent character variables per char #define ACCOUNT_REG_NUM 64 // max permanent local account variables per account #define ACCOUNT_REG2_NUM 16 // max permanent global account variables per account @@ -98,8 +103,9 @@ #define MAX_GUILDSKILL 15 // increased max guild skills because of new skills [Sara-chan] #define MAX_GUILDLEVEL 50 #define MAX_GUARDIANS 8 //Local max per castle. [Skotlex] -#define MAX_QUEST_DB 2200 //Max quests that the server will load +#define MAX_QUEST_DB 2400 //Max quests that the server will load #define MAX_QUEST_OBJECTIVES 3 //Max quest objectives for a quest +#define MAX_START_ITEMS 32 //Max number of items allowed to be given to a char whenever it's created. [mkbu95] // for produce #define MIN_ATTRIBUTE 0 @@ -152,7 +158,7 @@ //Mercenary System #define MC_SKILLBASE 8201 #define MAX_MERCSKILL 40 -#define MAX_MERCENARY_CLASS 44 +#define MAX_MERCENARY_CLASS 61 //Elemental System #define MAX_ELEMENTALSKILL 42 @@ -219,6 +225,12 @@ enum e_skill_flag //... }; +enum e_mmo_charstatus_opt { + OPT_NONE = 0x0, + OPT_SHOW_EQUIP = 0x1, + OPT_ALLOW_PARTY = 0x2, +}; + struct s_skill { unsigned short id; unsigned char lv; @@ -378,8 +390,9 @@ struct mmo_charstatus { #ifdef HOTKEY_SAVING struct hotkey hotkeys[MAX_HOTKEYS]; #endif - bool show_equip; - short rename; + bool show_equip, allow_party; + unsigned short rename; + unsigned short slotchange; time_t delete_date; }; @@ -510,8 +523,10 @@ struct guild { struct guild_alliance alliance[MAX_GUILDALLIANCE]; struct guild_expulsion expulsion[MAX_GUILDEXPULSION]; struct guild_skill skill[MAX_GUILDSKILL]; - + + /* TODO: still used for something?|: */ unsigned short save_flag; // for TXT saving + void *channel; }; struct guild_castle { diff --git a/src/common/netbuffer.c b/src/common/netbuffer.c index 57742d612..60a299aa9 100644 --- a/src/common/netbuffer.c +++ b/src/common/netbuffer.c @@ -52,10 +52,10 @@ void netbuffer_init(){ // Set localsection name according to running serverype. switch(SERVER_TYPE){ - case ATHENA_SERVER_LOGIN: strcpy(localsection, "login-netbuffer"); break; - case ATHENA_SERVER_CHAR: strcpy(localsection, "char-netbuffer"); break; - case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break; - case ATHENA_SERVER_MAP: strcpy(localsection, "map-netbuffer"); break; + case SERVER_TYPE_LOGIN: strcpy(localsection, "login-netbuffer"); break; + case SERVER_TYPE_CHAR: strcpy(localsection, "char-netbuffer"); break; + //case ATHENA_SERVER_INTER: strcpy(localsection, "inter-netbuffer"); break; + case SERVER_TYPE_MAP: strcpy(localsection, "map-netbuffer"); break; default: strcpy(localsection, "unsupported_type"); break; } diff --git a/src/common/raconf.c b/src/common/raconf.c index 2703560ff..f7d1284b7 100644 --- a/src/common/raconf.c +++ b/src/common/raconf.c @@ -41,12 +41,11 @@ struct conf_value{ static struct conf_value *makeValue(const char *key, char *val, size_t val_len){ struct conf_value *v; - char *p; - size_t sz; +/* size_t sz; sz = sizeof(struct conf_value); if(val_len >= sizeof(v->strval)) - sz += (val_len - sizeof(v->strval) + 1); + sz += (val_len - sizeof(v->strval) + 1);*/ v = (struct conf_value*)aCalloc(1, sizeof(struct conf_value)); if(v == NULL){ @@ -106,6 +105,7 @@ static struct conf_value *makeValue(const char *key, char *val, size_t val_len){ }else if( *val >='0' && *val <= '9'){ // begins with normal digit, so assume its dec. // is it float? bool is_float = false; + char *p; for(p = val; *p != '\0'; p++){ if(*p == '.'){ diff --git a/src/common/showmsg.c b/src/common/showmsg.c index 609ae3c50..2a3146d35 100644 --- a/src/common/showmsg.c +++ b/src/common/showmsg.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/strlib.h" // StringBuf @@ -77,9 +78,9 @@ int console_msg_log = 0;//[Ind] msg error logging } \ else \ {/* dynamic buffer */ \ - buf.d_ = StringBuf_Malloc(); \ - buf.l_ = StringBuf_Vprintf(buf.d_, fmt, args); \ - buf.v_ = StringBuf_Value(buf.d_); \ + buf.d_ = StrBuf->Malloc(); \ + buf.l_ = StrBuf->Vprintf(buf.d_, fmt, args); \ + buf.v_ = StrBuf->Value(buf.d_); \ ShowDebug("showmsg: dynamic buffer used, increase the static buffer size to %d or more.\n", buf.l_+1);\ } \ //define BUFVPRINTF @@ -90,7 +91,7 @@ int console_msg_log = 0;//[Ind] msg error logging #define FREEBUF(buf) \ if( buf.d_ ) \ { \ - StringBuf_Free(buf.d_); \ + StrBuf->Free(buf.d_); \ buf.d_ = NULL; \ } \ buf.v_ = NULL; \ @@ -687,22 +688,12 @@ int _vShowMessage(enum msg_type flag, const char *string, va_list ap) ShowError("Empty string passed to _vShowMessage().\n"); return 1; } - /** - * For the buildbot, these result in a EXIT_FAILURE from core.c when done reading the params. - **/ -#if defined(BUILDBOT) - if( flag == MSG_WARNING || - flag == MSG_ERROR || - flag == MSG_SQL ) { - buildbotflag = 1; - } -#endif if( ( flag == MSG_WARNING && console_msg_log&1 ) || ( ( flag == MSG_ERROR || flag == MSG_SQL ) && console_msg_log&2 ) || ( flag == MSG_DEBUG && console_msg_log&4 ) ) {//[Ind] FILE *log = NULL; - if( (log = fopen(SERVER_TYPE == ATHENA_SERVER_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+")) ) { + if( (log = fopen(SERVER_TYPE == SERVER_TYPE_MAP ? "./log/map-msg_log.log" : "./log/unknown.log","a+")) ) { char timestring[255]; time_t curtime; time(&curtime); @@ -864,13 +855,13 @@ void ShowConfigWarning(config_setting_t *config, const char *string, ...) { StringBuf buf; va_list ap; - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, string); - StringBuf_Printf(&buf, " (%s:%d)\n", config_setting_source_file(config), config_setting_source_line(config)); + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, string); + StrBuf->Printf(&buf, " (%s:%d)\n", config_setting_source_file(config), config_setting_source_line(config)); va_start(ap, string); - _vShowMessage(MSG_WARNING, StringBuf_Value(&buf), ap); + _vShowMessage(MSG_WARNING, StrBuf->Value(&buf), ap); va_end(ap); - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); } void ShowDebug(const char *string, ...) { va_list ap; diff --git a/src/common/showmsg.h b/src/common/showmsg.h index 0d6cb5c9f..a88985770 100644 --- a/src/common/showmsg.h +++ b/src/common/showmsg.h @@ -1,11 +1,13 @@ -// 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 _SHOWMSG_H_ #define _SHOWMSG_H_ -#include "libconfig.h" - +#ifndef _HPMi_H_ + #include "libconfig.h" +#endif // for help with the console colors look here: // http://www.edoceo.com/liberum/?doc=printf-with-color // some code explanation (used here): @@ -85,15 +87,17 @@ enum msg_type { }; extern void ClearScreen(void); -extern void ShowMessage(const char *, ...); -extern void ShowStatus(const char *, ...); -extern void ShowSQL(const char *, ...); -extern void ShowInfo(const char *, ...); -extern void ShowNotice(const char *, ...); -extern void ShowWarning(const char *, ...); -extern void ShowDebug(const char *, ...); -extern void ShowError(const char *, ...); -extern void ShowFatalError(const char *, ...); -extern void ShowConfigWarning(config_setting_t *config, const char *string, ...); +#ifndef _HPMi_H_ + extern void ShowMessage(const char *, ...); + extern void ShowStatus(const char *, ...); + extern void ShowSQL(const char *, ...); + extern void ShowInfo(const char *, ...); + extern void ShowNotice(const char *, ...); + extern void ShowWarning(const char *, ...); + extern void ShowDebug(const char *, ...); + extern void ShowError(const char *, ...); + extern void ShowFatalError(const char *, ...); + extern void ShowConfigWarning(config_setting_t *config, const char *string, ...); +#endif #endif /* _SHOWMSG_H_ */ diff --git a/src/common/socket.c b/src/common/socket.c index 6977d4257..5126d231b 100644 --- a/src/common/socket.c +++ b/src/common/socket.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/mmo.h" @@ -812,7 +813,7 @@ int do_sockets(int next) continue; // after parse, check client's RFIFO size to know if there is an invalid packet (too big and not parsed) - if (session[i]->rdata_size == RFIFO_SIZE && session[i]->max_rdata == RFIFO_SIZE) { + if (session[i]->rdata_size == session[i]->max_rdata) { set_eof(i); continue; } @@ -1017,14 +1018,14 @@ int access_ipmask(const char* str, AccessControl* acc) { uint32 ip; uint32 mask; - unsigned int a[4]; - unsigned int m[4]; - int n; if( strcmp(str,"all") == 0 ) { ip = 0; mask = 0; } else { + unsigned int a[4]; + unsigned int m[4]; + int n; if( ((n=sscanf(str,"%u.%u.%u.%u/%u.%u.%u.%u",a,a+1,a+2,a+3,m,m+1,m+2,m+3)) != 8 && // not an ip + standard mask (n=sscanf(str,"%u.%u.%u.%u/%u",a,a+1,a+2,a+3,m)) != 5 && // not an ip + bit mask (n=sscanf(str,"%u.%u.%u.%u",a,a+1,a+2,a+3)) != 4 ) || // not an ip @@ -1337,7 +1338,6 @@ void socket_init(void) ShowInfo("Server supports up to '"CL_WHITE"%u"CL_RESET"' concurrent connections.\n", rlim_cur); } - bool session_isValid(int fd) { return ( fd > 0 && fd < FD_SETSIZE && session[fd] != NULL ); @@ -1377,6 +1377,72 @@ uint16 ntows(uint16 netshort) return ((netshort & 0xFF) << 8) | ((netshort & 0xFF00) >> 8); } +/* [Ind/Hercules] - socket_datasync */ +void socket_datasync(int fd, bool send) { + struct { + unsigned int length;/* short is not enough for some */ + } data_list[] = { + { sizeof(struct mmo_charstatus) }, + { sizeof(struct quest) }, + { sizeof(struct item) }, + { sizeof(struct point) }, + { sizeof(struct s_skill) }, + { sizeof(struct global_reg) }, + { sizeof(struct accreg) }, + { sizeof(struct status_change_data) }, + { sizeof(struct storage_data) }, + { sizeof(struct guild_storage) }, + { sizeof(struct s_pet) }, + { sizeof(struct s_mercenary) }, + { sizeof(struct s_homunculus) }, + { sizeof(struct s_elemental) }, + { sizeof(struct s_friend) }, + { sizeof(struct mail_message) }, + { sizeof(struct mail_data) }, + { sizeof(struct registry) }, + { sizeof(struct party_member) }, + { sizeof(struct party) }, + { sizeof(struct guild_member) }, + { sizeof(struct guild_position) }, + { sizeof(struct guild_alliance) }, + { sizeof(struct guild_expulsion) }, + { sizeof(struct guild_skill) }, + { sizeof(struct guild) }, + { sizeof(struct guild_castle) }, + { sizeof(struct fame_list) }, + }; + unsigned short i; + unsigned int alen = ARRAYLENGTH(data_list); + if( send ) { + unsigned short p_len = ( alen * 4 ) + 4; + WFIFOHEAD(fd, p_len); + + WFIFOW(fd, 0) = 0x2b0a; + WFIFOW(fd, 2) = p_len; + + for( i = 0; i < alen; i++ ) { + WFIFOL(fd, 4 + ( i * 4 ) ) = data_list[i].length; + } + + WFIFOSET(fd, p_len); + } else { + for( i = 0; i < alen; i++ ) { + if( RFIFOL(fd, 4 + (i * 4) ) != data_list[i].length ) { + /* force the other to go wrong too so both are taken down */ + WFIFOHEAD(fd, 8); + WFIFOW(fd, 0) = 0x2b0a; + WFIFOW(fd, 2) = 8; + WFIFOL(fd, 4) = 0; + WFIFOSET(fd, 8); + flush_fifo(fd); + /* shut down */ + ShowFatalError("Servers are out of sync! recompile from scratch (%d)\n",i); + exit(EXIT_FAILURE); + } + } + } +} + #ifdef SEND_SHORTLIST // Add a fd to the shortlist so that it'll be recognized as a fd that needs // sending or eof handling. diff --git a/src/common/socket.h b/src/common/socket.h index 7c0e02f5d..4879cb109 100644 --- a/src/common/socket.h +++ b/src/common/socket.h @@ -145,6 +145,9 @@ extern int naddr_; // # of ip addresses void set_eof(int fd); +/* [Ind/Hercules] - socket_datasync */ +void socket_datasync(int fd, bool send); + /// Use a shortlist of sockets instead of iterating all sessions for sockets /// that have data to send or need eof handling. /// Adapted to use a static array instead of a linked list. diff --git a/src/common/sql.c b/src/common/sql.c index 800aa89b0..391211183 100644 --- a/src/common/sql.c +++ b/src/common/sql.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -15,11 +16,13 @@ #include <string.h>// strlen/strnlen/memcpy/memset #include <stdlib.h>// strtoul +void hercules_mysql_error_handler(unsigned int ecode); +int mysql_reconnect_type; +unsigned int mysql_reconnect_count; /// Sql handle -struct Sql -{ +struct Sql { StringBuf buf; MYSQL handle; MYSQL_RES* result; @@ -32,8 +35,7 @@ struct Sql // Column length receiver. // Takes care of the possible size missmatch between uint32 and unsigned long. -struct s_column_length -{ +struct s_column_length { uint32* out_length; unsigned long length; }; @@ -42,8 +44,7 @@ typedef struct s_column_length s_column_length; /// Sql statement -struct SqlStmt -{ +struct SqlStmt { StringBuf buf; MYSQL_STMT* stmt; MYSQL_BIND* params; @@ -70,11 +71,11 @@ Sql* Sql_Malloc(void) CREATE(self, Sql, 1); mysql_init(&self->handle); - StringBuf_Init(&self->buf); + StrBuf->Init(&self->buf); self->lengths = NULL; self->result = NULL; self->keepalive = INVALID_TIMER; - + self->handle.reconnect = 1; return self; } @@ -88,7 +89,7 @@ int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* hos if( self == NULL ) return SQL_ERROR; - StringBuf_Clear(&self->buf); + StrBuf->Clear(&self->buf); if( !mysql_real_connect(&self->handle, host, user, passwd, db, (unsigned int)port, NULL/*unix_socket*/, 0/*clientflag*/) ) { ShowSQL("%s\n", mysql_error(&self->handle)); @@ -110,18 +111,16 @@ int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* hos /// Retrieves the timeout of the connection. int Sql_GetTimeout(Sql* self, uint32* out_timeout) { - if( self && out_timeout && SQL_SUCCESS == Sql_Query(self, "SHOW VARIABLES LIKE 'wait_timeout'") ) - { + if( self && out_timeout && SQL_SUCCESS == SQL->Query(self, "SHOW VARIABLES LIKE 'wait_timeout'") ) { char* data; size_t len; - if( SQL_SUCCESS == Sql_NextRow(self) && - SQL_SUCCESS == Sql_GetData(self, 1, &data, &len) ) - { + if( SQL_SUCCESS == SQL->NextRow(self) && + SQL_SUCCESS == SQL->GetData(self, 1, &data, &len) ) { *out_timeout = (uint32)strtoul(data, NULL, 10); - Sql_FreeResult(self); + SQL->FreeResult(self); return SQL_SUCCESS; } - Sql_FreeResult(self); + SQL->FreeResult(self); } return SQL_ERROR; } @@ -135,12 +134,11 @@ int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_l size_t len; size_t off = 0; - if( self == NULL || SQL_ERROR == Sql_Query(self, "EXPLAIN `%s`", table) ) + if( self == NULL || SQL_ERROR == SQL->Query(self, "EXPLAIN `%s`", table) ) return SQL_ERROR; out_buf[off] = '\0'; - while( SQL_SUCCESS == Sql_NextRow(self) && SQL_SUCCESS == Sql_GetData(self, 0, &data, &len) ) - { + while( SQL_SUCCESS == SQL->NextRow(self) && SQL_SUCCESS == SQL->GetData(self, 0, &data, &len) ) { len = strnlen(data, len); if( off + len + 2 > buf_len ) { @@ -153,7 +151,7 @@ int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_l out_buf[off++] = sep; } out_buf[off] = '\0'; - Sql_FreeResult(self); + SQL->FreeResult(self); return SQL_SUCCESS; } @@ -246,7 +244,7 @@ int Sql_Query(Sql* self, const char* query, ...) va_list args; va_start(args, query); - res = Sql_QueryV(self, query, args); + res = SQL->QueryV(self, query, args); va_end(args); return res; @@ -260,18 +258,20 @@ int Sql_QueryV(Sql* self, const char* query, va_list args) if( self == NULL ) return SQL_ERROR; - Sql_FreeResult(self); - StringBuf_Clear(&self->buf); - StringBuf_Vprintf(&self->buf, query, args); - if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + SQL->FreeResult(self); + StrBuf->Clear(&self->buf); + StrBuf->Vprintf(&self->buf, query, args); + if( mysql_real_query(&self->handle, StrBuf->Value(&self->buf), (unsigned long)StrBuf->Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } self->result = mysql_store_result(&self->handle); if( mysql_errno(&self->handle) != 0 ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } return SQL_SUCCESS; @@ -285,18 +285,20 @@ int Sql_QueryStr(Sql* self, const char* query) if( self == NULL ) return SQL_ERROR; - Sql_FreeResult(self); - StringBuf_Clear(&self->buf); - StringBuf_AppendStr(&self->buf, query); - if( mysql_real_query(&self->handle, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + SQL->FreeResult(self); + StrBuf->Clear(&self->buf); + StrBuf->AppendStr(&self->buf, query); + if( mysql_real_query(&self->handle, StrBuf->Value(&self->buf), (unsigned long)StrBuf->Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } self->result = mysql_store_result(&self->handle); if( mysql_errno(&self->handle) != 0 ) { ShowSQL("DB error - %s\n", mysql_error(&self->handle)); + hercules_mysql_error_handler(mysql_errno(&self->handle)); return SQL_ERROR; } return SQL_SUCCESS; @@ -336,13 +338,10 @@ uint64 Sql_NumRows(Sql* self) /// Fetches the next row. -int Sql_NextRow(Sql* self) -{ - if( self && self->result ) - { +int Sql_NextRow(Sql* self) { + if( self && self->result ) { self->row = mysql_fetch_row(self->result); - if( self->row ) - { + if( self->row ) { self->lengths = mysql_fetch_lengths(self->result); return SQL_SUCCESS; } @@ -358,15 +357,11 @@ int Sql_NextRow(Sql* self) /// Gets the data of a column. int Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len) { - if( self && self->row ) - { - if( col < Sql_NumColumns(self) ) - { + if( self && self->row ) { + if( col < SQL->NumColumns(self) ) { if( out_buf ) *out_buf = self->row[col]; if( out_len ) *out_len = (size_t)self->lengths[col]; - } - else - {// out of range - ignore + } else {// out of range - ignore if( out_buf ) *out_buf = NULL; if( out_len ) *out_len = 0; } @@ -378,10 +373,8 @@ int Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len) /// Frees the result of the query. -void Sql_FreeResult(Sql* self) -{ - if( self && self->result ) - { +void Sql_FreeResult(Sql* self) { + if( self && self->result ) { mysql_free_result(self->result); self->result = NULL; self->row = NULL; @@ -396,8 +389,8 @@ void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug { if( self == NULL ) ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line); - else if( StringBuf_Length(&self->buf) > 0 ) - ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf)); + else if( StrBuf->Length(&self->buf) > 0 ) + ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StrBuf->Value(&self->buf)); else ShowDebug("at %s:%lu\n", debug_file, debug_line); } @@ -409,8 +402,8 @@ void Sql_Free(Sql* self) { if( self ) { - Sql_FreeResult(self); - StringBuf_Destroy(&self->buf); + SQL->FreeResult(self); + StrBuf->Destroy(&self->buf); if( self->keepalive != INVALID_TIMER ) delete_timer(self->keepalive, Sql_P_KeepaliveTimer); aFree(self); } @@ -582,8 +575,7 @@ static void SqlStmt_P_ShowDebugTruncatedColumn(SqlStmt* self, size_t i) /// Allocates and initializes a new SqlStmt handle. -SqlStmt* SqlStmt_Malloc(Sql* sql) -{ +SqlStmt* SqlStmt_Malloc(Sql* sql) { SqlStmt* self; MYSQL_STMT* stmt; @@ -591,13 +583,12 @@ SqlStmt* SqlStmt_Malloc(Sql* sql) return NULL; stmt = mysql_stmt_init(&sql->handle); - if( stmt == NULL ) - { + if( stmt == NULL ) { ShowSQL("DB error - %s\n", mysql_error(&sql->handle)); return NULL; } CREATE(self, SqlStmt, 1); - StringBuf_Init(&self->buf); + StrBuf->Init(&self->buf); self->stmt = stmt; self->params = NULL; self->columns = NULL; @@ -634,11 +625,12 @@ int SqlStmt_PrepareV(SqlStmt* self, const char* query, va_list args) return SQL_ERROR; SqlStmt_FreeResult(self); - StringBuf_Clear(&self->buf); - StringBuf_Vprintf(&self->buf, query, args); - if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + StrBuf->Clear(&self->buf); + StrBuf->Vprintf(&self->buf, query, args); + if( mysql_stmt_prepare(self->stmt, StrBuf->Value(&self->buf), (unsigned long)StrBuf->Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } self->bind_params = false; @@ -655,11 +647,12 @@ int SqlStmt_PrepareStr(SqlStmt* self, const char* query) return SQL_ERROR; SqlStmt_FreeResult(self); - StringBuf_Clear(&self->buf); - StringBuf_AppendStr(&self->buf, query); - if( mysql_stmt_prepare(self->stmt, StringBuf_Value(&self->buf), (unsigned long)StringBuf_Length(&self->buf)) ) + StrBuf->Clear(&self->buf); + StrBuf->AppendStr(&self->buf, query); + if( mysql_stmt_prepare(self->stmt, StrBuf->Value(&self->buf), (unsigned long)StrBuf->Length(&self->buf)) ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } self->bind_params = false; @@ -721,12 +714,14 @@ int SqlStmt_Execute(SqlStmt* self) mysql_stmt_execute(self->stmt) ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } self->bind_columns = false; if( mysql_stmt_store_result(self->stmt) )// store all the data { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } @@ -868,6 +863,7 @@ int SqlStmt_NextRow(SqlStmt* self) if( err ) { ShowSQL("DB error - %s\n", mysql_stmt_error(self->stmt)); + hercules_mysql_error_handler(mysql_stmt_errno(self->stmt)); return SQL_ERROR; } @@ -920,8 +916,8 @@ void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned lo { if( self == NULL ) ShowDebug("at %s:%lu - self is NULL\n", debug_file, debug_line); - else if( StringBuf_Length(&self->buf) > 0 ) - ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StringBuf_Value(&self->buf)); + else if( StrBuf->Length(&self->buf) > 0 ) + ShowDebug("at %s:%lu - %s\n", debug_file, debug_line, StrBuf->Value(&self->buf)); else ShowDebug("at %s:%lu\n", debug_file, debug_line); } @@ -934,7 +930,7 @@ void SqlStmt_Free(SqlStmt* self) if( self ) { SqlStmt_FreeResult(self); - StringBuf_Destroy(&self->buf); + StrBuf->Destroy(&self->buf); mysql_stmt_close(self->stmt); if( self->params ) aFree(self->params); @@ -946,3 +942,136 @@ void SqlStmt_Free(SqlStmt* self) aFree(self); } } +/* receives mysql error codes during runtime (not on first-time-connects) */ +void hercules_mysql_error_handler(unsigned int ecode) { + static unsigned int retry = 1; + switch( ecode ) { + case 2003:/* Can't connect to MySQL (this error only happens here when failing to reconnect) */ + if( mysql_reconnect_type == 1 ) { + if( ++retry > mysql_reconnect_count ) { + ShowFatalError("MySQL has been unreachable for too long, %d reconnects were attempted. Shutting Down\n", retry); + exit(EXIT_FAILURE); + } + } + break; + } +} +void Sql_inter_server_read(const char* cfgName, bool first) { + int i; + char line[1024], w1[1024], w2[1024]; + FILE* fp; + + fp = fopen(cfgName, "r"); + if(fp == NULL) { + if( first ) { + ShowFatalError("File not found: %s\n", cfgName); + exit(EXIT_FAILURE); + } else + ShowError("File not found: %s\n", cfgName); + return; + } + + while(fgets(line, sizeof(line), fp)) { + i = sscanf(line, "%[^:]: %[^\r\n]", w1, w2); + if(i != 2) + continue; + + if(!strcmpi(w1,"mysql_reconnect_type")) { + mysql_reconnect_type = atoi(w2); + switch( mysql_reconnect_type ) { + case 1: + case 2: + break; + default: + ShowError("%s::mysql_reconnect_type is set to %d which is not valid, defaulting to 1...\n", cfgName, mysql_reconnect_type); + mysql_reconnect_type = 1; + break; + } + } else if(!strcmpi(w1,"mysql_reconnect_count")) { + mysql_reconnect_count = atoi(w2); + if( mysql_reconnect_count < 1 ) + mysql_reconnect_count = 1; + } else if(!strcmpi(w1,"import")) + Sql_inter_server_read(w2,false); + } + fclose(fp); + + return; +} + +void Sql_HerculesUpdateCheck(Sql* self) { + char line[22];// "yyyy-mm-dd--hh-mm" (17) + ".sql" (4) + 1 + FILE* ifp;/* index fp */ + unsigned int performed = 0; + + if( !( ifp = fopen("sql-files/upgrades/index.txt", "r") ) ) { + ShowError("SQL upgrade index was not found!\n"); + return; + } + + while(fgets(line, sizeof(line), ifp)) { + char path[41];// "sql-files/upgrades/" (19) + "yyyy-mm-dd--hh-mm" (17) + ".sql" (4) + 1 + char timestamp[11];// "1360186680" (10) + 1 + FILE* ufp;/* upgrade fp */ + + if( line[0] == '\n' || ( line[0] == '/' && line[1] == '/' ) )/* skip \n and "//" comments */ + continue; + + sprintf(path,"sql-files/upgrades/%s",line); + + if( !( ufp = fopen(path, "r") ) ) { + ShowError("SQL upgrade file %s was not found!\n",path); + continue; + } + + if( fgetc(ufp) != '#' ) + continue; + + fseek (ufp,1,SEEK_SET);/* woo. skip the # */ + + if( fgets(timestamp,sizeof(timestamp),ufp) ) { + unsigned int timestampui = atol(timestamp); + if( SQL_ERROR == SQL->Query(self, "SELECT 1 FROM `sql_updates` WHERE `timestamp` = '%u' LIMIT 1", timestampui) ) + Sql_ShowDebug(self); + if( Sql_NumRows(self) != 1 ) { + ShowSQL("'"CL_WHITE"%s"CL_RESET"' wasn't applied to the database\n",path); + performed++; + } + } + + fclose(ufp); + } + + fclose(ifp); + + if( performed ) { + ShowSQL("If you did apply these updates or would like to be skip, insert a new entry in your sql_updates table with the timestamp of each file\n"); + } +} + +void Sql_Init(void) { + Sql_inter_server_read("conf/inter-server.conf",true); +} +void sql_defaults(void) { + SQL = &sql_s; + + SQL->Connect = Sql_Connect; + SQL->GetTimeout = Sql_GetTimeout; + SQL->GetColumnNames = Sql_GetColumnNames; + SQL->SetEncoding = Sql_SetEncoding; + SQL->Ping = Sql_Ping; + SQL->EscapeString = Sql_EscapeString; + SQL->EscapeStringLen = Sql_EscapeStringLen; + SQL->Query = Sql_Query; + SQL->QueryV = Sql_QueryV; + SQL->QueryStr = Sql_QueryStr; + SQL->LastInsertId = Sql_LastInsertId; + SQL->NumColumns = Sql_NumColumns; + SQL->NumRows = Sql_NumRows; + SQL->NextRow = Sql_NextRow; + SQL->GetData = Sql_GetData; + SQL->FreeResult = Sql_FreeResult; + SQL->ShowDebug_ = Sql_ShowDebug_; + SQL->Free = Sql_Free; + SQL->Malloc = Sql_Malloc; +} diff --git a/src/common/sql.h b/src/common/sql.h index 898e2c778..d5a0eda2c 100644 --- a/src/common/sql.h +++ b/src/common/sql.h @@ -1,5 +1,6 @@ -// 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 _COMMON_SQL_H_ #define _COMMON_SQL_H_ @@ -21,8 +22,7 @@ /// Data type identifier. /// String, enum and blob data types need the buffer length specified. -enum SqlDataType -{ +enum SqlDataType { SQLDT_NULL, // fixed size SQLDT_INT8, @@ -63,149 +63,96 @@ typedef enum SqlDataType SqlDataType; typedef struct Sql Sql; typedef struct SqlStmt SqlStmt; - -/// Allocates and initializes a new Sql handle. -struct Sql* Sql_Malloc(void); - - - -/// Establishes a connection. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_Connect(Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db); - - - - -/// Retrieves the timeout of the connection. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_GetTimeout(Sql* self, uint32* out_timeout); - - - - -/// Retrieves the name of the columns of a table into out_buf, with the separator after each name. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_GetColumnNames(Sql* self, const char* table, char* out_buf, size_t buf_len, char sep); - - - - -/// Changes the encoding of the connection. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_SetEncoding(Sql* self, const char* encoding); - - - -/// Pings the connection. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_Ping(Sql* self); - - - -/// Escapes a string. -/// The output buffer must be at least strlen(from)*2+1 in size. -/// -/// @return The size of the escaped string -size_t Sql_EscapeString(Sql* self, char* out_to, const char* from); - - - -/// Escapes a string. -/// The output buffer must be at least from_len*2+1 in size. -/// -/// @return The size of the escaped string -size_t Sql_EscapeStringLen(Sql* self, char* out_to, const char* from, size_t from_len); - - - -/// Executes a query. -/// Any previous result is freed. -/// The query is constructed as if it was sprintf. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_Query(Sql* self, const char* query, ...); - - - -/// Executes a query. -/// Any previous result is freed. -/// The query is constructed as if it was svprintf. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_QueryV(Sql* self, const char* query, va_list args); - - - -/// Executes a query. -/// Any previous result is freed. -/// The query is used directly. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_QueryStr(Sql* self, const char* query); - - - -/// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query. -/// -/// @return Value of the auto-increment column -uint64 Sql_LastInsertId(Sql* self); - - - -/// Returns the number of columns in each row of the result. -/// -/// @return Number of columns -uint32 Sql_NumColumns(Sql* self); - - - -/// Returns the number of rows in the result. -/// -/// @return Number of rows -uint64 Sql_NumRows(Sql* self); - - - -/// Fetches the next row. -/// The data of the previous row is no longer valid. -/// -/// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA -int Sql_NextRow(Sql* self); - - - -/// Gets the data of a column. -/// The data remains valid until the next row is fetched or the result is freed. -/// -/// @return SQL_SUCCESS or SQL_ERROR -int Sql_GetData(Sql* self, size_t col, char** out_buf, size_t* out_len); - - - -/// Frees the result of the query. -void Sql_FreeResult(Sql* self); - - +struct sql_interface { + /// Establishes a connection. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*Connect) (Sql* self, const char* user, const char* passwd, const char* host, uint16 port, const char* db); + /// Retrieves the timeout of the connection. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*GetTimeout) (Sql* self, uint32* out_timeout); + /// Retrieves the name of the columns of a table into out_buf, with the separator after each name. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*GetColumnNames) (Sql* self, const char* table, char* out_buf, size_t buf_len, char sep); + /// Changes the encoding of the connection. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*SetEncoding) (Sql* self, const char* encoding); + /// Pings the connection. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*Ping) (Sql* self); + /// Escapes a string. + /// The output buffer must be at least strlen(from)*2+1 in size. + /// + /// @return The size of the escaped string + size_t (*EscapeString) (Sql* self, char* out_to, const char* from); + /// Escapes a string. + /// The output buffer must be at least from_len*2+1 in size. + /// + /// @return The size of the escaped string + size_t (*EscapeStringLen) (Sql* self, char* out_to, const char* from, size_t from_len); + /// Executes a query. + /// Any previous result is freed. + /// The query is constructed as if it was sprintf. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*Query) (Sql* self, const char* query, ...); + /// Executes a query. + /// Any previous result is freed. + /// The query is constructed as if it was svprintf. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*QueryV) (Sql* self, const char* query, va_list args); + /// Executes a query. + /// Any previous result is freed. + /// The query is used directly. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*QueryStr) (Sql* self, const char* query); + /// Returns the number of the AUTO_INCREMENT column of the last INSERT/UPDATE query. + /// + /// @return Value of the auto-increment column + uint64 (*LastInsertId) (Sql* self); + /// Returns the number of columns in each row of the result. + /// + /// @return Number of columns + uint32 (*NumColumns) (Sql* self); + /// Returns the number of rows in the result. + /// + /// @return Number of rows + uint64 (*NumRows) (Sql* self); + /// Fetches the next row. + /// The data of the previous row is no longer valid. + /// + /// @return SQL_SUCCESS, SQL_ERROR or SQL_NO_DATA + int (*NextRow) (Sql* self); + /// Gets the data of a column. + /// The data remains valid until the next row is fetched or the result is freed. + /// + /// @return SQL_SUCCESS or SQL_ERROR + int (*GetData) (Sql* self, size_t col, char** out_buf, size_t* out_len); + /// Frees the result of the query. + void (*FreeResult) (Sql* self); + /// Shows debug information (last query). + void (*ShowDebug_) (Sql* self, const char* debug_file, const unsigned long debug_line); + /// Frees a Sql handle returned by Sql_Malloc. + void (*Free) (Sql* self); + /// Allocates and initializes a new Sql handle. + struct Sql *(*Malloc) (void); +} sql_s; + +struct sql_interface *SQL; + +void sql_defaults(void); #if defined(SQL_REMOVE_SHOWDEBUG) -#define Sql_ShowDebug(self) (void)0 + #define Sql_ShowDebug(self) (void)0 #else -#define Sql_ShowDebug(self) Sql_ShowDebug_(self, __FILE__, __LINE__) + #define Sql_ShowDebug(self) SQL->ShowDebug_(self, __FILE__, __LINE__) #endif -/// Shows debug information (last query). -void Sql_ShowDebug_(Sql* self, const char* debug_file, const unsigned long debug_line); - - - -/// Frees a Sql handle returned by Sql_Malloc. -void Sql_Free(Sql* self); - - /////////////////////////////////////////////////////////////////////////////// // Prepared Statements @@ -220,8 +167,6 @@ void Sql_Free(Sql* self); // 1) SELECT col FROM table WHERE id=? // 2) INSERT INTO table(col1,col2) VALUES(?,?) - - /// Allocates and initializes a new SqlStmt handle. /// It uses the connection of the parent Sql handle. /// Queries in Sql and SqlStmt are independent and don't affect each other. @@ -238,8 +183,6 @@ struct SqlStmt* SqlStmt_Malloc(Sql* sql); /// @return SQL_SUCCESS or SQL_ERROR int SqlStmt_Prepare(SqlStmt* self, const char* query, ...); - - /// Prepares the statement. /// Any previous result is freed and all parameter bindings are removed. /// The query is constructed as if it was svprintf. @@ -324,12 +267,12 @@ int SqlStmt_NextRow(SqlStmt* self); /// Frees the result of the statement execution. void SqlStmt_FreeResult(SqlStmt* self); - +void Sql_HerculesUpdateCheck(Sql* self); #if defined(SQL_REMOVE_SHOWDEBUG) -#define SqlStmt_ShowDebug(self) (void)0 + #define SqlStmt_ShowDebug(self) (void)0 #else -#define SqlStmt_ShowDebug(self) SqlStmt_ShowDebug_(self, __FILE__, __LINE__) + #define SqlStmt_ShowDebug(self) SqlStmt_ShowDebug_(self, __FILE__, __LINE__) #endif /// Shows debug information (with statement). void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned long debug_line); @@ -339,6 +282,7 @@ void SqlStmt_ShowDebug_(SqlStmt* self, const char* debug_file, const unsigned lo /// Frees a SqlStmt returned by SqlStmt_Malloc. void SqlStmt_Free(SqlStmt* self); +void Sql_Init(void); #endif /* _COMMON_SQL_H_ */ diff --git a/src/common/strlib.c b/src/common/strlib.c index dfacbf136..686b2e47d 100644 --- a/src/common/strlib.c +++ b/src/common/strlib.c @@ -1,9 +1,11 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/malloc.h" #include "../common/showmsg.h" +#define STRLIB_C #include "strlib.h" #include <stdio.h> @@ -14,8 +16,7 @@ #define J_MAX_MALLOC_SIZE 65535 // escapes a string in-place (' -> \' , \ -> \\ , % -> _) -char* jstrescape (char* pt) -{ +char* jstrescape (char* pt) { //copy from here char *ptr; int i = 0, j = 0; @@ -220,8 +221,7 @@ const char* stristr(const char* haystack, const char* needle) } #ifdef __WIN32 -char* _strtok_r(char *s1, const char *s2, char **lasts) -{ +char* _strtok_r(char *s1, const char *s2, char **lasts) { char *ret; if (s1 == NULL) @@ -618,8 +618,7 @@ int sv_parse_next(struct s_svstate* sv) /// @param npos Size of the pos array /// @param opt Options that determine the parsing behaviour /// @return Number of fields found in the string or -1 if an error occured -int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) -{ +int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt) { struct s_svstate sv; int count; @@ -637,8 +636,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i // parse count = 0; if( npos > 0 ) out_pos[0] = startoff; - while( !sv.done ) - { + while( !sv.done ) { ++count; if( sv_parse_next(&sv) <= 0 ) return -1;// error @@ -668,8 +666,7 @@ int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, i /// @param nfields Size of the field array /// @param opt Options that determine the parsing behaviour /// @return Number of fields found in the string or -1 if an error occured -int sv_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt) -{ +int sv_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt) { int pos[1024]; int i; int done; @@ -681,30 +678,21 @@ int sv_split(char* str, int len, int startoff, char delim, char** out_fields, in // next line end = str + pos[1]; - if( end[0] == '\0' ) - { + if( end[0] == '\0' ) { *out_fields = end; - } - else if( (opt&SV_TERMINATE_LF) && end[0] == '\n' ) - { + } else if( (opt&SV_TERMINATE_LF) && end[0] == '\n' ) { if( !(opt&SV_KEEP_TERMINATOR) ) end[0] = '\0'; *out_fields = end + 1; - } - else if( (opt&SV_TERMINATE_CRLF) && end[0] == '\r' && end[1] == '\n' ) - { + } else if( (opt&SV_TERMINATE_CRLF) && end[0] == '\r' && end[1] == '\n' ) { if( !(opt&SV_KEEP_TERMINATOR) ) end[0] = end[1] = '\0'; *out_fields = end + 2; - } - else if( (opt&SV_TERMINATE_CR) && end[0] == '\r' ) - { + } else if( (opt&SV_TERMINATE_CR) && end[0] == '\r' ) { if( !(opt&SV_KEEP_TERMINATOR) ) end[0] = '\0'; *out_fields = end + 1; - } - else - { + } else { ShowError("sv_split: unknown line delimiter 0x02%x.\n", (unsigned char)end[0]); return -1;// error } @@ -714,10 +702,8 @@ int sv_split(char* str, int len, int startoff, char delim, char** out_fields, in // fields i = 2; done = 0; - while( done < ret && nfields > 0 ) - { - if( i < ARRAYLENGTH(pos) ) - {// split field + while( done < ret && nfields > 0 ) { + if( i < ARRAYLENGTH(pos) ) { // split field *out_fields = str + pos[i]; end = str + pos[i+1]; *end = '\0'; @@ -726,9 +712,7 @@ int sv_split(char* str, int len, int startoff, char delim, char** out_fields, in ++done; ++out_fields; --nfields; - } - else - {// get more fields + } else { // get more fields sv_parse(str, len, pos[i-1] + 1, delim, pos, ARRAYLENGTH(pos), opt); i = 2; } @@ -748,65 +732,59 @@ int sv_split(char* str, int len, int startoff, char delim, char** out_fields, in /// @param len Length of the source string /// @param escapes Extra characters to be escaped /// @return Length of the escaped string -size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* escapes) -{ +size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* escapes) { size_t i; size_t j; if( out_dest == NULL ) return 0;// nothing to do - if( src == NULL ) - {// nothing to escape + if( src == NULL ) { // nothing to escape *out_dest = 0; return 0; } if( escapes == NULL ) escapes = ""; - for( i = 0, j = 0; i < len; ++i ) - { - switch( src[i] ) - { - case '\0':// octal 0 - out_dest[j++] = '\\'; - out_dest[j++] = '0'; - out_dest[j++] = '0'; - out_dest[j++] = '0'; - break; - case '\r':// carriage return - out_dest[j++] = '\\'; - out_dest[j++] = 'r'; - break; - case '\n':// line feed - out_dest[j++] = '\\'; - out_dest[j++] = 'n'; - break; - case '\\':// escape character - out_dest[j++] = '\\'; - out_dest[j++] = '\\'; - break; - default: - if( strchr(escapes,src[i]) ) - {// escape + for( i = 0, j = 0; i < len; ++i ) { + switch( src[i] ) { + case '\0':// octal 0 out_dest[j++] = '\\'; - switch( src[i] ) - { - case '\a': out_dest[j++] = 'a'; break; - case '\b': out_dest[j++] = 'b'; break; - case '\t': out_dest[j++] = 't'; break; - case '\v': out_dest[j++] = 'v'; break; - case '\f': out_dest[j++] = 'f'; break; - case '\?': out_dest[j++] = '?'; break; - default:// to octal - out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0700)>>6)); - out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0070)>>3)); - out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0007) )); - break; + out_dest[j++] = '0'; + out_dest[j++] = '0'; + out_dest[j++] = '0'; + break; + case '\r':// carriage return + out_dest[j++] = '\\'; + out_dest[j++] = 'r'; + break; + case '\n':// line feed + out_dest[j++] = '\\'; + out_dest[j++] = 'n'; + break; + case '\\':// escape character + out_dest[j++] = '\\'; + out_dest[j++] = '\\'; + break; + default: + if( strchr(escapes,src[i]) ) {// escape + out_dest[j++] = '\\'; + switch( src[i] ) { + case '\a': out_dest[j++] = 'a'; break; + case '\b': out_dest[j++] = 'b'; break; + case '\t': out_dest[j++] = 't'; break; + case '\v': out_dest[j++] = 'v'; break; + case '\f': out_dest[j++] = 'f'; break; + case '\?': out_dest[j++] = '?'; break; + default:// to octal + out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0700)>>6)); + out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0070)>>3)); + out_dest[j++] = '0'+((char)(((unsigned char)src[i]&0007) )); + break; + } } - } - else - out_dest[j++] = src[i]; - break; + else + out_dest[j++] = src[i]; + break; } } out_dest[j] = 0; @@ -821,8 +799,7 @@ size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* esca /// @param src Source string /// @param len Length of the source string /// @return Length of the escaped string -size_t sv_unescape_c(char* out_dest, const char* src, size_t len) -{ +size_t sv_unescape_c(char* out_dest, const char* src, size_t len) { static unsigned char low2hex[256] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x0? 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,// 0x1? @@ -844,71 +821,58 @@ size_t sv_unescape_c(char* out_dest, const char* src, size_t len) size_t i; size_t j; - for( i = 0, j = 0; i < len; ) - { - if( src[i] == '\\' ) - { + for( i = 0, j = 0; i < len; ) { + if( src[i] == '\\' ) { ++i;// '\\' if( i >= len ) ShowWarning("sv_unescape_c: empty escape sequence\n"); - else if( src[i] == 'x' ) - {// hex escape sequence + else if( src[i] == 'x' ) {// hex escape sequence unsigned char c = 0; unsigned char inrange = 1; ++i;// 'x' - if( i >= len || !ISXDIGIT(src[i]) ) - { + if( i >= len || !ISXDIGIT(src[i]) ) { ShowWarning("sv_unescape_c: \\x with no following hex digits\n"); continue; } - do{ - if( c > 0x0F && inrange ) - { + do { + if( c > 0x0F && inrange ) { ShowWarning("sv_unescape_c: hex escape sequence out of range\n"); inrange = 0; } c = (c<<4)|low2hex[(unsigned char)src[i]];// hex digit ++i; - }while( i < len && ISXDIGIT(src[i]) ); + } while( i < len && ISXDIGIT(src[i]) ); out_dest[j++] = (char)c; - } - else if( src[i] == '0' || src[i] == '1' || src[i] == '2' || src[i] == '3' ) - {// octal escape sequence (255=0377) + } else if( src[i] == '0' || src[i] == '1' || src[i] == '2' || src[i] == '3' ) {// octal escape sequence (255=0377) unsigned char c = src[i]-'0'; ++i;// '0', '1', '2' or '3' - if( i < len && src[i] >= '0' && src[i] <= '7' ) - { + if( i < len && src[i] >= '0' && src[i] <= '7' ) { c = (c<<3)|(src[i]-'0'); ++i;// octal digit } - if( i < len && src[i] >= '0' && src[i] <= '7' ) - { + if( i < len && src[i] >= '0' && src[i] <= '7' ) { c = (c<<3)|(src[i]-'0'); ++i;// octal digit } out_dest[j++] = (char)c; - } - else - {// other escape sequence + } else { // other escape sequence if( strchr(SV_ESCAPE_C_SUPPORTED, src[i]) == NULL ) ShowWarning("sv_unescape_c: unknown escape sequence \\%c\n", src[i]); - switch( src[i] ) - { - case 'a': out_dest[j++] = '\a'; break; - case 'b': out_dest[j++] = '\b'; break; - case 't': out_dest[j++] = '\t'; break; - case 'n': out_dest[j++] = '\n'; break; - case 'v': out_dest[j++] = '\v'; break; - case 'f': out_dest[j++] = '\f'; break; - case 'r': out_dest[j++] = '\r'; break; - case '?': out_dest[j++] = '\?'; break; - default: out_dest[j++] = src[i]; break; + switch( src[i] ) { + case 'a': out_dest[j++] = '\a'; break; + case 'b': out_dest[j++] = '\b'; break; + case 't': out_dest[j++] = '\t'; break; + case 'n': out_dest[j++] = '\n'; break; + case 'v': out_dest[j++] = '\v'; break; + case 'f': out_dest[j++] = '\f'; break; + case 'r': out_dest[j++] = '\r'; break; + case '?': out_dest[j++] = '\?'; break; + default: out_dest[j++] = src[i]; break; } ++i;// escaped character } - } - else + } else out_dest[j++] = src[i++];// normal character } out_dest[j] = 0; @@ -916,31 +880,28 @@ size_t sv_unescape_c(char* out_dest, const char* src, size_t len) } /// Skips a C escape sequence (starting with '\\'). -const char* skip_escaped_c(const char* p) -{ - if( p && *p == '\\' ) - { +const char* skip_escaped_c(const char* p) { + if( p && *p == '\\' ) { ++p; - switch( *p ) - { - case 'x':// hexadecimal - ++p; - while( ISXDIGIT(*p) ) - ++p; - break; - case '0': - case '1': - case '2': - case '3':// octal - ++p; - if( *p >= '0' && *p <= '7' ) + switch( *p ) { + case 'x':// hexadecimal ++p; - if( *p >= '0' && *p <= '7' ) - ++p; - break; - default: - if( *p && strchr(SV_ESCAPE_C_SUPPORTED, *p) ) + while( ISXDIGIT(*p) ) + ++p; + break; + case '0': + case '1': + case '2': + case '3':// octal ++p; + if( *p >= '0' && *p <= '7' ) + ++p; + if( *p >= '0' && *p <= '7' ) + ++p; + break; + default: + if( *p && strchr(SV_ESCAPE_C_SUPPORTED, *p) ) + ++p; } } return p; @@ -958,8 +919,7 @@ const char* skip_escaped_c(const char* p) /// @param maxcols Maximum number of columns of a valid row /// @param parseproc User-supplied row processing function /// @return true on success, false if file could not be opened -bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current)) -{ +bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current)) { FILE* fp; int lines = 0; int entries = 0; @@ -971,9 +931,7 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc snprintf(path, sizeof(path), "%s/%s", directory, filename); // open file - fp = fopen(path, "r"); - if( fp == NULL ) - { + if( (fp = fopen(path, "r")) == NULL ) { ShowError("sv_readdb: can't read %s\n", path); return false; } @@ -983,12 +941,10 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc fields = (char**)aMalloc(fields_length*sizeof(char*)); // process rows one by one - while( fgets(line, sizeof(line), fp) ) - { + while( fgets(line, sizeof(line), fp) ) { lines++; - if( ( match = strstr(line, "//") ) != NULL ) - {// strip comments + if( ( match = strstr(line, "//") ) != NULL ) {// strip comments match[0] = 0; } @@ -998,25 +954,21 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc columns = sv_split(line, strlen(line), 0, delim, fields, fields_length, (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF)); - if( columns < mincols ) - { + if( columns < mincols ) { ShowError("sv_readdb: Insufficient columns in line %d of \"%s\" (found %d, need at least %d).\n", lines, path, columns, mincols); continue; // not enough columns } - if( columns > maxcols ) - { + if( columns > maxcols ) { ShowError("sv_readdb: Too many columns in line %d of \"%s\" (found %d, maximum is %d).\n", lines, path, columns, maxcols ); continue; // too many columns } - if( entries == maxrows ) - { + if( entries == maxrows ) { ShowError("sv_readdb: Reached the maximum allowed number of entries (%d) when parsing file \"%s\".\n", maxrows, path); break; } // parse this row - if( !parseproc(fields+1, columns, entries) ) - { + if( !parseproc(fields+1, columns, entries) ) { ShowError("sv_readdb: Could not process contents of line %d of \"%s\".\n", lines, path); continue; // invalid row contents } @@ -1039,41 +991,36 @@ bool sv_readdb(const char* directory, const char* filename, char delim, int minc // @author MouseJstr (original) /// Allocates a StringBuf -StringBuf* StringBuf_Malloc() -{ +StringBuf* StringBuf_Malloc(void) { StringBuf* self; CREATE(self, StringBuf, 1); - StringBuf_Init(self); + StrBuf->Init(self); return self; } /// Initializes a previously allocated StringBuf -void StringBuf_Init(StringBuf* self) -{ +void StringBuf_Init(StringBuf* self) { self->max_ = 1024; self->ptr_ = self->buf_ = (char*)aMalloc(self->max_ + 1); } /// Appends the result of printf to the StringBuf -int StringBuf_Printf(StringBuf* self, const char* fmt, ...) -{ +int StringBuf_Printf(StringBuf* self, const char* fmt, ...) { int len; va_list ap; va_start(ap, fmt); - len = StringBuf_Vprintf(self, fmt, ap); + len = StrBuf->Vprintf(self, fmt, ap); va_end(ap); return len; } /// Appends the result of vprintf to the StringBuf -int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list ap) -{ +int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list ap) { int n, size, off; - for(;;) - { + for(;;) { va_list apcopy; /* Try to print in the allocated space. */ size = self->max_ - (self->ptr_ - self->buf_); @@ -1081,8 +1028,7 @@ int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list ap) n = vsnprintf(self->ptr_, size, fmt, apcopy); va_end(apcopy); /* If that worked, return the length. */ - if( n > -1 && n < size ) - { + if( n > -1 && n < size ) { self->ptr_ += n; return (int)(self->ptr_ - self->buf_); } @@ -1095,13 +1041,11 @@ int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list ap) } /// Appends the contents of another StringBuf to the StringBuf -int StringBuf_Append(StringBuf* self, const StringBuf* sbuf) -{ +int StringBuf_Append(StringBuf* self, const StringBuf* sbuf) { int available = self->max_ - (self->ptr_ - self->buf_); int needed = (int)(sbuf->ptr_ - sbuf->buf_); - if( needed >= available ) - { + if( needed >= available ) { int off = (int)(self->ptr_ - self->buf_); self->max_ += needed; self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1); @@ -1114,13 +1058,12 @@ int StringBuf_Append(StringBuf* self, const StringBuf* sbuf) } // Appends str to the StringBuf -int StringBuf_AppendStr(StringBuf* self, const char* str) -{ +int StringBuf_AppendStr(StringBuf* self, const char* str) { int available = self->max_ - (self->ptr_ - self->buf_); int needed = (int)strlen(str); - if( needed >= available ) - {// not enough space, expand the buffer (minimum expansion = 1024) + if( needed >= available ) { + // not enough space, expand the buffer (minimum expansion = 1024) int off = (int)(self->ptr_ - self->buf_); self->max_ += max(needed, 1024); self->buf_ = (char*)aRealloc(self->buf_, self->max_ + 1); @@ -1133,35 +1076,78 @@ int StringBuf_AppendStr(StringBuf* self, const char* str) } // Returns the length of the data in the Stringbuf -int StringBuf_Length(StringBuf* self) -{ +int StringBuf_Length(StringBuf* self) { return (int)(self->ptr_ - self->buf_); } /// Returns the data in the StringBuf -char* StringBuf_Value(StringBuf* self) -{ +char* StringBuf_Value(StringBuf* self) { *self->ptr_ = '\0'; return self->buf_; } /// Clears the contents of the StringBuf -void StringBuf_Clear(StringBuf* self) -{ +void StringBuf_Clear(StringBuf* self) { self->ptr_ = self->buf_; } /// Destroys the StringBuf -void StringBuf_Destroy(StringBuf* self) -{ +void StringBuf_Destroy(StringBuf* self) { aFree(self->buf_); self->ptr_ = self->buf_ = 0; self->max_ = 0; } // Frees a StringBuf returned by StringBuf_Malloc -void StringBuf_Free(StringBuf* self) -{ - StringBuf_Destroy(self); +void StringBuf_Free(StringBuf* self) { + StrBuf->Destroy(self); aFree(self); } +void strlib_defaults(void) { + /* connect */ + strlib = &strlib_s; + StrBuf = &stringbuf_s; + sv = &sv_s; + /* link~u! */ + strlib->jstrescape = jstrescape; + strlib->jmemescapecpy = jmemescapecpy; + strlib->remove_control_chars = remove_control_chars; + strlib->trim = trim; + strlib->normalize_name = normalize_name; + strlib->stristr = stristr; + +#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN) + strlib->strnlen = strnlen; +#endif + +#if defined(WIN32) && defined(_MSC_VER) && _MSC_VER <= 1200 + strlib->strtoull = strtoull; +#endif + strlib->e_mail_check = e_mail_check; + strlib->config_switch = config_switch; + strlib->safestrncpy = safestrncpy; + strlib->safestrnlen = safestrnlen; + strlib->safesnprintf = safesnprintf; + strlib->strline = strline; + strlib->bin2hex = bin2hex; + + StrBuf->Malloc = StringBuf_Malloc; + StrBuf->Init = StringBuf_Init; + StrBuf->Printf = StringBuf_Printf; + StrBuf->Vprintf = StringBuf_Vprintf; + StrBuf->Append = StringBuf_Append; + StrBuf->AppendStr = StringBuf_AppendStr; + StrBuf->Length = StringBuf_Length; + StrBuf->Value = StringBuf_Value; + StrBuf->Clear = StringBuf_Clear; + StrBuf->Destroy = StringBuf_Destroy; + StrBuf->Free = StringBuf_Free; + + sv->parse_next = sv_parse_next; + sv->parse = sv_parse; + sv->split = sv_split; + sv->escape_c = sv_escape_c; + sv->unescape_c = sv_unescape_c; + sv->skip_escaped_c = skip_escaped_c; + sv->readdb = sv_readdb; +} diff --git a/src/common/strlib.h b/src/common/strlib.h index bbc2c6105..4a073c3bc 100644 --- a/src/common/strlib.h +++ b/src/common/strlib.h @@ -1,5 +1,6 @@ -// 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 _STRLIB_H_ #define _STRLIB_H_ @@ -11,56 +12,14 @@ #include <string.h> #undef __USE_GNU -char* jstrescape (char* pt); -char* jstrescapecpy (char* pt, const char* spt); -int jmemescapecpy (char* pt, const char* spt, int size); - -int remove_control_chars(char* str); -char* trim(char* str); -char* normalize_name(char* str,const char* delims); -const char *stristr(const char *haystack, const char *needle); - #ifdef WIN32 -#define HAVE_STRTOK_R -#define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr)) -char* _strtok_r(char* s1, const char* s2, char** lasts); -#endif - -#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN) -size_t strnlen (const char* string, size_t maxlen); + #define HAVE_STRTOK_R + #define strtok_r(s,delim,save_ptr) _strtok_r((s),(delim),(save_ptr)) + char *_strtok_r(char* s1, const char* s2, char** lasts); #endif -#if defined(WIN32) && defined(_MSC_VER) && _MSC_VER <= 1200 -uint64 strtoull(const char* str, char** endptr, int base); -#endif - -int e_mail_check(char* email); -int config_switch(const char* str); - -/// strncpy that always nul-terminates the string -char* safestrncpy(char* dst, const char* src, size_t n); - -/// doesn't crash on null pointer -size_t safestrnlen(const char* string, size_t maxlen); - -/// Works like snprintf, but always nul-terminates the buffer. -/// Returns the size of the string (without nul-terminator) -/// or -1 if the buffer is too small. -int safesnprintf(char* buf, size_t sz, const char* fmt, ...); - -/// Returns the line of the target position in the string. -/// Lines start at 1. -int strline(const char* str, size_t pos); - -/// Produces the hexadecimal representation of the given input. -/// The output buffer must be at least count*2+1 in size. -/// Returns true on success, false on failure. -bool bin2hex(char* output, unsigned char* input, size_t count); - - /// Bitfield determining the behaviour of sv_parse and sv_split. -typedef enum e_svopt -{ +typedef enum e_svopt { // default: no escapes and no line terminator SV_NOESCAPE_NOTERMINATE = 0, // Escapes according to the C compiler. @@ -78,8 +37,7 @@ typedef enum e_svopt /// Parse state. /// The field is [start,end[ -struct s_svstate -{ +struct s_svstate { const char* str; //< string to parse int len; //< string length int off; //< current offset in the string @@ -90,66 +48,144 @@ struct s_svstate bool done; //< if all the text has been parsed }; -/// Parses a single field in a delim-separated string. -/// The delimiter after the field is skipped. -/// -/// @param sv Parse state -/// @return 1 if a field was parsed, 0 if done, -1 on error. -int sv_parse_next(struct s_svstate* sv); - -/// Parses a delim-separated string. -/// Starts parsing at startoff and fills the pos array with position pairs. -/// out_pos[0] and out_pos[1] are the start and end of line. -/// Other position pairs are the start and end of fields. -/// Returns the number of fields found or -1 if an error occurs. -int sv_parse(const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt); - -/// Splits a delim-separated string. -/// WARNING: this function modifies the input string -/// Starts splitting at startoff and fills the out_fields array. -/// out_fields[0] is the start of the next line. -/// Other entries are the start of fields (nul-teminated). -/// Returns the number of fields found or -1 if an error occurs. -int sv_split(char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt); - -/// Escapes src to out_dest according to the format of the C compiler. -/// Returns the length of the escaped string. -/// out_dest should be len*4+1 in size. -size_t sv_escape_c(char* out_dest, const char* src, size_t len, const char* escapes); - -/// Unescapes src to out_dest according to the format of the C compiler. -/// Returns the length of the unescaped string. -/// out_dest should be len+1 in size and can be the same buffer as src. -size_t sv_unescape_c(char* out_dest, const char* src, size_t len); - -/// Skips a C escape sequence (starting with '\\'). -const char* skip_escaped_c(const char* p); - -/// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row. -/// Tracks the progress of the operation (current line number, number of successfully processed rows). -/// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read. -bool sv_readdb(const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current)); - /// StringBuf - dynamic string -struct StringBuf -{ +struct StringBuf { char *buf_; char *ptr_; unsigned int max_; }; typedef struct StringBuf StringBuf; -StringBuf* StringBuf_Malloc(void); -void StringBuf_Init(StringBuf* self); -int StringBuf_Printf(StringBuf* self, const char* fmt, ...); -int StringBuf_Vprintf(StringBuf* self, const char* fmt, va_list args); -int StringBuf_Append(StringBuf* self, const StringBuf *sbuf); -int StringBuf_AppendStr(StringBuf* self, const char* str); -int StringBuf_Length(StringBuf* self); -char* StringBuf_Value(StringBuf* self); -void StringBuf_Clear(StringBuf* self); -void StringBuf_Destroy(StringBuf* self); -void StringBuf_Free(StringBuf* self); - +struct strlib_interface { + char *(*jstrescape) (char* pt); + char *(*jstrescapecpy) (char* pt, const char* spt); + int (*jmemescapecpy) (char* pt, const char* spt, int size); + int (*remove_control_chars) (char* str); + char *(*trim) (char* str); + char *(*normalize_name) (char* str,const char* delims); + const char *(*stristr) (const char *haystack, const char *needle); + +#if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN) + size_t (*strnlen) (const char* string, size_t maxlen); +#endif + +#if defined(WIN32) && defined(_MSC_VER) && _MSC_VER <= 1200 + uint64 (*strtoull) (const char* str, char** endptr, int base); +#endif + + int (*e_mail_check) (char* email); + int (*config_switch) (const char* str); + + /// strncpy that always nul-terminates the string + char *(*safestrncpy) (char* dst, const char* src, size_t n); + + /// doesn't crash on null pointer + size_t (*safestrnlen) (const char* string, size_t maxlen); + + /// Works like snprintf, but always nul-terminates the buffer. + /// Returns the size of the string (without nul-terminator) + /// or -1 if the buffer is too small. + int (*safesnprintf) (char* buf, size_t sz, const char* fmt, ...); + + /// Returns the line of the target position in the string. + /// Lines start at 1. + int (*strline) (const char* str, size_t pos); + + /// Produces the hexadecimal representation of the given input. + /// The output buffer must be at least count*2+1 in size. + /// Returns true on success, false on failure. + bool (*bin2hex) (char* output, unsigned char* input, size_t count); +} strlib_s; + +struct strlib_interface *strlib; + +struct stringbuf_interface { + StringBuf* (*Malloc) (void); + void (*Init) (StringBuf* self); + int (*Printf) (StringBuf* self, const char* fmt, ...); + int (*Vprintf) (StringBuf* self, const char* fmt, va_list args); + int (*Append) (StringBuf* self, const StringBuf *sbuf); + int (*AppendStr) (StringBuf* self, const char* str); + int (*Length) (StringBuf* self); + char* (*Value) (StringBuf* self); + void (*Clear) (StringBuf* self); + void (*Destroy) (StringBuf* self); + void (*Free) (StringBuf* self); +} stringbuf_s; + +struct stringbuf_interface *StrBuf; + +struct sv_interface { + /// Parses a single field in a delim-separated string. + /// The delimiter after the field is skipped. + /// + /// @param sv Parse state + /// @return 1 if a field was parsed, 0 if done, -1 on error. + int (*parse_next) (struct s_svstate* sv); + + /// Parses a delim-separated string. + /// Starts parsing at startoff and fills the pos array with position pairs. + /// out_pos[0] and out_pos[1] are the start and end of line. + /// Other position pairs are the start and end of fields. + /// Returns the number of fields found or -1 if an error occurs. + int (*parse) (const char* str, int len, int startoff, char delim, int* out_pos, int npos, enum e_svopt opt); + + /// Splits a delim-separated string. + /// WARNING: this function modifies the input string + /// Starts splitting at startoff and fills the out_fields array. + /// out_fields[0] is the start of the next line. + /// Other entries are the start of fields (nul-teminated). + /// Returns the number of fields found or -1 if an error occurs. + int (*split) (char* str, int len, int startoff, char delim, char** out_fields, int nfields, enum e_svopt opt); + + /// Escapes src to out_dest according to the format of the C compiler. + /// Returns the length of the escaped string. + /// out_dest should be len*4+1 in size. + size_t (*escape_c) (char* out_dest, const char* src, size_t len, const char* escapes); + + /// Unescapes src to out_dest according to the format of the C compiler. + /// Returns the length of the unescaped string. + /// out_dest should be len+1 in size and can be the same buffer as src. + size_t (*unescape_c) (char* out_dest, const char* src, size_t len); + + /// Skips a C escape sequence (starting with '\\'). + const char* (*skip_escaped_c) (const char* p); + + /// Opens and parses a file containing delim-separated columns, feeding them to the specified callback function row by row. + /// Tracks the progress of the operation (current line number, number of successfully processed rows). + /// Returns 'true' if it was able to process the specified file, or 'false' if it could not be read. + bool (*readdb) (const char* directory, const char* filename, char delim, int mincols, int maxcols, int maxrows, bool (*parseproc)(char* fields[], int columns, int current)); +} sv_s; + +struct sv_interface *sv; + +void strlib_defaults(void); + +/* the purpose of these macros is simply to not make calling them be an annoyance */ +#ifndef STRLIB_C + #define jstrescape(pt) strlib->jstrescape(pt) + #define jstrescapecpy(pt,spt) strlib->jstrescapecpy(pt,spt) + #define jmemescapecpy(pt,spt,size) strlib->jmemescapecpy(pt,spt,size) + #define remove_control_chars(str) strlib->remove_control_chars(str) + #define trim(str) strlib->trim(str) + #define normalize_name(str,delims) strlib->normalize_name(str,delims) + #define stristr(haystack,needle) strlib->stristr(haystack,needle) + + #if !(defined(WIN32) && defined(_MSC_VER) && _MSC_VER >= 1400) && !defined(HAVE_STRNLEN) + #define strnln(string,maxlen) strlib->strnlen(string,maxlen) + #endif + + #if defined(WIN32) && defined(_MSC_VER) && _MSC_VER <= 1200 + #define strtoull(str,endptr,base) strlib->strtoull(str,endptr,base) + #endif + + #define e_mail_check(email) strlib->e_mail_check(email) + #define config_switch(str) strlib->config_switch(str) + #define safestrncpy(dst,src,n) strlib->safestrncpy(dst,src,n) + #define safestrnlen(string,maxlen) strlib->safestrnlen(string,maxlen) + #define safesnprintf(buf,sz,fmt,...) strlib->safesnprintf(buf,sz,fmt,##__VA_ARGS__) + #define strline(str,pos) strlib->strline(str,pos) + #define bin2hex(output,input,count) strlib->bin2hex(output,input,count) +#endif /* STRLIB_C */ #endif /* _STRLIB_H_ */ diff --git a/src/common/timer.c b/src/common/timer.c index c239a9d70..edb46bd71 100644 --- a/src/common/timer.c +++ b/src/common/timer.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/db.h" @@ -62,7 +63,7 @@ struct timer_func_list { } *tfl_root = NULL; /// Sets the name of a timer function. -int add_timer_func_list(TimerFunc func, char* name) +int timer_add_func_list(TimerFunc func, char* name) { struct timer_func_list* tfl; @@ -70,9 +71,9 @@ int add_timer_func_list(TimerFunc func, char* name) for( tfl=tfl_root; tfl != NULL; tfl=tfl->next ) {// check suspicious cases if( func == tfl->func ) - ShowWarning("add_timer_func_list: duplicating function %p(%s) as %s.\n",tfl->func,tfl->name,name); + ShowWarning("timer_add_func_list: duplicating function %p(%s) as %s.\n",tfl->func,tfl->name,name); else if( strcmp(name,tfl->name) == 0 ) - ShowWarning("add_timer_func_list: function %p has the same name as %p(%s)\n",func,tfl->func,tfl->name); + ShowWarning("timer_add_func_list: function %p has the same name as %p(%s)\n",func,tfl->func,tfl->name); } CREATE(tfl,struct timer_func_list,1); tfl->next = tfl_root; @@ -137,8 +138,7 @@ static void rdtsc_calibrate(){ #endif /// platform-abstracted tick retrieval -static unsigned int tick(void) -{ +static unsigned int tick(void) { #if defined(WIN32) return GetTickCount(); #elif defined(ENABLE_RDTSC) @@ -163,28 +163,25 @@ static unsigned int tick(void) static unsigned int gettick_cache; static int gettick_count = 1; -unsigned int gettick_nocache(void) -{ +unsigned int timer_gettick_nocache(void) { gettick_count = TICK_CACHE; gettick_cache = tick(); return gettick_cache; } -unsigned int gettick(void) -{ +unsigned int timer_gettick(void) { return ( --gettick_count == 0 ) ? gettick_nocache() : gettick_cache; } ////////////////////////////// #else ////////////////////////////// // tick doesn't get cached -unsigned int gettick_nocache(void) +unsigned int timer_gettick_nocache(void) { return tick(); } -unsigned int gettick(void) -{ +unsigned int timer_gettick(void) { return tick(); } ////////////////////////////////////////////////////////////////////////// @@ -196,8 +193,7 @@ unsigned int gettick(void) *--------------------------------------*/ /// Adds a timer to the timer_heap -static void push_timer_heap(int tid) -{ +static void push_timer_heap(int tid) { BHEAP_ENSURE(timer_heap, 1, 256); BHEAP_PUSH(timer_heap, tid, DIFFTICK_MINTOPCMP); } @@ -207,8 +203,7 @@ static void push_timer_heap(int tid) *--------------------------*/ /// Returns a free timer id. -static int acquire_timer(void) -{ +static int acquire_timer(void) { int tid; // select a free timer @@ -240,8 +235,7 @@ static int acquire_timer(void) /// Starts a new timer that is deleted once it expires (single-use). /// Returns the timer's id. -int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data) -{ +int timer_add(unsigned int tick, TimerFunc func, int id, intptr_t data) { int tid; tid = acquire_timer(); @@ -258,13 +252,12 @@ int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data) /// Starts a new timer that automatically restarts itself (infinite loop until manually removed). /// Returns the timer's id, or INVALID_TIMER if it fails. -int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval) +int timer_add_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval) { int tid; - if( interval < 1 ) - { - ShowError("add_timer_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick())); + if( interval < 1 ) { + ShowError("timer_add_interval: invalid interval (tick=%u %p[%s] id=%d data=%d diff_tick=%d)\n", tick, func, search_timer_func_list(func), id, data, DIFF_TICK(tick, gettick())); return INVALID_TIMER; } @@ -281,24 +274,20 @@ int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, } /// Retrieves internal timer data -const struct TimerData* get_timer(int tid) -{ +const struct TimerData* timer_get(int tid) { return ( tid >= 0 && tid < timer_data_num ) ? &timer_data[tid] : NULL; } /// Marks a timer specified by 'id' for immediate deletion once it expires. /// Param 'func' is used for debug/verification purposes. /// Returns 0 on success, < 0 on failure. -int delete_timer(int tid, TimerFunc func) -{ - if( tid < 0 || tid >= timer_data_num ) - { - ShowError("delete_timer error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func)); +int timer_do_delete(int tid, TimerFunc func) { + if( tid < 0 || tid >= timer_data_num ) { + ShowError("timer_do_delete error : no such timer %d (%p(%s))\n", tid, func, search_timer_func_list(func)); return -1; } - if( timer_data[tid].func != func ) - { - ShowError("delete_timer error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func)); + if( timer_data[tid].func != func ) { + ShowError("timer_do_delete error : function mismatch %p(%s) != %p(%s)\n", timer_data[tid].func, search_timer_func_list(timer_data[tid].func), func, search_timer_func_list(func)); return -2; } @@ -310,22 +299,19 @@ int delete_timer(int tid, TimerFunc func) /// Adjusts a timer's expiration time. /// Returns the new tick value, or -1 if it fails. -int addtick_timer(int tid, unsigned int tick) -{ +int timer_addtick(int tid, unsigned int tick) { return settick_timer(tid, timer_data[tid].tick+tick); } /// Modifies a timer's expiration time (an alternative to deleting a timer and starting a new one). /// Returns the new tick value, or -1 if it fails. -int settick_timer(int tid, unsigned int tick) -{ +int timer_settick(int tid, unsigned int tick) { size_t i; // search timer position ARR_FIND(0, BHEAP_LENGTH(timer_heap), i, BHEAP_DATA(timer_heap)[i] == tid); - if( i == BHEAP_LENGTH(timer_heap) ) - { - ShowError("settick_timer: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); + if( i == BHEAP_LENGTH(timer_heap) ) { + ShowError("timer_settick: no such timer %d (%p(%s))\n", tid, timer_data[tid].func, search_timer_func_list(timer_data[tid].func)); return -1; } @@ -344,13 +330,11 @@ int settick_timer(int tid, unsigned int tick) /// Executes all expired timers. /// Returns the value of the smallest non-expired timer (or 1 second if there aren't any). -int do_timer(unsigned int tick) -{ +int do_timer(unsigned int tick) { int diff = TIMER_MAX_INTERVAL; // return value // process all timers one by one - while( BHEAP_LENGTH(timer_heap) ) - { + while( BHEAP_LENGTH(timer_heap) ) { int tid = BHEAP_PEEK(timer_heap);// top element in heap (smallest tick) diff = DIFF_TICK(timer_data[tid].tick, tick); @@ -361,8 +345,7 @@ int do_timer(unsigned int tick) BHEAP_POP(timer_heap, DIFFTICK_MINTOPCMP); timer_data[tid].type |= TIMER_REMOVE_HEAP; - if( timer_data[tid].func ) - { + if( timer_data[tid].func ) { if( diff < -1000 ) // timer was delayed for more than 1 second, use current tick instead timer_data[tid].func(tid, tick, timer_data[tid].id, timer_data[tid].data); @@ -371,29 +354,27 @@ int do_timer(unsigned int tick) } // in the case the function didn't change anything... - if( timer_data[tid].type & TIMER_REMOVE_HEAP ) - { + if( timer_data[tid].type & TIMER_REMOVE_HEAP ) { timer_data[tid].type &= ~TIMER_REMOVE_HEAP; - switch( timer_data[tid].type ) - { - default: - case TIMER_ONCE_AUTODEL: - timer_data[tid].type = 0; - if (free_timer_list_pos >= free_timer_list_max) { - free_timer_list_max += 256; - RECREATE(free_timer_list,int,free_timer_list_max); - memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int)); - } - free_timer_list[free_timer_list_pos++] = tid; - break; - case TIMER_INTERVAL: - if( DIFF_TICK(timer_data[tid].tick, tick) < -1000 ) - timer_data[tid].tick = tick + timer_data[tid].interval; - else - timer_data[tid].tick += timer_data[tid].interval; - push_timer_heap(tid); - break; + switch( timer_data[tid].type ) { + default: + case TIMER_ONCE_AUTODEL: + timer_data[tid].type = 0; + if (free_timer_list_pos >= free_timer_list_max) { + free_timer_list_max += 256; + RECREATE(free_timer_list,int,free_timer_list_max); + memset(free_timer_list + (free_timer_list_max - 256), 0, 256 * sizeof(int)); + } + free_timer_list[free_timer_list_pos++] = tid; + break; + case TIMER_INTERVAL: + if( DIFF_TICK(timer_data[tid].tick, tick) < -1000 ) + timer_data[tid].tick = tick + timer_data[tid].interval; + else + timer_data[tid].tick += timer_data[tid].interval; + push_timer_heap(tid); + break; } } } @@ -401,8 +382,7 @@ int do_timer(unsigned int tick) return cap_value(diff, TIMER_MIN_INTERVAL, TIMER_MAX_INTERVAL); } -unsigned long get_uptime(void) -{ +unsigned long timer_get_uptime(void) { return (unsigned long)difftime(time(NULL), start_time); } @@ -415,8 +395,7 @@ void timer_init(void) time(&start_time); } -void timer_final(void) -{ +void timer_final(void) { struct timer_func_list *tfl; struct timer_func_list *next; @@ -430,3 +409,15 @@ void timer_final(void) BHEAP_CLEAR(timer_heap); if (free_timer_list) aFree(free_timer_list); } +void timer_defaults(void) { + gettick = timer_gettick; + gettick_nocache = timer_gettick_nocache; + add_timer = timer_add; + add_timer_interval = timer_add_interval; + add_timer_func_list = timer_add_func_list; + get_timer = timer_get; + delete_timer = timer_do_delete; + addtick_timer = timer_addtick; + settick_timer = timer_settick; + get_uptime = timer_get_uptime; +} diff --git a/src/common/timer.h b/src/common/timer.h index d45c73d12..902679f51 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -1,5 +1,6 @@ -// 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 _TIMER_H_ #define _TIMER_H_ @@ -35,23 +36,26 @@ struct TimerData { // Function prototype declaration -unsigned int gettick(void); -unsigned int gettick_nocache(void); +int do_timer(unsigned int tick); +void timer_init(void); +void timer_final(void); -int add_timer(unsigned int tick, TimerFunc func, int id, intptr_t data); -int add_timer_interval(unsigned int tick, TimerFunc func, int id, intptr_t data, int interval); -const struct TimerData* get_timer(int tid); -int delete_timer(int tid, TimerFunc func); +/* Hercules Renewal Phase One */ +unsigned int (*gettick) (void); +unsigned int (*gettick_nocache) (void); -int addtick_timer(int tid, unsigned int tick); -int settick_timer(int tid, unsigned int tick); +int (*add_timer) (unsigned int tick, TimerFunc func, int id, intptr_t data); +int (*add_timer_interval) (unsigned int tick, TimerFunc func, int id, intptr_t data, int interval); +const struct TimerData *(*get_timer) (int tid); +int (*delete_timer) (int tid, TimerFunc func); -int add_timer_func_list(TimerFunc func, char* name); +int (*addtick_timer) (int tid, unsigned int tick); +int (*settick_timer) (int tid, unsigned int tick); -unsigned long get_uptime(void); +int (*add_timer_func_list) (TimerFunc func, char* name); -int do_timer(unsigned int tick); -void timer_init(void); -void timer_final(void); +unsigned long (*get_uptime) (void); + +void timer_defaults(void); #endif /* _TIMER_H_ */ diff --git a/src/config/classes/general.h b/src/config/classes/general.h index 6e6cc1425..206f57b37 100644 --- a/src/config/classes/general.h +++ b/src/config/classes/general.h @@ -1,11 +1,11 @@ -// Copyright (c) rAthena 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 _CONFIG_GENERAL_H_ #define _CONFIG_GENERAL_H_ /** - * rAthena configuration file (http://rathena.org) - * For detailed guidance on these check http://rathena.org/wiki/SRC/config/ + * Hercules configuration file (http://hercules.ws) **/ /** @@ -17,6 +17,11 @@ #define MAGIC_REFLECTION_TYPE 1 /** + * Spirit Sphere Limitation + **/ +#define MAX_SPIRITBALL 15 + +/** * No settings past this point **/ diff --git a/src/config/const.h b/src/config/const.h index 5fb74e22e..53f24da6f 100644 --- a/src/config/const.h +++ b/src/config/const.h @@ -1,11 +1,12 @@ -// Copyright (c) rAthena Dev Teams - Licensed under GNU GPL -// For more information, see LICENCE in the main folder -#ifndef _RRCONFIGS_CONST_ -#define _RRCONFIGS_CONST_ +// 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_ /** - * rAthena configuration file (http://rathena.org) - * For detailed guidance on these check http://rathena.org/wiki/SRC/config/ + * Hercules configuration file (http://hercules.ws) + * For detailed guidance on these check http://hercules.ws/wiki/SRC/config/ **/ /** @@ -18,8 +19,14 @@ #if SECURE_NPCTIMEOUT_INTERVAL <= 0 #error SECURE_NPCTIMEOUT_INTERVAL should be at least 1 (1s) #endif -#if SECURE_NPCTIMEOUT < 0 - #error SECURE_NPCTIMEOUT cannot be lower than 0 +#if NPC_SECURE_TIMEOUT_INPUT < 0 + #error NPC_SECURE_TIMEOUT_INPUT cannot be lower than 0 +#endif +#if NPC_SECURE_TIMEOUT_MENU < 0 + #error NPC_SECURE_TIMEOUT_MENU cannot be lower than 0 +#endif +#if NPC_SECURE_TIMEOUT_NEXT < 0 + #error NPC_SECURE_TIMEOUT_NEXT cannot be lower than 0 #endif /** @@ -46,9 +53,9 @@ /* pointer size fix which fixes several gcc warnings */ #ifdef __64BIT__ - #define __64BPRTSIZE(y) (intptr)y + #define __64BPTRSIZE(y) (intptr)y #else - #define __64BPRTSIZE(y) y + #define __64BPTRSIZE(y) y #endif /* ATCMD_FUNC(mobinfo) HIT and FLEE calculations */ @@ -93,7 +100,13 @@ time = time * (1 - (float)min(val, 100) / 100); \ } #endif + +/* console_input doesn't go well with minicore */ +#ifdef MINICORE + #undef CONSOLE_INPUT +#endif + /** * End of File **/ -#endif +#endif /* _H_CONSTANTS_ */ diff --git a/src/config/core.h b/src/config/core.h index 1e8ce9992..bec6cb507 100644 --- a/src/config/core.h +++ b/src/config/core.h @@ -1,13 +1,9 @@ -// Copyright (c) rAthena 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 _CONFIG_CORE_H_ #define _CONFIG_CORE_H_ -/** - * rAthena configuration file (http://rathena.org) - * For detailed guidance on these check http://rathena.org/wiki/SRC/config/ - **/ - /// Max number of items on @autolootid list #define AUTOLOOTITEM_SIZE 10 @@ -27,14 +23,16 @@ /// your map-server using more resources while this is active, comment the line #define SCRIPT_CALLFUNC_CHECK -/// Uncomment to disable rAthena's anonymous stat report -/// We kindly ask you to consider keeping it enabled, it helps us improve rAthena. -//#define STATS_OPT_OUT +/// Comment to disable Hercules' console_parse +/// CONSOLE_INPUT allows you to type commands into the server's console, +/// Disabling it saves one thread. +#define CONSOLE_INPUT +/// Maximum number of caracters 'CONSOLE_INPUT' will support per line. +#define MAX_CONSOLE_INPUT 150 -/// uncomment to enable query_sql script command and mysql logs to function on it's own thread -/// be aware this feature is under tests and you should use at your own risk, we however -/// welcome any feedback you may have regarding this feature, please send us all bug reports. -//#define BETA_THREAD_TEST +/// Uncomment to disable Hercules' anonymous stat report +/// We kindly ask you to consider keeping it enabled, it helps us improve Hercules. +//#define STATS_OPT_OUT /// Uncomment to enable the Cell Stack Limit mod. /// It's only config is the battle_config cell_stack_limit. @@ -48,6 +46,17 @@ /// - but is not the official behaviour. //#define CIRCULAR_AREA +//This is the distance at which @autoloot works, +//if the item drops farther from the player than this, +//it will not be autolooted. [Skotlex] +//Note: The range is unlimited unless this define is set. +//#define AUTOLOOT_DISTANCE AREA_SIZE + +/// Uncomment to switch the way map zones' "skill_damage_cap" functions. +/// When commented the cap takes place before modifiers, as to have them be useful. +/// When uncommented the cap takes place after modifiers. +//#define HMAP_ZONE_DAMAGE_CAP_TYPE + /// Uncomment to enable Non Stackable items unique ID /// By enabling it, the system will create an unique id for each new non stackable item created //#define NSI_UNIQUE_ID diff --git a/src/config/renewal.h b/src/config/renewal.h index 339937adb..8bd151f57 100644 --- a/src/config/renewal.h +++ b/src/config/renewal.h @@ -1,11 +1,12 @@ -// Copyright (c) rAthena 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 _CONFIG_RENEWAL_H_ #define _CONFIG_RENEWAL_H_ /** - * rAthena configuration file (http://rathena.org) - * For detailed guidance on these check http://rathena.org/wiki/SRC/config/ + * Hercules configuration file (http://hercules.ws) + * For detailed guidance on these check http://hercules.ws/wiki/SRC/config/ **/ /** diff --git a/src/config/secure.h b/src/config/secure.h index c57db018a..7f16ba55a 100644 --- a/src/config/secure.h +++ b/src/config/secure.h @@ -1,11 +1,12 @@ -// Copyright (c) rAthena 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 _CONFIG_SECURE_H_ #define _CONFIG_SECURE_H_ /** - * rAthena configuration file (http://rathena.org) - * For detailed guidance on these check http://rathena.org/wiki/SRC/config/ + * Hercules configuration file (http://hercules.ws) + * For detailed guidance on these check http://hercules.ws/wiki/SRC/config/ **/ /** @@ -16,11 +17,27 @@ * Optional NPC Dialog Timer * When enabled all npcs dialog will 'timeout' if user is on idle for longer than the amount of seconds allowed * - On 'timeout' the npc dialog window changes its next/menu to a 'close' button - * @values - * - ? : Desired idle time in seconds (e.g. 10) - * - 0 : Disabled + * Uncomment to enable **/ -#define SECURE_NPCTIMEOUT 0 +//#define SECURE_NPCTIMEOUT + +/** + * number of seconds to 'timeout' if the user is on idle for longer than the value allowed after a 'input' field is displayed. + * default: 180 + **/ +#define NPC_SECURE_TIMEOUT_INPUT 180 + +/** + * number of seconds to 'timeout' if the user is on idle for longer than the value allowed after a 'menu' is displayed. + * default: 60 + **/ +#define NPC_SECURE_TIMEOUT_MENU 60 + +/** + * number of seconds to 'timeout' if the user is on idle for longer than the value allowed after a 'next' button is displayed. + * default: 60 + **/ +#define NPC_SECURE_TIMEOUT_NEXT 60 /** * (Secure) Optional NPC Dialog Timer diff --git a/src/login/Makefile.in b/src/login/Makefile.in index d0fc34756..543b31b93 100644 --- a/src/login/Makefile.in +++ b/src/login/Makefile.in @@ -31,11 +31,11 @@ endif all: sql -sql: obj_sql login-server_sql +sql: obj_sql login-server clean: @echo " CLEAN login" - @rm -rf *.o obj_sql ../../login-server@EXEEXT@ ../../login-server_sql@EXEEXT@ + @rm -rf *.o obj_sql ../../login-server@EXEEXT@ ../../login-server@EXEEXT@ help: @echo "possible targets are 'sql' 'all' 'clean' 'help'" @@ -58,9 +58,9 @@ obj_sql: #executables -login-server_sql: $(LOGIN_SERVER_SQL_DEPENDS) +login-server: $(LOGIN_SERVER_SQL_DEPENDS) @echo " LD $@" - @@CC@ @LDFLAGS@ -o ../../login-server_sql@EXEEXT@ $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ + @@CC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@ # login object files diff --git a/src/login/account.h b/src/login/account.h index 1b567be70..be5bad988 100644 --- a/src/login/account.h +++ b/src/login/account.h @@ -38,17 +38,20 @@ struct mmo_account { int account_id; char userid[NAME_LENGTH]; - char pass[32+1]; // 23+1 for plaintext, 32+1 for md5-ed passwords - char sex; // gender (M/F/S) - char email[40]; // e-mail (by default: a@a.com) - int group_id; // player group id - unsigned int state; // packet 0x006a value + 1 (0: compte OK) - time_t unban_time; // (timestamp): ban time limit of the account (0 = no ban) - time_t expiration_time; // (timestamp): validity limit of the account (0 = unlimited) - unsigned int logincount;// number of successful auth attempts - char lastlogin[24]; // date+time of last successful login - char last_ip[16]; // save of last IP of connection - char birthdate[10+1]; // assigned birth date (format: YYYY-MM-DD, default: 0000-00-00) + char pass[32+1]; // 23+1 for plaintext, 32+1 for md5-ed passwords + char sex; // gender (M/F/S) + char email[40]; // e-mail (by default: a@a.com) + int group_id; // player group id + uint8 char_slots; // this accounts maximum character slots (maximum is limited to MAX_CHARS define in char server) + unsigned int state; // packet 0x006a value + 1 (0: compte OK) + time_t unban_time; // (timestamp): ban time limit of the account (0 = no ban) + time_t expiration_time; // (timestamp): validity limit of the account (0 = unlimited) + unsigned int logincount; // number of successful auth attempts + unsigned int pincode_change;// (timestamp): last time of pincode change + char pincode[4+1]; // pincode value + char lastlogin[24]; // date+time of last successful login + char last_ip[16]; // save of last IP of connection + char birthdate[10+1]; // assigned birth date (format: YYYY-MM-DD, default: 0000-00-00) int account_reg2_num; struct global_reg account_reg2[ACCOUNT_REG2_NUM]; // account script variables (stored on login server) }; @@ -152,5 +155,6 @@ struct AccountDB AccountDBIterator* (*iterator)(AccountDB* self); }; +void account_db_sql_up(AccountDB* self); #endif // __ACCOUNT_H_INCLUDED__ diff --git a/src/login/account_sql.c b/src/login/account_sql.c index 5073941e2..565dd0460 100644 --- a/src/login/account_sql.c +++ b/src/login/account_sql.c @@ -1,5 +1,6 @@ -// 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 #include "../common/malloc.h" #include "../common/mmo.h" @@ -125,7 +126,7 @@ static bool account_db_sql_init(AccountDB* self) const char* database; const char* codepage; - db->accounts = Sql_Malloc(); + db->accounts = SQL->Malloc(); sql_handle = db->accounts; if( db->db_hostname[0] != '\0' ) @@ -147,15 +148,15 @@ static bool account_db_sql_init(AccountDB* self) codepage = db->global_codepage; } - if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) ) + if( SQL_ERROR == SQL->Connect(sql_handle, username, password, hostname, port, database) ) { Sql_ShowDebug(sql_handle); - Sql_Free(db->accounts); + SQL->Free(db->accounts); db->accounts = NULL; return false; } - if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) ) + if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) ) Sql_ShowDebug(sql_handle); return true; @@ -166,7 +167,7 @@ static void account_db_sql_destroy(AccountDB* self) { AccountDB_SQL* db = (AccountDB_SQL*)self; - Sql_Free(db->accounts); + SQL->Free(db->accounts); db->accounts = NULL; aFree(db); } @@ -348,21 +349,21 @@ static bool account_db_sql_create(AccountDB* self, struct mmo_account* acc) char* data; size_t len; - if( SQL_SUCCESS != Sql_Query(sql_handle, "SELECT MAX(`account_id`)+1 FROM `%s`", db->account_db) ) + if( SQL_SUCCESS != SQL->Query(sql_handle, "SELECT MAX(`account_id`)+1 FROM `%s`", db->account_db) ) { Sql_ShowDebug(sql_handle); return false; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) { Sql_ShowDebug(sql_handle); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } - Sql_GetData(sql_handle, 0, &data, &len); + SQL->GetData(sql_handle, 0, &data, &len); account_id = ( data != NULL ) ? atoi(data) : 0; - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); if( account_id < START_ACCOUNT_NUM ) account_id = START_ACCOUNT_NUM; @@ -389,14 +390,14 @@ static bool account_db_sql_remove(AccountDB* self, const int account_id) Sql* sql_handle = db->accounts; bool result = false; - if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION") - || SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->account_db, account_id) - || SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->accreg_db, account_id) ) + if( SQL_SUCCESS != SQL->QueryStr(sql_handle, "START TRANSACTION") + || SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->account_db, account_id) + || SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `account_id` = %d", db->accreg_db, account_id) ) Sql_ShowDebug(sql_handle); else result = true; - result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") ); + result &= ( SQL_SUCCESS == SQL->QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") ); return result; } @@ -424,30 +425,30 @@ static bool account_db_sql_load_str(AccountDB* self, struct mmo_account* acc, co int account_id; char* data; - Sql_EscapeString(sql_handle, esc_userid, userid); + SQL->EscapeString(sql_handle, esc_userid, userid); // get the list of account IDs for this user ID - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `userid`= %s '%s'", + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `userid`= %s '%s'", db->account_db, (db->case_sensitive ? "BINARY" : ""), esc_userid) ) { Sql_ShowDebug(sql_handle); return false; } - if( Sql_NumRows(sql_handle) > 1 ) + if( SQL->NumRows(sql_handle) > 1 ) {// serious problem - duplicit account ShowError("account_db_sql_load_str: multiple accounts found when retrieving data for account '%s'!\n", userid); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) {// no such entry - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); account_id = atoi(data); return account_db_sql_load_num(self, acc, account_id); @@ -486,30 +487,30 @@ static bool account_db_sql_iter_next(AccountDBIterator* self, struct mmo_account AccountDBIterator_SQL* iter = (AccountDBIterator_SQL*)self; AccountDB_SQL* db = (AccountDB_SQL*)iter->db; Sql* sql_handle = db->accounts; - int account_id; char* data; // get next account ID - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` > '%d' ORDER BY `account_id` ASC LIMIT 1", + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `account_id` FROM `%s` WHERE `account_id` > '%d' ORDER BY `account_id` ASC LIMIT 1", db->account_db, iter->last_account_id) ) { Sql_ShowDebug(sql_handle); return false; } - if( SQL_SUCCESS == Sql_NextRow(sql_handle) && - SQL_SUCCESS == Sql_GetData(sql_handle, 0, &data, NULL) && + if( SQL_SUCCESS == SQL->NextRow(sql_handle) && + SQL_SUCCESS == SQL->GetData(sql_handle, 0, &data, NULL) && data != NULL ) {// get account data + int account_id; account_id = atoi(data); if( mmo_auth_fromsql(db, acc, account_id) ) { iter->last_account_id = account_id; - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return true; } } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } @@ -521,54 +522,57 @@ static bool mmo_auth_fromsql(AccountDB_SQL* db, struct mmo_account* acc, int acc int i = 0; // retrieve login entry for the specified account - if( SQL_ERROR == Sql_Query(sql_handle, - "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate` FROM `%s` WHERE `account_id` = %d", + if( SQL_ERROR == SQL->Query(sql_handle, + "SELECT `account_id`,`userid`,`user_pass`,`sex`,`email`,`group_id`,`state`,`unban_time`,`expiration_time`,`logincount`,`lastlogin`,`last_ip`,`birthdate`,`character_slots`,`pincode`,`pincode_change` FROM `%s` WHERE `account_id` = %d", db->account_db, account_id ) ) { Sql_ShowDebug(sql_handle); return false; } - if( SQL_SUCCESS != Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(sql_handle) ) {// no such entry - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return false; } - Sql_GetData(sql_handle, 0, &data, NULL); acc->account_id = atoi(data); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->userid, data, sizeof(acc->userid)); - Sql_GetData(sql_handle, 2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass)); - Sql_GetData(sql_handle, 3, &data, NULL); acc->sex = data[0]; - Sql_GetData(sql_handle, 4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email)); - Sql_GetData(sql_handle, 5, &data, NULL); acc->group_id = atoi(data); - Sql_GetData(sql_handle, 6, &data, NULL); acc->state = strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 7, &data, NULL); acc->unban_time = atol(data); - Sql_GetData(sql_handle, 8, &data, NULL); acc->expiration_time = atol(data); - Sql_GetData(sql_handle, 9, &data, NULL); acc->logincount = strtoul(data, NULL, 10); - Sql_GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin)); - Sql_GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip)); - Sql_GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate)); - - Sql_FreeResult(sql_handle); + SQL->GetData(sql_handle, 0, &data, NULL); acc->account_id = atoi(data); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->userid, data, sizeof(acc->userid)); + SQL->GetData(sql_handle, 2, &data, NULL); safestrncpy(acc->pass, data, sizeof(acc->pass)); + SQL->GetData(sql_handle, 3, &data, NULL); acc->sex = data[0]; + SQL->GetData(sql_handle, 4, &data, NULL); safestrncpy(acc->email, data, sizeof(acc->email)); + SQL->GetData(sql_handle, 5, &data, NULL); acc->group_id = atoi(data); + SQL->GetData(sql_handle, 6, &data, NULL); acc->state = strtoul(data, NULL, 10); + SQL->GetData(sql_handle, 7, &data, NULL); acc->unban_time = atol(data); + SQL->GetData(sql_handle, 8, &data, NULL); acc->expiration_time = atol(data); + SQL->GetData(sql_handle, 9, &data, NULL); acc->logincount = strtoul(data, NULL, 10); + SQL->GetData(sql_handle, 10, &data, NULL); safestrncpy(acc->lastlogin, data, sizeof(acc->lastlogin)); + SQL->GetData(sql_handle, 11, &data, NULL); safestrncpy(acc->last_ip, data, sizeof(acc->last_ip)); + SQL->GetData(sql_handle, 12, &data, NULL); safestrncpy(acc->birthdate, data, sizeof(acc->birthdate)); + SQL->GetData(sql_handle, 13, &data, NULL); acc->char_slots = atoi(data); + SQL->GetData(sql_handle, 14, &data, NULL); safestrncpy(acc->pincode, data, sizeof(acc->pincode)); + SQL->GetData(sql_handle, 15, &data, NULL); acc->pincode_change = atol(data); + + SQL->FreeResult(sql_handle); // retrieve account regs for the specified user - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) ) + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT `str`,`value` FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) ) { Sql_ShowDebug(sql_handle); return false; } - acc->account_reg2_num = (int)Sql_NumRows(sql_handle); + acc->account_reg2_num = (int)SQL->NumRows(sql_handle); - while( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + while( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str)); - Sql_GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value)); + SQL->GetData(sql_handle, 0, &data, NULL); safestrncpy(acc->account_reg2[i].str, data, sizeof(acc->account_reg2[i].str)); + SQL->GetData(sql_handle, 1, &data, NULL); safestrncpy(acc->account_reg2[i].value, data, sizeof(acc->account_reg2[i].value)); ++i; } - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); if( i != acc->account_reg2_num ) return false; @@ -587,7 +591,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo do { - if( SQL_SUCCESS != Sql_QueryStr(sql_handle, "START TRANSACTION") ) + if( SQL_SUCCESS != SQL->QueryStr(sql_handle, "START TRANSACTION") ) { Sql_ShowDebug(sql_handle); break; @@ -596,7 +600,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo if( is_new ) {// insert into account table if( SQL_SUCCESS != SqlStmt_Prepare(stmt, - "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", + "INSERT INTO `%s` (`account_id`, `userid`, `user_pass`, `sex`, `email`, `group_id`, `state`, `unban_time`, `expiration_time`, `logincount`, `lastlogin`, `last_ip`, `birthdate`, `character_slots`, `pincode`, `pincode_change`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)", db->account_db) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_INT, (void*)&acc->account_id, sizeof(acc->account_id)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) @@ -611,15 +615,16 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_STRING, (void*)&acc->pincode, strlen(acc->pincode)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 15, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); break; } - } - else - {// update account table - if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id) + } else {// update account table + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, "UPDATE `%s` SET `userid`=?,`user_pass`=?,`sex`=?,`email`=?,`group_id`=?,`state`=?,`unban_time`=?,`expiration_time`=?,`logincount`=?,`lastlogin`=?,`last_ip`=?,`birthdate`=?,`character_slots`=?,`pincode`=?,`pincode_change`=? WHERE `account_id` = '%d'", db->account_db, acc->account_id) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (void*)acc->userid, strlen(acc->userid)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (void*)acc->pass, strlen(acc->pass)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 2, SQLDT_ENUM, (void*)&acc->sex, sizeof(acc->sex)) @@ -632,6 +637,9 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo || SQL_SUCCESS != SqlStmt_BindParam(stmt, 9, SQLDT_STRING, (void*)&acc->lastlogin, strlen(acc->lastlogin)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 10, SQLDT_STRING, (void*)&acc->last_ip, strlen(acc->last_ip)) || SQL_SUCCESS != SqlStmt_BindParam(stmt, 11, SQLDT_STRING, (void*)&acc->birthdate, strlen(acc->birthdate)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 12, SQLDT_UCHAR, (void*)&acc->char_slots, sizeof(acc->char_slots)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 13, SQLDT_STRING, (void*)&acc->pincode, strlen(acc->pincode)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 14, SQLDT_LONG, (void*)&acc->pincode_change, sizeof(acc->pincode_change)) || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { SqlStmt_ShowDebug(stmt); @@ -640,7 +648,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo } // remove old account regs - if( SQL_SUCCESS != Sql_Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) ) + if( SQL_SUCCESS != SQL->Query(sql_handle, "DELETE FROM `%s` WHERE `type`='1' AND `account_id`='%d'", db->accreg_db, acc->account_id) ) { Sql_ShowDebug(sql_handle); break; @@ -673,8 +681,12 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo } while(0); // finally - result &= ( SQL_SUCCESS == Sql_QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") ); + result &= ( SQL_SUCCESS == SQL->QueryStr(sql_handle, (result == true) ? "COMMIT" : "ROLLBACK") ); SqlStmt_Free(stmt); return result; } +void account_db_sql_up(AccountDB* self) { + AccountDB_SQL* db = (AccountDB_SQL*)self; + Sql_HerculesUpdateCheck(db->accounts); +} diff --git a/src/login/ipban_sql.c b/src/login/ipban_sql.c index c75a1f956..701d3bc1d 100644 --- a/src/login/ipban_sql.c +++ b/src/login/ipban_sql.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/db.h" @@ -73,14 +74,14 @@ void ipban_init(void) } // establish connections - sql_handle = Sql_Malloc(); - if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) ) + sql_handle = SQL->Malloc(); + if( SQL_ERROR == SQL->Connect(sql_handle, username, password, hostname, port, database) ) { Sql_ShowDebug(sql_handle); - Sql_Free(sql_handle); + SQL->Free(sql_handle); exit(EXIT_FAILURE); } - if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) ) + if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) ) Sql_ShowDebug(sql_handle); if( login_config.ipban_cleanup_interval > 0 ) @@ -104,7 +105,7 @@ void ipban_final(void) ipban_cleanup(0,0,0,0); // always clean up on login-server stop // close connections - Sql_Free(sql_handle); + SQL->Free(sql_handle); sql_handle = NULL; } @@ -207,7 +208,7 @@ bool ipban_check(uint32 ip) if( !login_config.ipban ) return false;// ipban disabled - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `rtime` > NOW() AND (`list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u')", + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `rtime` > NOW() AND (`list` = '%u.*.*.*' OR `list` = '%u.%u.*.*' OR `list` = '%u.%u.%u.*' OR `list` = '%u.%u.%u.%u')", ipban_table, p[3], p[3], p[2], p[3], p[2], p[1], p[3], p[2], p[1], p[0]) ) { Sql_ShowDebug(sql_handle); @@ -215,12 +216,12 @@ bool ipban_check(uint32 ip) return true; } - if( SQL_ERROR == Sql_NextRow(sql_handle) ) + if( SQL_ERROR == SQL->NextRow(sql_handle) ) return true;// Shouldn't happen, but just in case... - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); matches = atoi(data); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); return( matches > 0 ); } @@ -239,7 +240,7 @@ void ipban_log(uint32 ip) if( failures >= login_config.dynamic_pass_failure_ban_limit ) { uint8* p = (uint8*)&ip; - if( SQL_ERROR == Sql_Query(sql_handle, "INSERT INTO `%s`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban')", + if( SQL_ERROR == SQL->Query(sql_handle, "INSERT INTO `%s`(`list`,`btime`,`rtime`,`reason`) VALUES ('%u.%u.%u.*', NOW() , NOW() + INTERVAL %d MINUTE ,'Password error ban')", ipban_table, p[3], p[2], p[1], login_config.dynamic_pass_failure_ban_duration) ) Sql_ShowDebug(sql_handle); } @@ -251,7 +252,7 @@ int ipban_cleanup(int tid, unsigned int tick, int id, intptr_t data) if( !login_config.ipban ) return 0;// ipban disabled - if( SQL_ERROR == Sql_Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") ) + if( SQL_ERROR == SQL->Query(sql_handle, "DELETE FROM `ipbanlist` WHERE `rtime` <= NOW()") ) Sql_ShowDebug(sql_handle); return 0; diff --git a/src/login/login.c b/src/login/login.c index e079dbaf2..8dd5ce20a 100644 --- a/src/login/login.c +++ b/src/login/login.c @@ -1,5 +1,6 @@ -// 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 #include "../common/core.h" #include "../common/db.h" @@ -108,7 +109,7 @@ static DBData create_online_user(DBKey key, va_list args) p->account_id = key.i; p->char_server = -1; p->waiting_disconnect = INVALID_TIMER; - return db_ptr2data(p); + return DB->ptr2data(p); } struct online_login_data* add_online_user(int char_server, int account_id) @@ -153,7 +154,7 @@ static int waiting_disconnect_timer(int tid, unsigned int tick, int id, intptr_t */ static int online_db_setoffline(DBKey key, DBData *data, va_list ap) { - struct online_login_data* p = db_data2ptr(data); + struct online_login_data* p = DB->data2ptr(data); int server = va_arg(ap, int); if( server == -1 ) { @@ -174,7 +175,7 @@ static int online_db_setoffline(DBKey key, DBData *data, va_list ap) */ static int online_data_cleanup_sub(DBKey key, DBData *data, va_list ap) { - struct online_login_data *character= db_data2ptr(data); + struct online_login_data *character= DB->data2ptr(data); if (character->char_server == -2) //Unknown server.. set them offline remove_online_user(character->account_id); return 0; @@ -359,58 +360,6 @@ int login_lan_config_read(const char *lancfgName) return 0; } -//----------------------- -// Console Command Parser [Wizputer] -//----------------------- -int parse_console(const char* command) -{ - ShowNotice("Console command: %s\n", command); - - if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 || strcmpi("end", command) == 0 ) - runflag = 0; - else if( strcmpi("alive", command) == 0 || strcmpi("status", command) == 0 ) - ShowInfo(CL_CYAN"Console: "CL_BOLD"I'm Alive."CL_RESET"\n"); - else if( strcmpi("help", command) == 0 ) - { - ShowInfo("To shutdown the server:\n"); - ShowInfo(" 'shutdown|exit|quit|end'\n"); - ShowInfo("To know if server is alive:\n"); - ShowInfo(" 'alive|status'\n"); - ShowInfo("To create a new account:\n"); - ShowInfo(" 'create'\n"); - } - else - {// commands with parameters - char cmd[128], params[256]; - - if( sscanf(command, "%127s %255[^\r\n]", cmd, params) < 2 ) - { - return 0; - } - - if( strcmpi(cmd, "create") == 0 ) - { - char username[NAME_LENGTH], password[NAME_LENGTH], sex; - - if( sscanf(params, "%23s %23s %c", username, password, &sex) < 3 || strnlen(username, sizeof(username)) < 4 || strnlen(password, sizeof(password)) < 1 ) - { - ShowWarning("Console: Invalid parameters for '%s'. Usage: %s <username> <password> <sex:F/M>\n", cmd, cmd); - return 0; - } - - if( mmo_auth_new(username, password, TOUPPER(sex), "0.0.0.0") != -1 ) - { - ShowError("Console: Account creation failed.\n"); - return 0; - } - ShowStatus("Console: Account '%s' created successfully.\n", username); - } - } - - return 0; -} - - //-------------------------------- // Packet parsing for char-servers //-------------------------------- @@ -556,29 +505,37 @@ int parse_fromchar(int fd) time_t expiration_time = 0; char email[40] = ""; int group_id = 0; + uint8 char_slots = 0; char birthdate[10+1] = ""; + char pincode[4+1] = "\0\0\0\0"; int account_id = RFIFOL(fd,2); RFIFOSKIP(fd,6); if( !accounts->load_num(accounts, &acc, account_id) ) ShowNotice("Char-server '%s': account %d NOT found (ip: %s).\n", server[id].name, account_id, ip); - else - { + else { safestrncpy(email, acc.email, sizeof(email)); expiration_time = acc.expiration_time; group_id = acc.group_id; + char_slots = acc.char_slots; + safestrncpy(pincode, acc.pincode, sizeof(pincode)); safestrncpy(birthdate, acc.birthdate, sizeof(birthdate)); + if( strlen(pincode) == 0 ) + memset(pincode,'\0',sizeof(pincode)); } - WFIFOHEAD(fd,62); + WFIFOHEAD(fd,72); WFIFOW(fd,0) = 0x2717; WFIFOL(fd,2) = account_id; safestrncpy((char*)WFIFOP(fd,6), email, 40); WFIFOL(fd,46) = (uint32)expiration_time; - WFIFOB(fd,50) = group_id; - safestrncpy((char*)WFIFOP(fd,51), birthdate, 10+1); - WFIFOSET(fd,62); + WFIFOB(fd,50) = (unsigned char)group_id; + WFIFOB(fd,51) = char_slots; + safestrncpy((char*)WFIFOP(fd,52), birthdate, 10+1); + safestrncpy((char*)WFIFOP(fd,63), pincode, 4+1 ); + WFIFOL(fd,68) = acc.pincode_change; + WFIFOSET(fd,72); } break; @@ -904,6 +861,41 @@ int parse_fromchar(int fd) RFIFOSKIP(fd,2); break; + case 0x2738: //Change PIN Code for a account + if( RFIFOREST(fd) < 11 ) + return 0; + else { + struct mmo_account acc; + + if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ) { + strncpy( acc.pincode, (char*)RFIFOP(fd,6), 5 ); + acc.pincode_change = ((unsigned int)time( NULL )); + accounts->save(accounts, &acc); + } + RFIFOSKIP(fd,11); + } + break; + + case 0x2739: // PIN Code was entered wrong too often + if( RFIFOREST(fd) < 6 ) + return 0; + else { + struct mmo_account acc; + + if( accounts->load_num(accounts, &acc, RFIFOL(fd,2) ) ) { + struct online_login_data* ld; + + if( ( ld = (struct online_login_data*)idb_get(online_db,acc.account_id) ) == NULL ) + return 0; + + login_log( host2ip(acc.last_ip), acc.userid, 100, "PIN Code check failed" ); + } + + remove_online_user(acc.account_id); + RFIFOSKIP(fd,6); + } + break; + default: ShowError("parse_fromchar: Unknown packet 0x%x from a char-server! Disconnecting!\n", command); set_eof(fd); @@ -955,7 +947,10 @@ int mmo_auth_new(const char* userid, const char* pass, const char sex, const cha safestrncpy(acc.lastlogin, "0000-00-00 00:00:00", sizeof(acc.lastlogin)); safestrncpy(acc.last_ip, last_ip, sizeof(acc.last_ip)); safestrncpy(acc.birthdate, "0000-00-00", sizeof(acc.birthdate)); - + safestrncpy(acc.pincode, "\0", sizeof(acc.pincode)); + acc.pincode_change = 0; + acc.char_slots = 0; + if( !accounts->create(accounts, &acc) ) return 0; @@ -1084,8 +1079,8 @@ int mmo_auth(struct login_session_data* sd, bool isServer) { // update session data sd->account_id = acc.account_id; - sd->login_id1 = rnd(); - sd->login_id2 = rnd(); + sd->login_id1 = rnd() + 1; + sd->login_id2 = rnd() + 1; safestrncpy(sd->lastlogin, acc.lastlogin, sizeof(sd->lastlogin)); sd->sex = acc.sex; sd->group_id = acc.group_id; @@ -1278,18 +1273,31 @@ void login_auth_failed(struct login_session_data* sd, int result) if( result == 1 && login_config.dynamic_pass_failure_ban ) ipban_log(ip); // log failed password attempt +#if PACKETVER >= 20120000 /* not sure when this started */ + WFIFOHEAD(fd,26); + WFIFOW(fd,0) = 0x83e; + WFIFOL(fd,2) = result; + if( result != 6 ) + memset(WFIFOP(fd,6), '\0', 20); + else { // 6 = Your are Prohibited to log in until %s + struct mmo_account acc; + time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0; + timestamp2string((char*)WFIFOP(fd,6), 20, unban_time, login_config.date_format); + } + WFIFOSET(fd,26); +#else WFIFOHEAD(fd,23); WFIFOW(fd,0) = 0x6a; WFIFOB(fd,2) = (uint8)result; if( result != 6 ) memset(WFIFOP(fd,3), '\0', 20); - else - {// 6 = Your are Prohibited to log in until %s + else { // 6 = Your are Prohibited to log in until %s struct mmo_account acc; time_t unban_time = ( accounts->load_str(accounts, &acc, sd->userid) ) ? acc.unban_time : 0; timestamp2string((char*)WFIFOP(fd,3), 20, unban_time, login_config.date_format); } WFIFOSET(fd,23); +#endif } @@ -1446,7 +1454,7 @@ int parse_login(int fd) login_auth_failed(sd, 3); // send "rejected from server" return 0; } - + result = mmo_auth(sd, false); if( result == -1 ) @@ -1555,7 +1563,6 @@ void login_set_defaults() login_config.ip_sync_interval = 0; login_config.log_login = true; safestrncpy(login_config.date_format, "%Y-%m-%d %H:%M:%S", sizeof(login_config.date_format)); - login_config.console = false; login_config.new_account_flag = true; login_config.new_acc_length_limit = true; login_config.use_md5_passwds = false; @@ -1596,7 +1603,7 @@ int login_config_read(const char* cfgName) continue; if(!strcmpi(w1,"timestamp_format")) - strncpy(timestamp_format, w2, 20); + safestrncpy(timestamp_format, w2, 20); else if(!strcmpi(w1,"stdout_with_ansisequence")) stdout_with_ansisequence = config_switch(w2); else if(!strcmpi(w1,"console_silent")) { @@ -1605,10 +1612,11 @@ int login_config_read(const char* cfgName) ShowInfo("Console Silent Setting: %d\n", atoi(w2)); } else if( !strcmpi(w1, "bind_ip") ) { - char ip_str[16]; login_config.login_ip = host2ip(w2); - if( login_config.login_ip ) + if( login_config.login_ip ) { + char ip_str[16]; ShowStatus("Login server binding IP address : %s -> %s\n", w2, ip2str(login_config.login_ip, ip_str)); + } } else if( !strcmpi(w1, "login_port") ) { login_config.login_port = (uint16)atoi(w2); @@ -1634,8 +1642,6 @@ int login_config_read(const char* cfgName) login_config.min_group_id_to_connect = atoi(w2); else if(!strcmpi(w1, "date_format")) safestrncpy(login_config.date_format, w2, sizeof(login_config.date_format)); - else if(!strcmpi(w1, "console")) - login_config.console = (bool)config_switch(w2); else if(!strcmpi(w1, "allowed_regs")) //account flood protection system allowed_regs = atoi(w2); else if(!strcmpi(w1, "time_allowed")) @@ -1653,10 +1659,10 @@ int login_config_read(const char* cfgName) else if(!strcmpi(w1, "client_hash")) { int group = 0; char md5[33]; - int i; if (sscanf(w2, "%d, %32s", &group, md5) == 2) { struct client_hash_node *nnode; + int i; CREATE(nnode, struct client_hash_node, 1); for (i = 0; i < 32; i += 2) { @@ -1778,9 +1784,8 @@ void do_abort(void) { } -void set_server_type(void) -{ - SERVER_TYPE = ATHENA_SERVER_LOGIN; +void set_server_type(void) { + SERVER_TYPE = SERVER_TYPE_LOGIN; } @@ -1862,22 +1867,21 @@ int do_init(int argc, char** argv) } } - if( login_config.console ) - { - //##TODO invoke a CONSOLE_START plugin event + // server port open & binding + if( (login_fd = make_listen_bind(login_config.login_ip,login_config.login_port)) == -1 ) { + ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",login_config.login_port); + exit(EXIT_FAILURE); } - - // server port open & binding - login_fd = make_listen_bind(login_config.login_ip, login_config.login_port); - if( runflag != CORE_ST_STOP ) - { + if( runflag != CORE_ST_STOP ) { shutdown_callback = do_shutdown; runflag = LOGINSERVER_ST_RUNNING; } + account_db_sql_up(accounts); + ShowStatus("The login-server is "CL_GREEN"ready"CL_RESET" (Server is listening on the port %u).\n\n", login_config.login_port); login_log(0, "login server", 100, "login server started"); - + return 0; } diff --git a/src/login/login.h b/src/login/login.h index 7ed556628..3cfea8bdc 100644 --- a/src/login/login.h +++ b/src/login/login.h @@ -68,7 +68,6 @@ struct Login_Config { unsigned int ip_sync_interval; // interval (in minutes) to execute a DNS/IP update (for dynamic IPs) bool log_login; // whether to log login server actions or not char date_format[32]; // date format used in messages - bool console; // console input system enabled? bool new_account_flag,new_acc_length_limit; // autoregistration via _M/_F ? / if yes minimum length is 4? int start_limited_time; // new account expiration time (-1: unlimited) bool use_md5_passwds; // work with password hashes instead of plaintext passwords? diff --git a/src/login/loginlog_sql.c b/src/login/loginlog_sql.c index d61172697..231ac783b 100644 --- a/src/login/loginlog_sql.c +++ b/src/login/loginlog_sql.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/mmo.h" @@ -37,16 +38,16 @@ unsigned long loginlog_failedattempts(uint32 ip, unsigned int minutes) if( !enabled ) return 0; - if( SQL_ERROR == Sql_Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `ip` = '%s' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE", + if( SQL_ERROR == SQL->Query(sql_handle, "SELECT count(*) FROM `%s` WHERE `ip` = '%s' AND `rcode` = '1' AND `time` > NOW() - INTERVAL %d MINUTE", log_login_db, ip2str(ip,NULL), minutes) )// how many times failed account? in one ip. Sql_ShowDebug(sql_handle); - if( SQL_SUCCESS == Sql_NextRow(sql_handle) ) + if( SQL_SUCCESS == SQL->NextRow(sql_handle) ) { char* data; - Sql_GetData(sql_handle, 0, &data, NULL); + SQL->GetData(sql_handle, 0, &data, NULL); failures = strtoul(data, NULL, 10); - Sql_FreeResult(sql_handle); + SQL->FreeResult(sql_handle); } return failures; } @@ -64,10 +65,10 @@ void login_log(uint32 ip, const char* username, int rcode, const char* message) if( !enabled ) return; - Sql_EscapeStringLen(sql_handle, esc_username, username, strnlen(username, NAME_LENGTH)); - Sql_EscapeStringLen(sql_handle, esc_message, message, strnlen(message, 255)); + SQL->EscapeStringLen(sql_handle, esc_username, username, strnlen(username, NAME_LENGTH)); + SQL->EscapeStringLen(sql_handle, esc_message, message, strnlen(message, 255)); - retcode = Sql_Query(sql_handle, + retcode = SQL->Query(sql_handle, "INSERT INTO `%s`(`time`,`ip`,`user`,`rcode`,`log`) VALUES (NOW(), '%s', '%s', '%d', '%s')", log_login_db, ip2str(ip,NULL), esc_username, rcode, esc_message); @@ -103,16 +104,16 @@ bool loginlog_init(void) codepage = global_codepage; } - sql_handle = Sql_Malloc(); + sql_handle = SQL->Malloc(); - if( SQL_ERROR == Sql_Connect(sql_handle, username, password, hostname, port, database) ) + if( SQL_ERROR == SQL->Connect(sql_handle, username, password, hostname, port, database) ) { Sql_ShowDebug(sql_handle); - Sql_Free(sql_handle); + SQL->Free(sql_handle); exit(EXIT_FAILURE); } - if( codepage[0] != '\0' && SQL_ERROR == Sql_SetEncoding(sql_handle, codepage) ) + if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) ) Sql_ShowDebug(sql_handle); enabled = true; @@ -122,7 +123,7 @@ bool loginlog_init(void) bool loginlog_final(void) { - Sql_Free(sql_handle); + SQL->Free(sql_handle); sql_handle = NULL; return true; } diff --git a/src/login/sql/CMakeLists.txt b/src/login/sql/CMakeLists.txt index 1355f17ee..46cf4db02 100644 --- a/src/login/sql/CMakeLists.txt +++ b/src/login/sql/CMakeLists.txt @@ -3,7 +3,7 @@ # login sql # if( BUILD_SQL_SERVERS ) -message( STATUS "Creating target login-server_sql" ) +message( STATUS "Creating target login-server" ) set( SQL_LOGIN_HEADERS "${SQL_LOGIN_SOURCE_DIR}/account.h" "${SQL_LOGIN_SOURCE_DIR}/ipban.h" @@ -24,16 +24,16 @@ set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_LOGIN_HEADE source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ) source_group( login FILES ${SQL_LOGIN_HEADERS} ${SQL_LOGIN_SOURCES} ) include_directories( ${INCLUDE_DIRS} ) -add_executable( login-server_sql ${SOURCE_FILES} ) -add_dependencies( login-server_sql ${DEPENDENCIES} ) -target_link_libraries( login-server_sql ${LIBRARIES} ${DEPENDENCIES} ) -set_target_properties( login-server_sql PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) +add_executable( login-server ${SOURCE_FILES} ) +add_dependencies( login-server ${DEPENDENCIES} ) +target_link_libraries( login-server ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( login-server PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_loginserver_sql DESCRIPTION "login-server (sql version)" DISPLAY_NAME "login-server_sql" GROUP Runtime ) - install( TARGETS login-server_sql + cpack_add_component( Runtime_loginserver_sql DESCRIPTION "login-server (sql version)" DISPLAY_NAME "login-server" GROUP Runtime ) + install( TARGETS login-server DESTINATION "." COMPONENT Runtime_loginserver_sql ) endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} login-server_sql CACHE INTERNAL "" ) -message( STATUS "Creating target login-server_sql - done" ) +set( TARGET_LIST ${TARGET_LIST} login-server CACHE INTERNAL "" ) +message( STATUS "Creating target login-server - done" ) endif( BUILD_SQL_SERVERS ) diff --git a/src/map/Makefile.in b/src/map/Makefile.in index 8e97221a7..bb99b6a05 100644 --- a/src/map/Makefile.in +++ b/src/map/Makefile.in @@ -17,7 +17,7 @@ MAP_OBJ = map.o chrif.o clif.o pc.o status.o npc.o \ storage.o skill.o atcommand.o battle.o battleground.o \ intif.o trade.o party.o vending.o guild.o pet.o \ log.o mail.o date.o unit.o homunculus.o mercenary.o quest.o instance.o \ - buyingstore.o searchstore.o duel.o pc_groups.o elemental.o + buyingstore.o searchstore.o duel.o pc_groups.o elemental.o irc-bot.o MAP_SQL_OBJ = $(MAP_OBJ:%=obj_sql/%) \ obj_sql/mapreg_sql.o MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ @@ -27,12 +27,12 @@ MAP_H = map.h chrif.h clif.h pc.h status.h npc.h \ log.h mail.h date.h unit.h homunculus.h mercenary.h quest.h instance.h mapreg.h \ buyingstore.h searchstore.h duel.h pc_groups.h \ ../config/core.h ../config/renewal.h ../config/secure.h ../config/const.h \ - ../config/classes/general.h elemental.h + ../config/classes/general.h elemental.h packets.h packets_struct.h irc-bot.h HAVE_MYSQL=@HAVE_MYSQL@ ifeq ($(HAVE_MYSQL),yes) ALL_DEPENDS=txt sql - SQL_DEPENDS=map-server_sql + SQL_DEPENDS=map-server else ALL_TARGET=txt SQL_DEPENDS=needs_mysql @@ -59,7 +59,7 @@ sql: $(SQL_DEPENDS) clean: @echo " CLEAN map" - @rm -rf *.o obj_txt obj_sql ../../map-server@EXEEXT@ ../../map-server_sql@EXEEXT@ + @rm -rf *.o obj_txt obj_sql ../../map-server@EXEEXT@ ../../map-server@EXEEXT@ help: ifeq ($(HAVE_MYSQL),yes) @@ -90,9 +90,9 @@ obj_sql: # executables -map-server_sql: obj_sql $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a +map-server: obj_sql $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a @echo " LD $@" - @@CC@ @LDFLAGS@ -o ../../map-server_sql@EXEEXT@ $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ + @@CC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_SQL_OBJ) ../common/obj_sql/common_sql.a ../common/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @PCRE_LIBS@ @MYSQL_LIBS@ # map object files diff --git a/src/map/atcommand.c b/src/map/atcommand.c index e54166019..d923027dd 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/mmo.h" @@ -43,43 +44,14 @@ #include "unit.h" #include "mapreg.h" #include "quest.h" +#include "searchstore.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <math.h> - -#define ATCOMMAND_LENGTH 50 -#define ACMD_FUNC(x) static int atcommand_ ## x (const int fd, struct map_session_data* sd, const char* command, const char* message) -#define MAX_MSG 1500 - - -typedef struct AtCommandInfo AtCommandInfo; -typedef struct AliasInfo AliasInfo; - -int atcmd_binding_count = 0; - -struct AtCommandInfo { - char command[ATCOMMAND_LENGTH]; - AtCommandFunc func; - char* at_groups;/* quick @commands "can-use" lookup */ - char* char_groups;/* quick @charcommands "can-use" lookup */ -}; - -struct AliasInfo { - AtCommandInfo *command; - char alias[ATCOMMAND_LENGTH]; -}; - - -char atcommand_symbol = '@'; // first char of the commands -char charcommand_symbol = '#'; - static char* msg_table[MAX_MSG]; // Server messages (0-499 reserved for GM commands, 500-999 reserved for others) -static DBMap* atcommand_db = NULL; //name -> AtCommandInfo -static DBMap* atcommand_alias_db = NULL; //alias -> AtCommandInfo -static config_t atcommand_config; static char atcmd_output[CHAT_SIZE_MAX]; static char atcmd_player_name[NAME_LENGTH]; @@ -92,12 +64,12 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n struct atcmd_binding_data* get_atcommandbind_byname(const char* name) { int i = 0; - if( *name == atcommand_symbol || *name == charcommand_symbol ) + if( *name == atcommand->at_symbol || *name == atcommand->char_symbol ) name++; // for backwards compatibility - ARR_FIND( 0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, name) == 0 ); + ARR_FIND( 0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, name) == 0 ); - return ( i < atcmd_binding_count ) ? atcmd_binding[i] : NULL; + return ( i < atcommand->binding_count ) ? atcommand->binding[i] : NULL; } //----------------------------------------------------------- @@ -169,107 +141,79 @@ void do_final_msg(void) /** * retrieves the help string associated with a given command. - * - * @param name the name of the command to retrieve help information for - * @return the string associated with the command, or NULL */ -static const char* atcommand_help_string(const char* command) -{ - const char* str = NULL; - config_setting_t* info; - - if( *command == atcommand_symbol || *command == charcommand_symbol ) - {// remove the prefix symbol for the raw name of the command - command ++; - } - - // convert alias to the real command name - command = atcommand_checkalias(command); - - // attept to find the first default help command - info = config_lookup(&atcommand_config, "help"); - - if( info == NULL ) - {// failed to find the help property in the configuration file - return NULL; - } - - if( !config_setting_lookup_string( info, command, &str ) ) - {// failed to find the matching help string - return NULL; - } - - // push the result from the method - return str; +static inline const char* atcommand_help_string(AtCommandInfo *info) { + return info->help; } + /*========================================== * @send (used for testing packet sends from the client) *------------------------------------------*/ -ACMD_FUNC(send) +ACMD(send) { int len=0,off,end,type; long num; - + // read message type as hex number (without the 0x) if(!message || !*message || - !((sscanf(message, "len %x", &type)==1 && (len=1)) - || sscanf(message, "%x", &type)==1) ) + !((sscanf(message, "len %x", &type)==1 && (len=1)) + || sscanf(message, "%x", &type)==1) ) { int i; for (i = 900; i <= 903; ++i) - clif_displaymessage(fd, msg_txt(i)); - return -1; + clif->message(fd, msg_txt(i)); + return false; } - + #define PARSE_ERROR(error,p) \ - {\ - clif_displaymessage(fd, (error));\ - sprintf(atcmd_output, ">%s", (p));\ - clif_displaymessage(fd, atcmd_output);\ - } -//define PARSE_ERROR - +{\ +clif->message(fd, (error));\ +sprintf(atcmd_output, ">%s", (p));\ +clif->message(fd, atcmd_output);\ +} + //define PARSE_ERROR + #define CHECK_EOS(p) \ - if(*(p) == 0){\ - clif_displaymessage(fd, "Unexpected end of string");\ - return -1;\ - } -//define CHECK_EOS - +if(*(p) == 0){\ +clif->message(fd, "Unexpected end of string");\ +return false;\ +} + //define CHECK_EOS + #define SKIP_VALUE(p) \ - {\ - while(*(p) && !ISSPACE(*(p))) ++(p); /* non-space */\ - while(*(p) && ISSPACE(*(p))) ++(p); /* space */\ - } -//define SKIP_VALUE - +{\ +while(*(p) && !ISSPACE(*(p))) ++(p); /* non-space */\ +while(*(p) && ISSPACE(*(p))) ++(p); /* space */\ +} + //define SKIP_VALUE + #define GET_VALUE(p,num) \ - {\ - if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\ - PARSE_ERROR("Invalid number in:",(p));\ - return -1;\ - }\ - } -//define GET_VALUE - +{\ +if(sscanf((p), "x%lx", &(num)) < 1 && sscanf((p), "%ld ", &(num)) < 1){\ +PARSE_ERROR("Invalid number in:",(p));\ +return false;\ +}\ +} + //define GET_VALUE + if (type > 0 && type < MAX_PACKET_DB) { - + if(len) {// show packet length - sprintf(atcmd_output, msg_txt(904), type, packet_db[sd->packet_ver][type].len); // Packet 0x%x length: %d - clif_displaymessage(fd, atcmd_output); - return 0; + sprintf(atcmd_output, msg_txt(904), type, packet_db[type].len); // Packet 0x%x length: %d + clif->message(fd, atcmd_output); + return true; } - - len=packet_db[sd->packet_ver][type].len; + + len=packet_db[type].len; off=2; if(len == 0) {// unknown packet - ERROR sprintf(atcmd_output, msg_txt(905), type); // Unknown packet: 0x%x - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } else if(len == -1) {// dynamic packet len=SHRT_MAX-4; // maximum length @@ -277,7 +221,7 @@ ACMD_FUNC(send) } WFIFOHEAD(fd, len); WFIFOW(fd,0)=TOW(type); - + // parse packet contents SKIP_VALUE(message); while(*message != 0 && off < len){ @@ -316,12 +260,12 @@ ACMD_FUNC(send) {// find start of string if(*message == 0 || ISSPACE(*message)){ PARSE_ERROR(msg_txt(906),message); // Not a string: - return -1; + return false; } ++message; } } - + // parse string ++message; CHECK_EOS(message); @@ -346,7 +290,7 @@ ACMD_FUNC(send) CHECK_EOS(message); if(!ISXDIGIT(*message)){ PARSE_ERROR(msg_txt(907),message); // Not a hexadecimal digit: - return -1; + return false; } num=(ISDIGIT(*message)?*message-'0':TOLOWER(*message)-'a'+10); if(ISXDIGIT(*message)){ @@ -399,7 +343,7 @@ ACMD_FUNC(send) ++message; CHECK_EOS(message); } - + // terminate the string if(off < end) {// fill the rest with 0's @@ -409,28 +353,26 @@ ACMD_FUNC(send) } else {// unknown PARSE_ERROR(msg_txt(908),message); // Unknown type of value in: - return -1; + return false; } SKIP_VALUE(message); } - - if(packet_db[sd->packet_ver][type].len == -1) - {// send dynamic packet + + if(packet_db[type].len == -1) {// send dynamic packet WFIFOW(fd,2)=TOW(off); WFIFOSET(fd,off); - } else - {// send static packet + } else {// send static packet if(off < len) memset(WFIFOP(fd,off),0,len-off); WFIFOSET(fd,len); } } else { - clif_displaymessage(fd, msg_txt(259)); // Invalid packet - return -1; + clif->message(fd, msg_txt(259)); // Invalid packet + return false; } sprintf (atcmd_output, msg_txt(258), type, type); // Sent packet 0x%x (%d) - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; #undef PARSE_ERROR #undef CHECK_EOS #undef SKIP_VALUE @@ -440,174 +382,174 @@ ACMD_FUNC(send) /*========================================== * @rura, @warp, @mapmove *------------------------------------------*/ -ACMD_FUNC(mapmove) +ACMD(mapmove) { char map_name[MAP_NAME_LENGTH_EXT]; unsigned short mapindex; short x = 0, y = 0; int16 m = -1; - + nullpo_retr(-1, sd); - + memset(map_name, '\0', sizeof(map_name)); - + if (!message || !*message || (sscanf(message, "%15s %hd %hd", map_name, &x, &y) < 3 && sscanf(message, "%15[^,],%hd,%hd", map_name, &x, &y) < 1)) { - - clif_displaymessage(fd, msg_txt(909)); // Please enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>). - return -1; - } - + + clif->message(fd, msg_txt(909)); // Please enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>). + return false; + } + mapindex = mapindex_name2id(map_name); if (mapindex) m = map_mapindex2mapid(mapindex); - + if (!mapindex) { // m < 0 means on different server! [Kevin] - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; + clif->message(fd, msg_txt(1)); // Map not found. + return false; } - - if ((x || y) && map_getcell(m, x, y, CELL_CHKNOPASS)) + + if ((x || y) && map_getcell(m, x, y, CELL_CHKNOPASS) && pc_get_group_level(sd) < battle_config.gm_ignore_warpable_area) { //This is to prevent the pc_setpos call from printing an error. - clif_displaymessage(fd, msg_txt(2)); + clif->message(fd, msg_txt(2)); if (!map_search_freecell(NULL, m, &x, &y, 10, 10, 1)) x = y = 0; //Invalid cell, use random spot. } if (map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(247)); - return -1; + clif->message(fd, msg_txt(247)); + return false; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); - return -1; + clif->message(fd, msg_txt(248)); + return false; } if (pc_setpos(sd, mapindex, x, y, CLR_TELEPORT) != 0) { - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; + clif->message(fd, msg_txt(1)); // Map not found. + return false; } - - clif_displaymessage(fd, msg_txt(0)); // Warped. - return 0; + + clif->message(fd, msg_txt(0)); // Warped. + return true; } /*========================================== * Displays where a character is. Corrected version by Silent. [Skotlex] *------------------------------------------*/ -ACMD_FUNC(where) +ACMD(where) { struct map_session_data* pl_sd; - + nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof atcmd_player_name); - + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(910)); // Please enter a player name (usage: @where <char name>). - return -1; + clif->message(fd, msg_txt(910)); // Please enter a player name (usage: @where <char name>). + return false; } - + pl_sd = map_nick2sd(atcmd_player_name); if (pl_sd == NULL || strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 || (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > pc_get_group_level(sd) && !pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) - ) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + ) { + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + snprintf(atcmd_output, sizeof atcmd_output, "%s %s %d %d", pl_sd->status.name, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, atcmd_output); - - return 0; + clif->message(fd, atcmd_output); + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(jumpto) +ACMD(jumpto) { struct map_session_data *pl_sd = NULL; - + nullpo_retr(-1, sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>). - return -1; + clif->message(fd, msg_txt(911)); // Please enter a player name (usage: @jumpto/@warpto/@goto <char name/ID>). + return false; } - + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(247)); // You are not authorized to warp to this map. - return -1; + clif->message(fd, msg_txt(247)); // You are not authorized to warp to this map. + return false; } - + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. - return -1; + clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map. + return false; } - + if( pc_isdead(sd) ) { - clif_displaymessage(fd, msg_txt(664)); - return -1; + clif->message(fd, msg_txt(664)); + return false; } - + pc_setpos(sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); sprintf(atcmd_output, msg_txt(4), pl_sd->status.name); // Jumped to %s - clif_displaymessage(fd, atcmd_output); - - return 0; + clif->message(fd, atcmd_output); + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(jump) +ACMD(jump) { short x = 0, y = 0; - + nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + sscanf(message, "%hd %hd", &x, &y); - + if (map[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. - return -1; + clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map. + return false; } - + if( pc_isdead(sd) ) { - clif_displaymessage(fd, msg_txt(664)); - return -1; + clif->message(fd, msg_txt(664)); + return false; } - + if ((x || y) && map_getcell(sd->bl.m, x, y, CELL_CHKNOPASS)) { //This is to prevent the pc_setpos call from printing an error. - clif_displaymessage(fd, msg_txt(2)); + clif->message(fd, msg_txt(2)); if (!map_search_freecell(NULL, sd->bl.m, &x, &y, 10, 10, 1)) x = y = 0; //Invalid cell, use random spot. } - + pc_setpos(sd, sd->mapindex, x, y, CLR_TELEPORT); sprintf(atcmd_output, msg_txt(5), sd->bl.x, sd->bl.y); // Jumped to %d %d - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } /*========================================== * Display list of online characters with * various info. *------------------------------------------*/ -ACMD_FUNC(who) +ACMD(who) { struct map_session_data *pl_sd = NULL; struct s_mapiterator *iter = NULL; @@ -623,93 +565,93 @@ ACMD_FUNC(who) */ int display_type = 1; int map_id = -1; - + nullpo_retr(-1, sd); - + if (strstr(command, "map") != NULL) { if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = map_mapname2mapid(map_name)) < 0) map_id = sd->bl.m; } else { sscanf(message, "%23s", player_name); } - + if (strstr(command, "2") != NULL) display_type = 2; else if (strstr(command, "3") != NULL) display_type = 3; - + level = pc_get_group_level(sd); - StringBuf_Init(&buf); - + StrBuf->Init(&buf); + iter = mapit_getallusers(); - for (pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter)) { + for (pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter)) { if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || (pl_sd->sc.option & OPTION_INVISIBLE)) && pc_get_group_level(pl_sd) > level)) { // you can look only lower or same level if (stristr(pl_sd->status.name, player_name) == NULL // search with no case sensitive || (map_id >= 0 && pl_sd->bl.m != map_id)) continue; switch (display_type) { case 2: { - StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " + StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " - StringBuf_Printf(&buf, msg_txt(347), pl_sd->status.base_level, pl_sd->status.job_level, - job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s" + StrBuf->Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " + StrBuf->Printf(&buf, msg_txt(347), pl_sd->status.base_level, pl_sd->status.job_level, + job_name(pl_sd->status.class_)); // "| Lv:%d/%d | Job: %s" break; } case 3: { if (pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID)) - StringBuf_Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) " - StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " + StrBuf->Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) " + StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " - StringBuf_Printf(&buf, msg_txt(348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d" + StrBuf->Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " + StrBuf->Printf(&buf, msg_txt(348), mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); // "| Location: %s %d %d" break; } default: { struct party_data *p = party_search(pl_sd->status.party_id); - struct guild *g = guild_search(pl_sd->status.guild_id); - - StringBuf_Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " + struct guild *g = pl_sd->guild; + + StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s " if (pc_get_group_id(pl_sd) > 0) // Player title, if exists - StringBuf_Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " + StrBuf->Printf(&buf, msg_txt(344), pc_group_id2name(pc_get_group_id(pl_sd))); // "(%s) " if (p != NULL) - StringBuf_Printf(&buf, msg_txt(345), p->party.name); // " | Party: '%s'" + StrBuf->Printf(&buf, msg_txt(345), p->party.name); // " | Party: '%s'" if (g != NULL) - StringBuf_Printf(&buf, msg_txt(346), g->name); // " | Guild: '%s'" + StrBuf->Printf(&buf, msg_txt(346), g->name); // " | Guild: '%s'" break; } } - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Clear(&buf); + clif->message(fd, StrBuf->Value(&buf)); + StrBuf->Clear(&buf); count++; } } - mapit_free(iter); - + mapit->free(iter); + if (map_id < 0) { if (count == 0) - StringBuf_Printf(&buf, msg_txt(28)); // No player found. + StrBuf->Printf(&buf, msg_txt(28)); // No player found. else if (count == 1) - StringBuf_Printf(&buf, msg_txt(29)); // 1 player found. + StrBuf->Printf(&buf, msg_txt(29)); // 1 player found. else - StringBuf_Printf(&buf, msg_txt(30), count); // %d players found. + StrBuf->Printf(&buf, msg_txt(30), count); // %d players found. } else { if (count == 0) - StringBuf_Printf(&buf, msg_txt(54), map[map_id].name); // No player found in map '%s'. + StrBuf->Printf(&buf, msg_txt(54), map[map_id].name); // No player found in map '%s'. else if (count == 1) - StringBuf_Printf(&buf, msg_txt(55), map[map_id].name); // 1 player found in map '%s'. + StrBuf->Printf(&buf, msg_txt(55), map[map_id].name); // 1 player found in map '%s'. else - StringBuf_Printf(&buf, msg_txt(56), count, map[map_id].name); // %d players found in map '%s'. + StrBuf->Printf(&buf, msg_txt(56), count, map[map_id].name); // %d players found in map '%s'. } - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); - return 0; + clif->message(fd, StrBuf->Value(&buf)); + StrBuf->Destroy(&buf); + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(whogm) +ACMD(whogm) { struct map_session_data* pl_sd; struct s_mapiterator* iter; @@ -719,28 +661,28 @@ ACMD_FUNC(whogm) char player_name[NAME_LENGTH]; struct guild *g; struct party_data *p; - + nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(match_text, '\0', sizeof(match_text)); memset(player_name, '\0', sizeof(player_name)); - + if (sscanf(message, "%199[^\n]", match_text) < 1) strcpy(match_text, ""); for (j = 0; match_text[j]; j++) match_text[j] = TOLOWER(match_text[j]); - + count = 0; level = pc_get_group_level(sd); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { pl_level = pc_get_group_level(pl_sd); if (!pl_level) continue; - + if (match_text[0]) { memcpy(player_name, pl_sd->status.name, NAME_LENGTH); @@ -754,420 +696,435 @@ ACMD_FUNC(whogm) if (pl_sd->sc.option & OPTION_INVISIBLE) continue; sprintf(atcmd_output, msg_txt(913), pl_sd->status.name); // Name: %s (GM) - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); count++; continue; } - + sprintf(atcmd_output, msg_txt(914), // Name: %s (GM:%d) | Location: %s %d %d - pl_sd->status.name, pl_level, - mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, atcmd_output); - + pl_sd->status.name, pl_level, + mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y); + clif->message(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(915), // BLvl: %d | Job: %s (Lvl: %d) - pl_sd->status.base_level, - job_name(pl_sd->status.class_), pl_sd->status.job_level); - clif_displaymessage(fd, atcmd_output); - + pl_sd->status.base_level, + job_name(pl_sd->status.class_), pl_sd->status.job_level); + clif->message(fd, atcmd_output); + p = party_search(pl_sd->status.party_id); - g = guild_search(pl_sd->status.guild_id); - + g = pl_sd->guild; + sprintf(atcmd_output,msg_txt(916), // Party: '%s' | Guild: '%s' - p?p->party.name:msg_txt(917), g?g->name:msg_txt(917)); // None. - - clif_displaymessage(fd, atcmd_output); + p?p->party.name:msg_txt(917), g?g->name:msg_txt(917)); // None. + + clif->message(fd, atcmd_output); count++; } - mapit_free(iter); - + mapit->free(iter); + if (count == 0) - clif_displaymessage(fd, msg_txt(150)); // No GM found. + clif->message(fd, msg_txt(150)); // No GM found. else if (count == 1) - clif_displaymessage(fd, msg_txt(151)); // 1 GM found. + clif->message(fd, msg_txt(151)); // 1 GM found. else { sprintf(atcmd_output, msg_txt(152), count); // %d GMs found. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(save) +ACMD(save) { nullpo_retr(-1, sd); - + pc_setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y); if (sd->status.pet_id > 0 && sd->pd) intif_save_petdata(sd->status.account_id, &sd->pd->pet); - + chrif_save(sd,0); - - clif_displaymessage(fd, msg_txt(6)); // Your save point has been changed. - - return 0; + + clif->message(fd, msg_txt(6)); // Your save point has been changed. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(load) +ACMD(load) { int16 m; - + nullpo_retr(-1, sd); - + m = map_mapindex2mapid(sd->status.save_point.map); if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(249)); // You are not authorized to warp to your save map. - return -1; + clif->message(fd, msg_txt(249)); // You are not authorized to warp to your save map. + return false; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); // You are not authorized to warp from your current map. - return -1; + clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map. + return false; } - + pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT); - clif_displaymessage(fd, msg_txt(7)); // Warping to save point.. - - return 0; + clif->message(fd, msg_txt(7)); // Warping to save point.. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(speed) +ACMD(speed) { int speed; - + nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%d", &speed) < 1) { sprintf(atcmd_output, msg_txt(918), MIN_WALK_SPEED, MAX_WALK_SPEED); // Please enter a speed value (usage: @speed <%d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; + } + + if (speed < 0) { + sd->base_status.speed = DEFAULT_WALK_SPEED; + sd->state.permanent_speed = 0; // Remove lock when set back to default speed. + } else { + sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); + sd->state.permanent_speed = 1; // Set lock when set to non-default speed. } - - sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED); status_calc_bl(&sd->bl, SCB_SPEED); - clif_displaymessage(fd, msg_txt(8)); // Speed changed. - return 0; + clif->message(fd, msg_txt(8)); // Speed changed. + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(storage) +ACMD(storage) { nullpo_retr(-1, sd); - + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag) - return -1; - + return false; + if (storage_storageopen(sd) == 1) { //Already open. - clif_displaymessage(fd, msg_txt(250)); - return -1; + clif->message(fd, msg_txt(250)); + return false; } - - clif_displaymessage(fd, msg_txt(919)); // Storage opened. - - return 0; + + clif->message(fd, msg_txt(919)); // Storage opened. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(guildstorage) +ACMD(guildstorage) { nullpo_retr(-1, sd); - + if (!sd->status.guild_id) { - clif_displaymessage(fd, msg_txt(252)); - return -1; + clif->message(fd, msg_txt(252)); + return false; } - + if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading) - return -1; - + return false; + if (sd->state.storage_flag == 1) { - clif_displaymessage(fd, msg_txt(250)); - return -1; + clif->message(fd, msg_txt(250)); + return false; } - + if (sd->state.storage_flag == 2) { - clif_displaymessage(fd, msg_txt(251)); - return -1; + clif->message(fd, msg_txt(251)); + return false; } - + storage_guild_storageopen(sd); - clif_displaymessage(fd, msg_txt(920)); // Guild storage opened. - return 0; + clif->message(fd, msg_txt(920)); // Guild storage opened. + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(option) +ACMD(option) { int param1 = 0, param2 = 0, param3 = 0; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%d %d %d", ¶m1, ¶m2, ¶m3) < 1 || param1 < 0 || param2 < 0 || param3 < 0) {// failed to match the parameters so inform the user of the options - const char* text = NULL; - + const char* text; + // attempt to find the setting information for this command - text = atcommand_help_string( command ); - + text = atcommand_help_string( info ); + // notify the user of the requirement to enter an option - clif_displaymessage(fd, msg_txt(921)); // Please enter at least one option. - - if( text ) - {// send the help text associated with this command - clif_displaymessage( fd, text ); + clif->message(fd, msg_txt(921)); // Please enter at least one option. + + if( text ) {// send the help text associated with this command + clif->messageln( fd, text ); } - - return -1; + + return false; } - + sd->sc.opt1 = param1; sd->sc.opt2 = param2; pc_setoption(sd, param3); - - clif_displaymessage(fd, msg_txt(9)); // Options changed. - - return 0; + + clif->message(fd, msg_txt(9)); // Options changed. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(hide) +ACMD(hide) { nullpo_retr(-1, sd); if (sd->sc.option & OPTION_INVISIBLE) { sd->sc.option &= ~OPTION_INVISIBLE; - if (sd->disguise) + if (sd->disguise != -1 ) status_set_viewdata(&sd->bl, sd->disguise); else status_set_viewdata(&sd->bl, sd->status.class_); - clif_displaymessage(fd, msg_txt(10)); // Invisible: Off - + clif->message(fd, msg_txt(10)); // Invisible: Off + // increment the number of pvp players on the map map[sd->bl.m].users_pvp++; - + if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank ) {// register the player for ranking calculations sd->pvp_timer = add_timer( gettick() + 200, pc_calc_pvprank_timer, sd->bl.id, 0 ); } //bugreport:2266 - map_foreachinmovearea(clif_insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl); + map_foreachinmovearea(clif->insight, &sd->bl, AREA_SIZE, sd->bl.x, sd->bl.y, BL_ALL, &sd->bl); } else { sd->sc.option |= OPTION_INVISIBLE; sd->vd.class_ = INVISIBLE_CLASS; - clif_displaymessage(fd, msg_txt(11)); // Invisible: On - + clif->message(fd, msg_txt(11)); // Invisible: On + // decrement the number of pvp players on the map map[sd->bl.m].users_pvp--; - + if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {// unregister the player for ranking delete_timer( sd->pvp_timer, pc_calc_pvprank_timer ); sd->pvp_timer = INVALID_TIMER; } } - clif_changeoption(&sd->bl); - - return 0; + clif->changeoption(&sd->bl); + + return true; } /*========================================== * Changes a character's class *------------------------------------------*/ -ACMD_FUNC(jobchange) +ACMD(jobchange) { int job = 0, upper = 0; const char* text; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) { - int i, found = 0; - - for (i = JOB_NOVICE; i < JOB_MAX; ++i) { - if (strncmpi(message, job_name(i), 16) == 0) { - job = i; - upper = 0; - found = 1; - break; + int i; + bool found = false; + + upper = 0; + + // Normal Jobs + for( i = JOB_NOVICE; i < JOB_MAX_BASIC && !found; i++ ){ + if (strncmpi(message, job_name(i), 16) == 0) { + job = i; + found = true; } } - + + // High Jobs, Babys and Third + for( i = JOB_NOVICE_HIGH; i < JOB_MAX && !found; i++ ){ + if (strncmpi(message, job_name(i), 16) == 0) { + job = i; + found = true; + } + } + if (!found) { - text = atcommand_help_string(command); + text = atcommand_help_string(info); if (text) - clif_displaymessage(fd, text); - return -1; + clif->messageln(fd, text); + return false; } } - + if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2 || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2 || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2 || job == JOB_STAR_GLADIATOR2 - || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2) - ) // Deny direct transformation into dummy jobs - {clif_displaymessage(fd, msg_txt(923)); //"You can not change to this job by command." - return 0;} - + || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2) + ) // Deny direct transformation into dummy jobs + {clif->message(fd, msg_txt(923)); //"You can not change to this job by command." + return true;} + if (pcdb_checkid(job)) { if (pc_jobchange(sd, job, upper) == 0) - clif_displaymessage(fd, msg_txt(12)); // Your job has been changed. + clif->message(fd, msg_txt(12)); // Your job has been changed. else { - clif_displaymessage(fd, msg_txt(155)); // You are unable to change your job. - return -1; + clif->message(fd, msg_txt(155)); // You are unable to change your job. + return false; } } else { - text = atcommand_help_string(command); + text = atcommand_help_string(info); if (text) - clif_displaymessage(fd, text); - return -1; + clif->messageln(fd, text); + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(kill) +ACMD(kill) { nullpo_retr(-1, sd); status_kill(&sd->bl); - clif_displaymessage(sd->fd, msg_txt(13)); // A pity! You've died. + clif->message(sd->fd, msg_txt(13)); // A pity! You've died. if (fd != sd->fd) - clif_displaymessage(fd, msg_txt(14)); // Character killed. - return 0; + clif->message(fd, msg_txt(14)); // Character killed. + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(alive) +ACMD(alive) { nullpo_retr(-1, sd); if (!status_revive(&sd->bl, 100, 100)) { - clif_displaymessage(fd, msg_txt(667)); - return -1; + clif->message(fd, msg_txt(667)); + return false; } - clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); - clif_displaymessage(fd, msg_txt(16)); // You've been revived! It's a miracle! - return 0; + clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); + clif->message(fd, msg_txt(16)); // You've been revived! It's a miracle! + return true; } /*========================================== * +kamic [LuzZza] *------------------------------------------*/ -ACMD_FUNC(kami) +ACMD(kami) { unsigned long color=0; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if(*(command + 5) != 'c' && *(command + 5) != 'C') { if (!message || !*message) { - clif_displaymessage(fd, msg_txt(980)); // Please enter a message (usage: @kami <message>). - return -1; + clif->message(fd, msg_txt(980)); // Please enter a message (usage: @kami <message>). + return false; } - + sscanf(message, "%199[^\n]", atcmd_output); if (strstr(command, "l") != NULL) - clif_broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); + clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); else intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, (*(command + 5) == 'b' || *(command + 5) == 'B') ? 0x10 : 0); } else { if(!message || !*message || (sscanf(message, "%lx %199[^\n]", &color, atcmd_output) < 2)) { - clif_displaymessage(fd, msg_txt(981)); // Please enter color and message (usage: @kamic <color> <message>). - return -1; + clif->message(fd, msg_txt(981)); // Please enter color and message (usage: @kamic <color> <message>). + return false; } - + if(color > 0xFFFFFF) { - clif_displaymessage(fd, msg_txt(982)); // Invalid color. - return -1; + clif->message(fd, msg_txt(982)); // Invalid color. + return false; } intif_broadcast2(atcmd_output, strlen(atcmd_output) + 1, color, 0x190, 12, 0, 0); } - return 0; + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(heal) +ACMD(heal) { int hp = 0, sp = 0; // [Valaris] thanks to fov nullpo_retr(-1, sd); - + sscanf(message, "%d %d", &hp, &sp); - + // some overflow checks if( hp == INT_MIN ) hp++; if( sp == INT_MIN ) sp++; - + if ( hp == 0 && sp == 0 ) { if (!status_percent_heal(&sd->bl, 100, 100)) - clif_displaymessage(fd, msg_txt(157)); // HP and SP have already been recovered. + clif->message(fd, msg_txt(157)); // HP and SP have already been recovered. else - clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered. - return 0; + clif->message(fd, msg_txt(17)); // HP, SP recovered. + return true; } - + if ( hp > 0 && sp >= 0 ) { if(!status_heal(&sd->bl, hp, sp, 0)) - clif_displaymessage(fd, msg_txt(157)); // HP and SP are already with the good value. + clif->message(fd, msg_txt(157)); // HP and SP are already with the good value. else - clif_displaymessage(fd, msg_txt(17)); // HP, SP recovered. - return 0; + clif->message(fd, msg_txt(17)); // HP, SP recovered. + return true; } - + if ( hp < 0 && sp <= 0 ) { status_damage(NULL, &sd->bl, -hp, -sp, 0, 0); - clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); - clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified. - return 0; + clif->damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); + clif->message(fd, msg_txt(156)); // HP or/and SP modified. + return true; } - + //Opposing signs. if ( hp ) { if (hp > 0) status_heal(&sd->bl, hp, 0, 0); else { status_damage(NULL, &sd->bl, -hp, 0, 0, 0); - clif_damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); + clif->damage(&sd->bl,&sd->bl, gettick(), 0, 0, -hp, 0, 4, 0); } } - + if ( sp ) { if (sp > 0) status_heal(&sd->bl, 0, sp, 0); else status_damage(NULL, &sd->bl, 0, -sp, 0, 0); } - - clif_displaymessage(fd, msg_txt(156)); // HP or/and SP modified. - return 0; + + clif->message(fd, msg_txt(156)); // HP or/and SP modified. + return true; } /*========================================== * @item command (usage: @item <name/id_of_item> <quantity>) (modified by [Yor] for pet_egg) *------------------------------------------*/ -ACMD_FUNC(item) +ACMD(item) { char item_name[100]; int number = 0, item_id, flag = 0; @@ -1175,54 +1132,54 @@ ACMD_FUNC(item) struct item_data *item_data; int get_count, i; nullpo_retr(-1, sd); - + memset(item_name, '\0', sizeof(item_name)); - + if (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 && - sscanf(message, "%99s %d", item_name, &number) < 1 - )) { - clif_displaymessage(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>). - return -1; + sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 && + sscanf(message, "%99s %d", item_name, &number) < 1 + )) { + clif->message(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>). + return false; } - + if (number <= 0) number = 1; - + if ((item_data = itemdb_searchname(item_name)) == NULL && (item_data = itemdb_exists(atoi(item_name))) == NULL) { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; + clif->message(fd, msg_txt(19)); // Invalid item ID or name. + return false; } - + item_id = item_data->nameid; get_count = number; //Check if it's stackable. if (!itemdb_isstackable2(item_data)) get_count = 1; - + for (i = 0; i < number; i += get_count) { // if not pet egg if (!pet_create_egg(sd, item_id)) { memset(&item_tmp, 0, sizeof(item_tmp)); item_tmp.nameid = item_id; item_tmp.identify = 1; - + if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND))) - clif_additem(sd, 0, 0, flag); + clif->additem(sd, 0, 0, flag); } } - + if (flag == 0) - clif_displaymessage(fd, msg_txt(18)); // Item created. - return 0; + clif->message(fd, msg_txt(18)); // Item created. + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(item2) +ACMD(item2) { struct item item_tmp; struct item_data *item_data; @@ -1230,30 +1187,30 @@ ACMD_FUNC(item2) int item_id, number = 0; int identify = 0, refine = 0, attr = 0; int c1 = 0, c2 = 0, c3 = 0, c4 = 0; - int flag = 0; - int loop, get_count, i; nullpo_retr(-1, sd); - + memset(item_name, '\0', sizeof(item_name)); - + if (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 && - sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 - )) { - clif_displaymessage(fd, msg_txt(984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity> - clif_displaymessage(fd, msg_txt(985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>). - return -1; + sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 && + sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 + )) { + clif->message(fd, msg_txt(984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity> + clif->message(fd, msg_txt(985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>). + return false; } - + if (number <= 0) number = 1; - + item_id = 0; if ((item_data = itemdb_searchname(item_name)) != NULL || (item_data = itemdb_exists(atoi(item_name))) != NULL) item_id = item_data->nameid; - + if (item_id > 500) { + int flag = 0; + int loop, get_count, i; loop = 1; get_count = number; if (item_data->type == IT_WEAPON || item_data->type == IT_ARMOR || @@ -1283,70 +1240,70 @@ ACMD_FUNC(item2) item_tmp.card[2] = c3; item_tmp.card[3] = c4; if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND))) - clif_additem(sd, 0, 0, flag); + clif->additem(sd, 0, 0, flag); } - + if (flag == 0) - clif_displaymessage(fd, msg_txt(18)); // Item created. + clif->message(fd, msg_txt(18)); // Item created. } else { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; + clif->message(fd, msg_txt(19)); // Invalid item ID or name. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(itemreset) +ACMD(itemreset) { int i; nullpo_retr(-1, sd); - + for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) { pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_COMMAND); } } - clif_displaymessage(fd, msg_txt(20)); // All of your items have been removed. - - return 0; + clif->message(fd, msg_txt(20)); // All of your items have been removed. + + return true; } /*========================================== * Atcommand @lvlup *------------------------------------------*/ -ACMD_FUNC(baselevelup) +ACMD(baselevelup) { int level=0, i=0, status_point=0; nullpo_retr(-1, sd); level = atoi(message); - + if (!message || !*message || !level) { - clif_displaymessage(fd, msg_txt(986)); // Please enter a level adjustment (usage: @lvup/@blevel/@baselvlup <number of levels>). - return -1; + clif->message(fd, msg_txt(986)); // Please enter a level adjustment (usage: @lvup/@blevel/@baselvlup <number of levels>). + return false; } - + if (level > 0) { if (sd->status.base_level >= pc_maxbaselv(sd)) { // check for max level by Valaris - clif_displaymessage(fd, msg_txt(47)); // Base level can't go any higher. - return -1; + clif->message(fd, msg_txt(47)); // Base level can't go any higher. + return false; } // End Addition if ((unsigned int)level > pc_maxbaselv(sd) || (unsigned int)level > pc_maxbaselv(sd) - sd->status.base_level) // fix positiv overflow level = pc_maxbaselv(sd) - sd->status.base_level; for (i = 0; i < level; i++) status_point += pc_gets_status_point(sd->status.base_level + i); - + sd->status.status_point += status_point; sd->status.base_level += (unsigned int)level; status_percent_heal(&sd->bl, 100, 100); - clif_misceffect(&sd->bl, 0); - clif_displaymessage(fd, msg_txt(21)); // Base level raised. + clif->misceffect(&sd->bl, 0); + clif->message(fd, msg_txt(21)); // Base level raised. } else { if (sd->status.base_level == 1) { - clif_displaymessage(fd, msg_txt(158)); // Base level can't go any lower. - return -1; + clif->message(fd, msg_txt(158)); // Base level can't go any lower. + return false; } level*=-1; if ((unsigned int)level >= sd->status.base_level) @@ -1360,49 +1317,49 @@ ACMD_FUNC(baselevelup) else sd->status.status_point -= status_point; sd->status.base_level -= (unsigned int)level; - clif_displaymessage(fd, msg_txt(22)); // Base level lowered. + clif->message(fd, msg_txt(22)); // Base level lowered. } sd->status.base_exp = 0; - clif_updatestatus(sd, SP_STATUSPOINT); - clif_updatestatus(sd, SP_BASELEVEL); - clif_updatestatus(sd, SP_BASEEXP); - clif_updatestatus(sd, SP_NEXTBASEEXP); + clif->updatestatus(sd, SP_STATUSPOINT); + clif->updatestatus(sd, SP_BASELEVEL); + clif->updatestatus(sd, SP_BASEEXP); + clif->updatestatus(sd, SP_NEXTBASEEXP); status_calc_pc(sd, 0); pc_baselevelchanged(sd); if(sd->status.party_id) party_send_levelup(sd); - return 0; + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(joblevelup) +ACMD(joblevelup) { int level=0; nullpo_retr(-1, sd); - + level = atoi(message); - + if (!message || !*message || !level) { - clif_displaymessage(fd, msg_txt(987)); // Please enter a level adjustment (usage: @joblvup/@jlevel/@joblvlup <number of levels>). - return -1; + clif->message(fd, msg_txt(987)); // Please enter a level adjustment (usage: @joblvup/@jlevel/@joblvlup <number of levels>). + return false; } if (level > 0) { if (sd->status.job_level >= pc_maxjoblv(sd)) { - clif_displaymessage(fd, msg_txt(23)); // Job level can't go any higher. - return -1; + clif->message(fd, msg_txt(23)); // Job level can't go any higher. + return false; } if ((unsigned int)level > pc_maxjoblv(sd) || (unsigned int)level > pc_maxjoblv(sd) - sd->status.job_level) // fix positiv overflow level = pc_maxjoblv(sd) - sd->status.job_level; sd->status.job_level += (unsigned int)level; sd->status.skill_point += level; - clif_misceffect(&sd->bl, 1); - clif_displaymessage(fd, msg_txt(24)); // Job level raised. + clif->misceffect(&sd->bl, 1); + clif->message(fd, msg_txt(24)); // Job level raised. } else { if (sd->status.job_level == 1) { - clif_displaymessage(fd, msg_txt(159)); // Job level can't go any lower. - return -1; + clif->message(fd, msg_txt(159)); // Job level can't go any lower. + return false; } level *=-1; if ((unsigned int)level >= sd->status.job_level) // fix negativ overflow @@ -1414,87 +1371,81 @@ ACMD_FUNC(joblevelup) sd->status.skill_point = 0; else sd->status.skill_point -= level; - clif_displaymessage(fd, msg_txt(25)); // Job level lowered. + clif->message(fd, msg_txt(25)); // Job level lowered. } sd->status.job_exp = 0; - clif_updatestatus(sd, SP_JOBLEVEL); - clif_updatestatus(sd, SP_JOBEXP); - clif_updatestatus(sd, SP_NEXTJOBEXP); - clif_updatestatus(sd, SP_SKILLPOINT); + clif->updatestatus(sd, SP_JOBLEVEL); + clif->updatestatus(sd, SP_JOBEXP); + clif->updatestatus(sd, SP_NEXTJOBEXP); + clif->updatestatus(sd, SP_SKILLPOINT); status_calc_pc(sd, 0); - - return 0; + + return true; } /*========================================== * @help *------------------------------------------*/ -ACMD_FUNC(help) -{ - config_setting_t *help; - const char *text = NULL; +ACMD(help) { const char *command_name = NULL; char *default_command = "help"; - + AtCommandInfo *tinfo = NULL; + nullpo_retr(-1, sd); - - help = config_lookup(&atcommand_config, "help"); - if (help == NULL) { - clif_displaymessage(fd, msg_txt(27)); // "Commands help is not available." - return -1; - } - + if (!message || !*message) { command_name = default_command; // If no command_name specified, display help for @help. } else { - if (*message == atcommand_symbol || *message == charcommand_symbol) + if (*message == atcommand->at_symbol || *message == atcommand->char_symbol) ++message; command_name = atcommand_checkalias(message); } - - if (!pc_can_use_command(sd, command_name, COMMAND_ATCOMMAND)) { + + if (!atcommand->can_use2(sd, command_name, COMMAND_ATCOMMAND)) { sprintf(atcmd_output, msg_txt(153), message); // "%s is Unknown Command" - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); atcommand_get_suggestions(sd, command_name, true); - return -1; + return false; } - - if (!config_setting_lookup_string(help, command_name, &text)) { - sprintf(atcmd_output, msg_txt(988), atcommand_symbol, command_name); // There is no help for %c%s. - clif_displaymessage(fd, atcmd_output); + + tinfo = get_atcommandinfo_byname(atcommand_checkalias(command_name)); + + if ( !tinfo || tinfo->help == NULL ) { + sprintf(atcmd_output, msg_txt(988), atcommand->at_symbol, command_name); // There is no help for %c%s. + clif->message(fd, atcmd_output); atcommand_get_suggestions(sd, command_name, true); - return -1; + return false; } - - sprintf(atcmd_output, msg_txt(989), atcommand_symbol, command_name); // Help for command %c%s: - clif_displaymessage(fd, atcmd_output); - + + sprintf(atcmd_output, msg_txt(989), atcommand->at_symbol, command_name); // Help for command %c%s: + clif->message(fd, atcmd_output); + { // Display aliases DBIterator* iter; AtCommandInfo *command_info; AliasInfo *alias_info = NULL; StringBuf buf; bool has_aliases = false; - - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, msg_txt(990)); // Available aliases: + + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, msg_txt(990)); // Available aliases: command_info = get_atcommandinfo_byname(command_name); - iter = db_iterator(atcommand_alias_db); + iter = db_iterator(atcommand->alias_db); for (alias_info = dbi_first(iter); dbi_exists(iter); alias_info = dbi_next(iter)) { if (alias_info->command == command_info) { - StringBuf_Printf(&buf, " %s", alias_info->alias); + StrBuf->Printf(&buf, " %s", alias_info->alias); has_aliases = true; } } dbi_destroy(iter); if (has_aliases) - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); + clif->message(fd, StrBuf->Value(&buf)); + StrBuf->Destroy(&buf); } - + // Display help contents - clif_displaymessage(fd, text); - return 0; + clif->message(fd, tinfo->help); + return true; } // helper function, used in foreach calls to stop auto-attack timers @@ -1516,7 +1467,7 @@ static int atcommand_stopattack(struct block_list *bl,va_list ap) static int atcommand_pvpoff_sub(struct block_list *bl,va_list ap) { TBL_PC* sd = (TBL_PC*)bl; - clif_pvpset(sd, 0, 0, 2); + clif->pvpset(sd, 0, 0, 2); if (sd->pvp_timer != INVALID_TIMER) { delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); sd->pvp_timer = INVALID_TIMER; @@ -1524,23 +1475,26 @@ static int atcommand_pvpoff_sub(struct block_list *bl,va_list ap) return 0; } -ACMD_FUNC(pvpoff) +ACMD(pvpoff) { nullpo_retr(-1, sd); - + if (!map[sd->bl.m].flag.pvp) { - clif_displaymessage(fd, msg_txt(160)); // PvP is already Off. - return -1; + clif->message(fd, msg_txt(160)); // PvP is already Off. + return false; } - + + map_zone_change2(sd->bl.m,map[sd->bl.m].prev_zone); map[sd->bl.m].flag.pvp = 0; - - if (!battle_config.pk_mode) - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); + + if (!battle_config.pk_mode) { + clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); + clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP); + } map_foreachinmap(atcommand_pvpoff_sub,sd->bl.m, BL_PC); map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); - clif_displaymessage(fd, msg_txt(31)); // PvP: Off. - return 0; + clif->message(fd, msg_txt(31)); // PvP: Off. + return true; } /*========================================== @@ -1560,190 +1514,195 @@ static int atcommand_pvpon_sub(struct block_list *bl,va_list ap) return 0; } -ACMD_FUNC(pvpon) +ACMD(pvpon) { nullpo_retr(-1, sd); - + if (map[sd->bl.m].flag.pvp) { - clif_displaymessage(fd, msg_txt(161)); // PvP is already On. - return -1; + clif->message(fd, msg_txt(161)); // PvP is already On. + return false; } - + + map_zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_PVP_NAME)); map[sd->bl.m].flag.pvp = 1; - - if (!battle_config.pk_mode) - {// display pvp circle and rank - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE); + + if (!battle_config.pk_mode) {// display pvp circle and rank + clif->map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE); + clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP); map_foreachinmap(atcommand_pvpon_sub,sd->bl.m, BL_PC); } - - clif_displaymessage(fd, msg_txt(32)); // PvP: On. - - return 0; + + clif->message(fd, msg_txt(32)); // PvP: On. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(gvgoff) +ACMD(gvgoff) { nullpo_retr(-1, sd); - + if (!map[sd->bl.m].flag.gvg) { - clif_displaymessage(fd, msg_txt(162)); // GvG is already Off. - return -1; + clif->message(fd, msg_txt(162)); // GvG is already Off. + return false; } - + + map_zone_change2(sd->bl.m,map[sd->bl.m].prev_zone); map[sd->bl.m].flag.gvg = 0; - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); + clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING); + clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP); map_foreachinmap(atcommand_stopattack,sd->bl.m, BL_CHAR, 0); - clif_displaymessage(fd, msg_txt(33)); // GvG: Off. - - return 0; + clif->message(fd, msg_txt(33)); // GvG: Off. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(gvgon) +ACMD(gvgon) { nullpo_retr(-1, sd); - + if (map[sd->bl.m].flag.gvg) { - clif_displaymessage(fd, msg_txt(163)); // GvG is already On. - return -1; + clif->message(fd, msg_txt(163)); // GvG is already On. + return false; } - + + map_zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_GVG_NAME)); map[sd->bl.m].flag.gvg = 1; - clif_map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE); - clif_displaymessage(fd, msg_txt(34)); // GvG: On. - - return 0; + clif->map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE); + clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP); + clif->message(fd, msg_txt(34)); // GvG: On. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(model) +ACMD(model) { int hair_style = 0, hair_color = 0, cloth_color = 0; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%d %d %d", &hair_style, &hair_color, &cloth_color) < 1) { sprintf(atcmd_output, msg_txt(991), // Please enter at least one value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>). MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR, MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE && hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR && cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { - pc_changelook(sd, LOOK_HAIR, hair_style); - pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); - pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + pc_changelook(sd, LOOK_HAIR, hair_style); + pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); + pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); + clif->message(fd, msg_txt(36)); // Appearence changed. } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; + clif->message(fd, msg_txt(37)); // An invalid number was specified. + return false; } - - return 0; + + return true; } /*========================================== * @dye && @ccolor *------------------------------------------*/ -ACMD_FUNC(dye) +ACMD(dye) { int cloth_color = 0; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1) { sprintf(atcmd_output, msg_txt(992), MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); // Please enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) { pc_changelook(sd, LOOK_CLOTHES_COLOR, cloth_color); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + clif->message(fd, msg_txt(36)); // Appearence changed. } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; + clif->message(fd, msg_txt(37)); // An invalid number was specified. + return false; } - - return 0; + + return true; } /*========================================== * @hairstyle && @hstyle *------------------------------------------*/ -ACMD_FUNC(hair_style) +ACMD(hair_style) { int hair_style = 0; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%d", &hair_style) < 1) { sprintf(atcmd_output, msg_txt(993), MIN_HAIR_STYLE, MAX_HAIR_STYLE); // Please enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) { - pc_changelook(sd, LOOK_HAIR, hair_style); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + pc_changelook(sd, LOOK_HAIR, hair_style); + clif->message(fd, msg_txt(36)); // Appearence changed. } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; + clif->message(fd, msg_txt(37)); // An invalid number was specified. + return false; } - - return 0; + + return true; } /*========================================== * @haircolor && @hcolor *------------------------------------------*/ -ACMD_FUNC(hair_color) +ACMD(hair_color) { int hair_color = 0; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%d", &hair_color) < 1) { sprintf(atcmd_output, msg_txt(994), MIN_HAIR_COLOR, MAX_HAIR_COLOR); // Please enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) { - pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); - clif_displaymessage(fd, msg_txt(36)); // Appearence changed. + pc_changelook(sd, LOOK_HAIR_COLOR, hair_color); + clif->message(fd, msg_txt(36)); // Appearence changed. } else { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; + clif->message(fd, msg_txt(37)); // An invalid number was specified. + return false; } - - return 0; + + return true; } /*========================================== * @go [city_number or city_name] - Updated by Harbin *------------------------------------------*/ -ACMD_FUNC(go) +ACMD(go) { int i; int town; char map_name[MAP_NAME_LENGTH]; int16 m; - + const struct { char map[MAP_NAME_LENGTH]; int x, y; @@ -1789,37 +1748,31 @@ ACMD_FUNC(go) { MAP_MALAYA, 242, 211 }, // 34=Malaya Port { MAP_ECLAGE, 110, 39 }, // 35=Eclage }; - + nullpo_retr(-1, sd); - - if( map[sd->bl.m].flag.nogo && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { - clif_displaymessage(sd->fd,msg_txt(995)); // You cannot use @go on this map. - return 0; - } - + memset(map_name, '\0', sizeof(map_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + // get the number town = atoi(message); - + if (!message || !*message || sscanf(message, "%11s", map_name) < 1 || town < 0 || town >= ARRAYLENGTH(data)) {// no value matched so send the list of locations const char* text; - + // attempt to find the text help string - text = atcommand_help_string( command ); - - clif_displaymessage(fd, msg_txt(38)); // Invalid location number, or name. - - if( text ) - {// send the text to the client - clif_displaymessage( fd, text ); - } - - return -1; + text = atcommand_help_string( info ); + + clif->message(fd, msg_txt(38)); // Invalid location number, or name. + + if( text ) {// send the text to the client + clif->messageln( fd, text ); + } + + return false; } - + // get possible name of the city map_name[MAP_NAME_LENGTH-1] = '\0'; for (i = 0; map_name[i]; i++) @@ -1908,36 +1861,36 @@ ACMD_FUNC(go) } else if (strncmp(map_name, "eclage", 3) == 0) { town = 35; } - + if (town >= 0 && town < ARRAYLENGTH(data)) { m = map_mapname2mapid(data[town].map); if (m >= 0 && map[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(247)); - return -1; + clif->message(fd, msg_txt(247)); + return false; } if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(248)); - return -1; + clif->message(fd, msg_txt(248)); + return false; } if (pc_setpos(sd, mapindex_name2id(data[town].map), data[town].x, data[town].y, CLR_TELEPORT) == 0) { - clif_displaymessage(fd, msg_txt(0)); // Warped. + clif->message(fd, msg_txt(0)); // Warped. } else { - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; + clif->message(fd, msg_txt(1)); // Map not found. + return false; } } else { // if you arrive here, you have an error in town variable when reading of names - clif_displaymessage(fd, msg_txt(38)); // Invalid location number or name. - return -1; + clif->message(fd, msg_txt(38)); // Invalid location number or name. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(monster) +ACMD(monster) { char name[NAME_LENGTH]; char monster[NAME_LENGTH]; @@ -1949,14 +1902,14 @@ ACMD_FUNC(monster) short mx, my; unsigned int size; nullpo_retr(-1, sd); - + memset(name, '\0', sizeof(name)); memset(monster, '\0', sizeof(monster)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(80)); // Give the display name or monster name/id please. - return -1; + clif->message(fd, msg_txt(80)); // Give the display name or monster name/id please. + return false; } if (sscanf(message, "\"%23[^\"]\" %23s %d", name, monster, &number) > 1 || sscanf(message, "%23s \"%23[^\"]\" %d", monster, name, &number) > 1) { @@ -1971,43 +1924,43 @@ ACMD_FUNC(monster) //As before, name may be already filled. name[0] = '\0'; } else { - clif_displaymessage(fd, msg_txt(80)); // Give a display name and monster name/id please. - return -1; + clif->message(fd, msg_txt(80)); // Give a display name and monster name/id please. + return false; } - + if ((mob_id = mobdb_searchname(monster)) == 0) // check name first (to avoid possible name begining by a number) mob_id = mobdb_checkid(atoi(monster)); - + if (mob_id == 0) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; + clif->message(fd, msg_txt(40)); // Invalid monster ID or name. + return false; } - + if (mob_id == MOBID_EMPERIUM) { - clif_displaymessage(fd, msg_txt(83)); // Monster 'Emperium' cannot be spawned. - return -1; + clif->message(fd, msg_txt(83)); // Monster 'Emperium' cannot be spawned. + return false; } - + if (number <= 0) number = 1; - + if( !name[0] ) strcpy(name, "--ja--"); - + // If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit) number = battle_config.atc_spawn_quantity_limit; - + if (strcmp(command+1, "monstersmall") == 0) size = SZ_MEDIUM; // This is just gorgeous [mkbu95] else if (strcmp(command+1, "monsterbig") == 0) size = SZ_BIG; else size = SZ_SMALL; - + if (battle_config.etc_log) ShowInfo("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, sd->bl.x, sd->bl.y); - + count = 0; range = (int)sqrt((float)number) +2; // calculation of an odd number (+ 4 area around) for (i = 0; i < number; i++) { @@ -2015,20 +1968,20 @@ ACMD_FUNC(monster) k = mob_once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname, size, AI_NONE); count += (k != 0) ? 1 : 0; } - + if (count != 0) if (number == count) - clif_displaymessage(fd, msg_txt(39)); // All monster summoned! + clif->message(fd, msg_txt(39)); // All monster summoned! else { sprintf(atcmd_output, msg_txt(240), count); // %d monster(s) summoned! - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - else { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; - } - - return 0; + else { + clif->message(fd, msg_txt(40)); // Invalid monster ID or name. + return false; + } + + return true; } /*========================================== @@ -2038,13 +1991,13 @@ static int atkillmonster_sub(struct block_list *bl, va_list ap) { struct mob_data *md; int flag; - + nullpo_ret(md=(struct mob_data *)bl); flag = va_arg(ap, int); - + if (md->guardian_data) return 0; //Do not touch WoE mobs! - + if (flag) status_zap(bl,md->status.hp, 0); else @@ -2052,68 +2005,68 @@ static int atkillmonster_sub(struct block_list *bl, va_list ap) return 1; } -ACMD_FUNC(killmonster) +ACMD(killmonster) { int map_id, drop_flag; char map_name[MAP_NAME_LENGTH_EXT]; nullpo_retr(-1, sd); - + memset(map_name, '\0', sizeof(map_name)); - + if (!message || !*message || sscanf(message, "%15s", map_name) < 1) map_id = sd->bl.m; else { if ((map_id = map_mapname2mapid(map_name)) < 0) map_id = sd->bl.m; } - + drop_flag = strcmp(command+1, "killmonster2"); - + map_foreachinmap(atkillmonster_sub, map_id, BL_MOB, -drop_flag); - - clif_displaymessage(fd, msg_txt(165)); // All monsters killed! - - return 0; + + clif->message(fd, msg_txt(165)); // All monsters killed! + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(refine) +ACMD(refine) { int i,j, position = 0, refine = 0, current_position, final_refine; int count; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%d %d", &position, &refine) < 2) { - clif_displaymessage(fd, msg_txt(996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>). + clif->message(fd, msg_txt(996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>). sprintf(atcmd_output, msg_txt(997), EQP_HEAD_LOW); // %d: Lower Headgear - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(998), EQP_HAND_R); // %d: Right Hand - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(999), EQP_GARMENT); // %d: Garment - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1000), EQP_ACC_L); // %d: Left Accessory - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1001), EQP_ARMOR); // %d: Body Armor - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1002), EQP_HAND_L); // %d: Left Hand - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1003), EQP_SHOES); // %d: Shoes - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1004), EQP_ACC_R); // %d: Right Accessory - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1005), EQP_HEAD_TOP); // %d: Top Headgear - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1006), EQP_HEAD_MID); // %d: Mid Headgear - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + refine = cap_value(refine, -MAX_REFINE, MAX_REFINE); - + count = 0; for (j = 0; j < EQI_MAX-1; j++) { if ((i = sd->equip_index[j]) < 0) @@ -2124,68 +2077,68 @@ ACMD_FUNC(refine) continue; if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == i || sd->equip_index[EQI_HEAD_LOW] == i)) continue; - + if(position && !(sd->status.inventory[i].equip & position)) continue; - + final_refine = cap_value(sd->status.inventory[i].refine + refine, 0, MAX_REFINE); if (sd->status.inventory[i].refine != final_refine) { sd->status.inventory[i].refine = final_refine; current_position = sd->status.inventory[i].equip; pc_unequipitem(sd, i, 3); - clif_refine(fd, 0, i, sd->status.inventory[i].refine); - clif_delitem(sd, i, 1, 3); - clif_additem(sd, i, 1, 0); + clif->refine(fd, 0, i, sd->status.inventory[i].refine); + clif->delitem(sd, i, 1, 3); + clif->additem(sd, i, 1, 0); pc_equipitem(sd, i, current_position); - clif_misceffect(&sd->bl, 3); + clif->misceffect(&sd->bl, 3); count++; } } - + if (count == 0) - clif_displaymessage(fd, msg_txt(166)); // No item has been refined. + clif->message(fd, msg_txt(166)); // No item has been refined. else if (count == 1) - clif_displaymessage(fd, msg_txt(167)); // 1 item has been refined. + clif->message(fd, msg_txt(167)); // 1 item has been refined. else { sprintf(atcmd_output, msg_txt(168), count); // %d items have been refined. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(produce) +ACMD(produce) { char item_name[100]; int item_id, attribute = 0, star = 0; - int flag = 0; struct item_data *item_data; struct item tmp_item; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(item_name, '\0', sizeof(item_name)); - + if (!message || !*message || ( - sscanf(message, "\"%99[^\"]\" %d %d", item_name, &attribute, &star) < 1 && - sscanf(message, "%99s %d %d", item_name, &attribute, &star) < 1 - )) { - clif_displaymessage(fd, msg_txt(1007)); // Please enter at least one item name/ID (usage: @produce <equip name/ID> <element> <# of very's>). - return -1; + sscanf(message, "\"%99[^\"]\" %d %d", item_name, &attribute, &star) < 1 && + sscanf(message, "%99s %d %d", item_name, &attribute, &star) < 1 + )) { + clif->message(fd, msg_txt(1007)); // Please enter at least one item name/ID (usage: @produce <equip name/ID> <element> <# of very's>). + return false; } - + if ( (item_data = itemdb_searchname(item_name)) == NULL && - (item_data = itemdb_exists(atoi(item_name))) == NULL ) { - clif_displaymessage(fd, msg_txt(170)); //This item is not an equipment. - return -1; + (item_data = itemdb_exists(atoi(item_name))) == NULL ) { + clif->message(fd, msg_txt(170)); //This item is not an equipment. + return false; } - + item_id = item_data->nameid; - + if (itemdb_isequip2(item_data)) { + int flag = 0; if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE) attribute = ATTRIBUTE_NORMAL; if (star < MIN_STAR || star > MAX_STAR) @@ -2196,117 +2149,120 @@ ACMD_FUNC(produce) tmp_item.identify = 1; tmp_item.card[0] = CARD0_FORGE; tmp_item.card[1] = item_data->type==IT_WEAPON? - ((star*5) << 8) + attribute:0; + ((star*5) << 8) + attribute:0; tmp_item.card[2] = GetWord(sd->status.char_id, 0); tmp_item.card[3] = GetWord(sd->status.char_id, 1); - clif_produceeffect(sd, 0, item_id); - clif_misceffect(&sd->bl, 3); - + clif->produce_effect(sd, 0, item_id); + clif->misceffect(&sd->bl, 3); + if ((flag = pc_additem(sd, &tmp_item, 1, LOG_TYPE_COMMAND))) - clif_additem(sd, 0, 0, flag); + clif->additem(sd, 0, 0, flag); } else { sprintf(atcmd_output, msg_txt(169), item_id, item_data->name); // The item (%d: '%s') is not equipable. - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(memo) +ACMD(memo) { int position = 0; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if( !message || !*message || sscanf(message, "%d", &position) < 1 ) { int i; - clif_displaymessage(sd->fd, msg_txt(668)); + clif->message(sd->fd, msg_txt(668)); for( i = 0; i < MAX_MEMOPOINTS; i++ ) { if( sd->status.memo_point[i].map ) sprintf(atcmd_output, "%d - %s (%d,%d)", i, mapindex_id2name(sd->status.memo_point[i].map), sd->status.memo_point[i].x, sd->status.memo_point[i].y); else sprintf(atcmd_output, msg_txt(171), i); // %d - void - clif_displaymessage(sd->fd, atcmd_output); + clif->message(sd->fd, atcmd_output); } - return 0; + return true; } - + if( position < 0 || position >= MAX_MEMOPOINTS ) { sprintf(atcmd_output, msg_txt(1008), 0, MAX_MEMOPOINTS-1); // Please enter a valid position (usage: @memo <memo_position:%d-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + pc_memo(sd, position); - return 0; + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(gat) +ACMD(gat) { int y; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + for (y = 2; y >= -2; y--) { sprintf(atcmd_output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X", - map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y, - map_getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE), - map_getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE), - map_getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE), - map_getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE), - map_getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE)); - - clif_displaymessage(fd, atcmd_output); - } - - return 0; + map[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y, + map_getcell(sd->bl.m, sd->bl.x - 2, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x - 1, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE), + map_getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE)); + + clif->message(fd, atcmd_output); + } + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(displaystatus) +ACMD(displaystatus) { int i, type, flag, tick, val1 = 0, val2 = 0, val3 = 0; nullpo_retr(-1, sd); - + if (!message || !*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) { - clif_displaymessage(fd, msg_txt(1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}). - return -1; + clif->message(fd, msg_txt(1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}). + return false; } if (i < 2) flag = 1; if (i < 3) tick = 0; - - clif_status_change(&sd->bl, type, flag, tick, val1, val2, val3); - - return 0; + + if( flag == 0 ) + clif->sc_end(&sd->bl,sd->bl.id,AREA,type); + else + clif->status_change(&sd->bl, type, flag, tick, val1, val2, val3); + + return true; } /*========================================== * @stpoint (Rewritten by [Yor]) *------------------------------------------*/ -ACMD_FUNC(statuspoint) +ACMD(statuspoint) { int point; unsigned int new_status_point; - + if (!message || !*message || (point = atoi(message)) == 0) { - clif_displaymessage(fd, msg_txt(1010)); // Please enter a number (usage: @stpoint <number of points>). - return -1; + clif->message(fd, msg_txt(1010)); // Please enter a number (usage: @stpoint <number of points>). + return false; } - + if(point < 0) { if(sd->status.status_point < (unsigned int)(-point)) @@ -2326,36 +2282,36 @@ ACMD_FUNC(statuspoint) { new_status_point = sd->status.status_point + point; } - + if (new_status_point != sd->status.status_point) { sd->status.status_point = new_status_point; - clif_updatestatus(sd, SP_STATUSPOINT); - clif_displaymessage(fd, msg_txt(174)); // Number of status points changed. + clif->updatestatus(sd, SP_STATUSPOINT); + clif->message(fd, msg_txt(174)); // Number of status points changed. } else { if (point < 0) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. else - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. - return -1; + clif->message(fd, msg_txt(149)); // Unable to increase the number/value. + return false; } - - return 0; + + return true; } /*========================================== * @skpoint (Rewritten by [Yor]) *------------------------------------------*/ -ACMD_FUNC(skillpoint) +ACMD(skillpoint) { int point; unsigned int new_skill_point; nullpo_retr(-1, sd); - + if (!message || !*message || (point = atoi(message)) == 0) { - clif_displaymessage(fd, msg_txt(1011)); // Please enter a number (usage: @skpoint <number of points>). - return -1; + clif->message(fd, msg_txt(1011)); // Please enter a number (usage: @skpoint <number of points>). + return false; } - + if(point < 0) { if(sd->status.skill_point < (unsigned int)(-point)) @@ -2375,85 +2331,85 @@ ACMD_FUNC(skillpoint) { new_skill_point = sd->status.skill_point + point; } - + if (new_skill_point != sd->status.skill_point) { sd->status.skill_point = new_skill_point; - clif_updatestatus(sd, SP_SKILLPOINT); - clif_displaymessage(fd, msg_txt(175)); // Number of skill points changed. + clif->updatestatus(sd, SP_SKILLPOINT); + clif->message(fd, msg_txt(175)); // Number of skill points changed. } else { if (point < 0) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. else - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. - return -1; + clif->message(fd, msg_txt(149)); // Unable to increase the number/value. + return false; } - - return 0; + + return true; } /*========================================== * @zeny *------------------------------------------*/ -ACMD_FUNC(zeny) +ACMD(zeny) { int zeny=0, ret=-1; nullpo_retr(-1, sd); - + if (!message || !*message || (zeny = atoi(message)) == 0) { - clif_displaymessage(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>). - return -1; + clif->message(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>). + return false; } - + if(zeny > 0){ if((ret=pc_getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL)) == 1) - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. + clif->message(fd, msg_txt(149)); // Unable to increase the number/value. } else { if( sd->status.zeny < -zeny ) zeny = -sd->status.zeny; if((ret=pc_payzeny(sd,-zeny,LOG_TYPE_COMMAND,NULL)) == 1) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. } - if(!ret) clif_displaymessage(fd, msg_txt(176)); //ret=0 mean cmd success - return 0; + if(!ret) clif->message(fd, msg_txt(176)); //ret=0 mean cmd success + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(param) +ACMD(param) { int i, value = 0, new_value, max; const char* param[] = { "str", "agi", "vit", "int", "dex", "luk" }; short* status[6]; //we don't use direct initialization because it isn't part of the c standard. nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { - clif_displaymessage(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). - return -1; + clif->message(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). + return false; } - + ARR_FIND( 0, ARRAYLENGTH(param), i, strcmpi(command+1, param[i]) == 0 ); - + if( i == ARRAYLENGTH(param) || i > MAX_STATUS_TYPE) { // normally impossible... - clif_displaymessage(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). - return -1; + clif->message(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>). + return false; } - + status[0] = &sd->status.str; status[1] = &sd->status.agi; status[2] = &sd->status.vit; status[3] = &sd->status.int_; status[4] = &sd->status.dex; status[5] = &sd->status.luk; - + if( battle_config.atcommand_max_stat_bypass ) max = SHRT_MAX; else max = pc_maxparameter(sd); - + if(value < 0 && *status[i] <= -value) { new_value = 1; } else if(max - *status[i] < value) { @@ -2461,41 +2417,41 @@ ACMD_FUNC(param) } else { new_value = *status[i] + value; } - + if (new_value != *status[i]) { *status[i] = new_value; - clif_updatestatus(sd, SP_STR + i); - clif_updatestatus(sd, SP_USTR + i); + clif->updatestatus(sd, SP_STR + i); + clif->updatestatus(sd, SP_USTR + i); status_calc_pc(sd, 0); - clif_displaymessage(fd, msg_txt(42)); // Stat changed. + clif->message(fd, msg_txt(42)); // Stat changed. } else { if (value < 0) - clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. else - clif_displaymessage(fd, msg_txt(149)); // Unable to increase the number/value. - return -1; + clif->message(fd, msg_txt(149)); // Unable to increase the number/value. + return false; } - - return 0; + + return true; } /*========================================== * Stat all by fritz (rewritten by [Yor]) *------------------------------------------*/ -ACMD_FUNC(stat_all) +ACMD(stat_all) { int index, count, value, max, new_value; short* status[6]; //we don't use direct initialization because it isn't part of the c standard. nullpo_retr(-1, sd); - + status[0] = &sd->status.str; status[1] = &sd->status.agi; status[2] = &sd->status.vit; status[3] = &sd->status.int_; status[4] = &sd->status.dex; status[5] = &sd->status.luk; - + if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) { value = pc_maxparameter(sd); max = pc_maxparameter(sd); @@ -2505,295 +2461,295 @@ ACMD_FUNC(stat_all) else max = pc_maxparameter(sd); } - + count = 0; for (index = 0; index < ARRAYLENGTH(status); index++) { - + if (value > 0 && *status[index] > max - value) new_value = max; else if (value < 0 && *status[index] <= -value) new_value = 1; else new_value = *status[index] +value; - + if (new_value != (int)*status[index]) { *status[index] = new_value; - clif_updatestatus(sd, SP_STR + index); - clif_updatestatus(sd, SP_USTR + index); + clif->updatestatus(sd, SP_STR + index); + clif->updatestatus(sd, SP_USTR + index); count++; } } - + if (count > 0) { // if at least 1 stat modified status_calc_pc(sd, 0); - clif_displaymessage(fd, msg_txt(84)); // All stats changed! + clif->message(fd, msg_txt(84)); // All stats changed! } else { if (value < 0) - clif_displaymessage(fd, msg_txt(177)); // You cannot decrease that stat anymore. + clif->message(fd, msg_txt(177)); // You cannot decrease that stat anymore. else - clif_displaymessage(fd, msg_txt(178)); // You cannot increase that stat anymore. - return -1; + clif->message(fd, msg_txt(178)); // You cannot increase that stat anymore. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(guildlevelup) +ACMD(guildlevelup) { int level = 0; short added_level; struct guild *guild_info; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) { - clif_displaymessage(fd, msg_txt(1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>). - return -1; + clif->message(fd, msg_txt(1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>). + return false; } - - if (sd->status.guild_id <= 0 || (guild_info = guild_search(sd->status.guild_id)) == NULL) { - clif_displaymessage(fd, msg_txt(43)); // You're not in a guild. - return -1; + + if (sd->status.guild_id <= 0 || (guild_info = sd->guild) == NULL) { + clif->message(fd, msg_txt(43)); // You're not in a guild. + return false; } //if (strcmp(sd->status.name, guild_info->master) != 0) { - // clif_displaymessage(fd, msg_txt(44)); // You're not the master of your guild. - // return -1; + // clif->message(fd, msg_txt(44)); // You're not the master of your guild. + // return false; //} - + added_level = (short)level; if (level > 0 && (level > MAX_GUILDLEVEL || added_level > ((short)MAX_GUILDLEVEL - guild_info->guild_lv))) // fix positiv overflow added_level = (short)MAX_GUILDLEVEL - guild_info->guild_lv; else if (level < 0 && (level < -MAX_GUILDLEVEL || added_level < (1 - guild_info->guild_lv))) // fix negativ overflow added_level = 1 - guild_info->guild_lv; - + if (added_level != 0) { intif_guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level)); - clif_displaymessage(fd, msg_txt(179)); // Guild level changed. + clif->message(fd, msg_txt(179)); // Guild level changed. } else { - clif_displaymessage(fd, msg_txt(45)); // Guild level change failed. - return -1; + clif->message(fd, msg_txt(45)); // Guild level change failed. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(makeegg) +ACMD(makeegg) { struct item_data *item_data; int id, pet_id; nullpo_retr(-1, sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>). - return -1; + clif->message(fd, msg_txt(1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>). + return false; } - + if ((item_data = itemdb_searchname(message)) != NULL) // for egg name id = item_data->nameid; else - if ((id = mobdb_searchname(message)) != 0) // for monster name - ; - else - id = atoi(message); - + if ((id = mobdb_searchname(message)) != 0) // for monster name + ; + else + id = atoi(message); + pet_id = search_petDB_index(id, PET_CLASS); if (pet_id < 0) pet_id = search_petDB_index(id, PET_EGG); if (pet_id >= 0) { sd->catch_target_class = pet_db[pet_id].class_; intif_create_pet( - sd->status.account_id, sd->status.char_id, - (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, - (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, - 100, 0, 1, pet_db[pet_id].jname); + sd->status.account_id, sd->status.char_id, + (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, + (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, + 100, 0, 1, pet_db[pet_id].jname); } else { - clif_displaymessage(fd, msg_txt(180)); // The monster/egg name/id doesn't exist. - return -1; + clif->message(fd, msg_txt(180)); // The monster/egg name/id doesn't exist. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(hatch) +ACMD(hatch) { nullpo_retr(-1, sd); if (sd->status.pet_id <= 0) - clif_sendegg(sd); + clif->sendegg(sd); else { - clif_displaymessage(fd, msg_txt(181)); // You already have a pet. - return -1; + clif->message(fd, msg_txt(181)); // You already have a pet. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(petfriendly) +ACMD(petfriendly) { int friendly; struct pet_data *pd; nullpo_retr(-1, sd); - + if (!message || !*message || (friendly = atoi(message)) < 0) { - clif_displaymessage(fd, msg_txt(1016)); // Please enter a valid value (usage: @petfriendly <0-1000>). - return -1; + clif->message(fd, msg_txt(1016)); // Please enter a valid value (usage: @petfriendly <0-1000>). + return false; } - + pd = sd->pd; if (!pd) { - clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. - return -1; + clif->message(fd, msg_txt(184)); // Sorry, but you have no pet. + return false; } - + if (friendly < 0 || friendly > 1000) { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; + clif->message(fd, msg_txt(37)); // An invalid number was specified. + return false; } - + if (friendly == pd->pet.intimate) { - clif_displaymessage(fd, msg_txt(183)); // Pet intimacy is already at maximum. - return -1; + clif->message(fd, msg_txt(183)); // Pet intimacy is already at maximum. + return false; } - + pet_set_intimate(pd, friendly); - clif_send_petstatus(sd); - clif_displaymessage(fd, msg_txt(182)); // Pet intimacy changed. - return 0; + clif->send_petstatus(sd); + clif->message(fd, msg_txt(182)); // Pet intimacy changed. + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(pethungry) +ACMD(pethungry) { int hungry; struct pet_data *pd; nullpo_retr(-1, sd); - + if (!message || !*message || (hungry = atoi(message)) < 0) { - clif_displaymessage(fd, msg_txt(1017)); // Please enter a valid number (usage: @pethungry <0-100>). - return -1; + clif->message(fd, msg_txt(1017)); // Please enter a valid number (usage: @pethungry <0-100>). + return false; } - + pd = sd->pd; if (!sd->status.pet_id || !pd) { - clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. - return -1; + clif->message(fd, msg_txt(184)); // Sorry, but you have no pet. + return false; } if (hungry < 0 || hungry > 100) { - clif_displaymessage(fd, msg_txt(37)); // An invalid number was specified. - return -1; + clif->message(fd, msg_txt(37)); // An invalid number was specified. + return false; } if (hungry == pd->pet.hungry) { - clif_displaymessage(fd, msg_txt(186)); // Pet hunger is already at maximum. - return -1; + clif->message(fd, msg_txt(186)); // Pet hunger is already at maximum. + return false; } - + pd->pet.hungry = hungry; - clif_send_petstatus(sd); - clif_displaymessage(fd, msg_txt(185)); // Pet hunger changed. - - return 0; + clif->send_petstatus(sd); + clif->message(fd, msg_txt(185)); // Pet hunger changed. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(petrename) +ACMD(petrename) { struct pet_data *pd; nullpo_retr(-1, sd); if (!sd->status.pet_id || !sd->pd) { - clif_displaymessage(fd, msg_txt(184)); // Sorry, but you have no pet. - return -1; + clif->message(fd, msg_txt(184)); // Sorry, but you have no pet. + return false; } pd = sd->pd; if (!pd->pet.rename_flag) { - clif_displaymessage(fd, msg_txt(188)); // You can already rename your pet. - return -1; + clif->message(fd, msg_txt(188)); // You can already rename your pet. + return false; } - + pd->pet.rename_flag = 0; intif_save_petdata(sd->status.account_id, &pd->pet); - clif_send_petstatus(sd); - clif_displaymessage(fd, msg_txt(187)); // You can now rename your pet. - - return 0; + clif->send_petstatus(sd); + clif->message(fd, msg_txt(187)); // You can now rename your pet. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(recall) { +ACMD(recall) { struct map_session_data *pl_sd = NULL; - + nullpo_retr(-1, sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1018)); // Please enter a player name (usage: @recall <char name/ID>). - return -1; + clif->message(fd, msg_txt(1018)); // Please enter a player name (usage: @recall <char name/ID>). + return false; } - + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level doesn't authorize you to preform this action on the specified player. - return -1; + clif->message(fd, msg_txt(81)); // Your GM level doesn't authorize you to preform this action on the specified player. + return false; } - + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1019)); // You are not authorized to warp someone to this map. - return -1; + clif->message(fd, msg_txt(1019)); // You are not authorized to warp someone to this map. + return false; } if (pl_sd->bl.m >= 0 && map[pl_sd->bl.m].flag.nowarp && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1020)); // You are not authorized to warp this player from their map. - return -1; + clif->message(fd, msg_txt(1020)); // You are not authorized to warp this player from their map. + return false; } if (pl_sd->bl.m == sd->bl.m && pl_sd->bl.x == sd->bl.x && pl_sd->bl.y == sd->bl.y) { - return -1; + return false; } pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); sprintf(atcmd_output, msg_txt(46), pl_sd->status.name); // %s recalled! - clif_displaymessage(fd, atcmd_output); - - return 0; + clif->message(fd, atcmd_output); + + return true; } /*========================================== * charblock command (usage: charblock <player_name>) * This command do a definitiv ban on a player *------------------------------------------*/ -ACMD_FUNC(char_block) +ACMD(char_block) { nullpo_retr(-1, sd); - + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1021)); // Please enter a player name (usage: @charblock/@block <char name>). - return -1; + clif->message(fd, msg_txt(1021)); // Please enter a player name (usage: @charblock/@block <char name>). + return false; } - + chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block - clif_displaymessage(fd, msg_txt(88)); // Character name sent to char-server to ask it. - - return 0; + clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it. + + return true; } /*========================================== @@ -2811,24 +2767,24 @@ ACMD_FUNC(char_block) * <example> @ban +1m-2mn1s-6y test_player * this example adds 1 month and 1 second, and substracts 2 minutes and 6 years at the same time. *------------------------------------------*/ -ACMD_FUNC(char_ban) +ACMD(char_ban) { char * modif_p; int year, month, day, hour, minute, second, value; time_t timestamp; struct tm *tmtime; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - - if (!message || !*message || sscanf(message, "%s %23[^\n]", atcmd_output, atcmd_player_name) < 2) { - clif_displaymessage(fd, msg_txt(1022)); // Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>). - return -1; + + if (!message || !*message || sscanf(message, "%255s %23[^\n]", atcmd_output, atcmd_player_name) < 2) { + clif->message(fd, msg_txt(1022)); // Please enter ban time and a player name (usage: @charban/@ban/@banish/@charbanish <time> <char name>). + return false; } - + atcmd_output[sizeof(atcmd_output)-1] = '\0'; - + modif_p = atcmd_output; year = month = day = hour = minute = second = 0; while (modif_p[0] != '\0') { @@ -2867,8 +2823,8 @@ ACMD_FUNC(char_ban) } } if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0 && second == 0) { - clif_displaymessage(fd, msg_txt(85)); // Invalid time for ban command. - return -1; + clif->message(fd, msg_txt(85)); // Invalid time for ban command. + return false; } /** * We now check if you can adjust the ban to negative (and if this is the case) @@ -2882,602 +2838,600 @@ ACMD_FUNC(char_ban) tmtime->tm_min = tmtime->tm_min + minute; tmtime->tm_sec = tmtime->tm_sec + second; timestamp = mktime(tmtime); - if( timestamp <= time(NULL) && !pc_can_use_command(sd, "unban", COMMAND_ATCOMMAND) ) { - clif_displaymessage(fd,msg_txt(1023)); // You are not allowed to reduce the length of a ban. - return -1; + if( timestamp <= time(NULL) && !pc_can_use_command(sd, "@unban") ) { + clif->message(fd,msg_txt(1023)); // You are not allowed to reduce the length of a ban. + return false; } - + chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 2, year, month, day, hour, minute, second); // type: 2 - ban - clif_displaymessage(fd, msg_txt(88)); // Character name sent to char-server to ask it. - - return 0; + clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it. + + return true; } /*========================================== * charunblock command (usage: charunblock <player_name>) *------------------------------------------*/ -ACMD_FUNC(char_unblock) +ACMD(char_unblock) { nullpo_retr(-1, sd); - + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1024)); // Please enter a player name (usage: @charunblock <char name>). - return -1; + clif->message(fd, msg_txt(1024)); // Please enter a player name (usage: @charunblock <char name>). + return false; } - + // send answer to login server via char-server chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock - clif_displaymessage(fd, msg_txt(88)); // Character name sent to char-server to ask it. - - return 0; + clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it. + + return true; } /*========================================== * charunban command (usage: charunban <player_name>) *------------------------------------------*/ -ACMD_FUNC(char_unban) +ACMD(char_unban) { nullpo_retr(-1, sd); - + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1025)); // Please enter a player name (usage: @charunban <char name>). - return -1; + clif->message(fd, msg_txt(1025)); // Please enter a player name (usage: @charunban <char name>). + return false; } - + // send answer to login server via char-server chrif_char_ask_name(sd->status.account_id, atcmd_player_name, 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban - clif_displaymessage(fd, msg_txt(88)); // Character name sent to char-server to ask it. - - return 0; + clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(night) +ACMD(night) { nullpo_retr(-1, sd); - + if (night_flag != 1) { map_night_timer(night_timer_tid, 0, 0, 1); } else { - clif_displaymessage(fd, msg_txt(89)); // Night mode is already enabled. - return -1; + clif->message(fd, msg_txt(89)); // Night mode is already enabled. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(day) +ACMD(day) { nullpo_retr(-1, sd); - + if (night_flag != 0) { map_day_timer(day_timer_tid, 0, 0, 1); } else { - clif_displaymessage(fd, msg_txt(90)); // Day mode is already enabled. - return -1; + clif->message(fd, msg_txt(90)); // Day mode is already enabled. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(doom) +ACMD(doom) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - + nullpo_retr(-1, sd); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if (pl_sd->fd != fd && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { status_kill(&pl_sd->bl); - clif_specialeffect(&pl_sd->bl,450,AREA); - clif_displaymessage(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. + clif->specialeffect(&pl_sd->bl,450,AREA); + clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. } } - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(62)); // Judgement was made. - - return 0; + mapit->free(iter); + + clif->message(fd, msg_txt(62)); // Judgement was made. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(doommap) +ACMD(doommap) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - + nullpo_retr(-1, sd); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if (pl_sd->fd != fd && sd->bl.m == pl_sd->bl.m && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { status_kill(&pl_sd->bl); - clif_specialeffect(&pl_sd->bl,450,AREA); - clif_displaymessage(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. + clif->specialeffect(&pl_sd->bl,450,AREA); + clif->message(pl_sd->fd, msg_txt(61)); // The holy messenger has given judgement. } } - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(62)); // Judgement was made. - - return 0; + mapit->free(iter); + + clif->message(fd, msg_txt(62)); // Judgement was made. + + return true; } /*========================================== * *------------------------------------------*/ static void atcommand_raise_sub(struct map_session_data* sd) { - + status_revive(&sd->bl, 100, 100); - - clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); - clif_displaymessage(sd->fd, msg_txt(63)); // Mercy has been shown. + + clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); + clif->message(sd->fd, msg_txt(63)); // Mercy has been shown. } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(raise) +ACMD(raise) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - + nullpo_retr(-1, sd); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) if( pc_isdead(pl_sd) ) atcommand_raise_sub(pl_sd); - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(64)); // Mercy has been granted. - - return 0; + mapit->free(iter); + + clif->message(fd, msg_txt(64)); // Mercy has been granted. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(raisemap) +ACMD(raisemap) { struct map_session_data* pl_sd; struct s_mapiterator* iter; - + nullpo_retr(-1, sd); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) if (sd->bl.m == pl_sd->bl.m && pc_isdead(pl_sd) ) atcommand_raise_sub(pl_sd); - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(64)); // Mercy has been granted. - - return 0; + mapit->free(iter); + + clif->message(fd, msg_txt(64)); // Mercy has been granted. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(kick) +ACMD(kick) { struct map_session_data *pl_sd; nullpo_retr(-1, sd); - + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1026)); // Please enter a player name (usage: @kick <char name/ID>). - return -1; + clif->message(fd, msg_txt(1026)); // Please enter a player name (usage: @kick <char name/ID>). + return false; } - + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; + clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return false; } - - clif_GM_kick(sd, pl_sd); - - return 0; + + clif->GM_kick(sd, pl_sd); + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(kickall) +ACMD(kickall) { struct map_session_data* pl_sd; struct s_mapiterator* iter; nullpo_retr(-1, sd); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kick only lower or same gm level if (sd->status.account_id != pl_sd->status.account_id) - clif_GM_kick(NULL, pl_sd); + clif->GM_kick(NULL, pl_sd); } } - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(195)); // All players have been kicked! - - return 0; + mapit->free(iter); + + clif->message(fd, msg_txt(195)); // All players have been kicked! + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(allskill) +ACMD(allskill) { nullpo_retr(-1, sd); pc_allskillup(sd); // all skills sd->status.skill_point = 0; // 0 skill points - clif_updatestatus(sd, SP_SKILLPOINT); // update - clif_displaymessage(fd, msg_txt(76)); // All skills have been added to your skill tree. - - return 0; + clif->updatestatus(sd, SP_SKILLPOINT); // update + clif->message(fd, msg_txt(76)); // All skills have been added to your skill tree. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(questskill) +ACMD(questskill) { - uint16 skill_id; + uint16 skill_id, index; nullpo_retr(-1, sd); - + if (!message || !*message || (skill_id = atoi(message)) <= 0) {// also send a list of skills applicable to this command const char* text; - + // attempt to find the text corresponding to this command - text = atcommand_help_string( command ); - + text = atcommand_help_string( info ); + // send the error message as always - clif_displaymessage(fd, msg_txt(1027)); // Please enter a quest skill number. - - if( text ) - {// send the skill ID list associated with this command - clif_displaymessage( fd, text ); + clif->message(fd, msg_txt(1027)); // Please enter a quest skill number. + + if( text ) {// send the skill ID list associated with this command + clif->messageln( fd, text ); } - - return -1; + + return false; } - if (skill_id >= MAX_SKILL_DB) { - clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist. - return -1; + if( !(index = skill->get_index(skill_id)) ) { + clif->message(fd, msg_txt(198)); // This skill number doesn't exist. + return false; } - if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) { - clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. - return -1; + if (!(skill->get_inf2(skill_id) & INF2_QUEST_SKILL)) { + clif->message(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. + return false; } - if (pc_checkskill(sd, skill_id) > 0) { - clif_displaymessage(fd, msg_txt(196)); // You already have this quest skill. - return -1; + if (pc_checkskill2(sd, index) > 0) { + clif->message(fd, msg_txt(196)); // You already have this quest skill. + return false; } - + pc_skill(sd, skill_id, 1, 0); - clif_displaymessage(fd, msg_txt(70)); // You have learned the skill. - - return 0; + clif->message(fd, msg_txt(70)); // You have learned the skill. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(lostskill) +ACMD(lostskill) { - uint16 skill_id; + uint16 skill_id, index; nullpo_retr(-1, sd); - + if (!message || !*message || (skill_id = atoi(message)) <= 0) {// also send a list of skills applicable to this command const char* text; - + // attempt to find the text corresponding to this command - text = atcommand_help_string( command ); - + text = atcommand_help_string( info ); + // send the error message as always - clif_displaymessage(fd, msg_txt(1027)); // Please enter a quest skill number. - - if( text ) - {// send the skill ID list associated with this command - clif_displaymessage( fd, text ); + clif->message(fd, msg_txt(1027)); // Please enter a quest skill number. + + if( text ) {// send the skill ID list associated with this command + clif->messageln( fd, text ); } - - return -1; + + return false; } - if (skill_id >= MAX_SKILL) { - clif_displaymessage(fd, msg_txt(198)); // This skill number doesn't exist. - return -1; + if ( !( index = skill->get_index(skill_id) ) ) { + clif->message(fd, msg_txt(198)); // This skill number doesn't exist. + return false; } - if (!(skill_get_inf2(skill_id) & INF2_QUEST_SKILL)) { - clif_displaymessage(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. - return -1; + if (!(skill->get_inf2(skill_id) & INF2_QUEST_SKILL)) { + clif->message(fd, msg_txt(197)); // This skill number doesn't exist or isn't a quest skill. + return false; } - if (pc_checkskill(sd, skill_id) == 0) { - clif_displaymessage(fd, msg_txt(201)); // You don't have this quest skill. - return -1; + if (pc_checkskill2(sd, index) == 0) { + clif->message(fd, msg_txt(201)); // You don't have this quest skill. + return false; } - - sd->status.skill[skill_id].lv = 0; - sd->status.skill[skill_id].flag = 0; - clif_deleteskill(sd,skill_id); - clif_displaymessage(fd, msg_txt(71)); // You have forgotten the skill. - - return 0; + + sd->status.skill[index].lv = 0; + sd->status.skill[index].flag = 0; + clif->deleteskill(sd,skill_id); + clif->message(fd, msg_txt(71)); // You have forgotten the skill. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(spiritball) +ACMD(spiritball) { int max_spiritballs; int number; nullpo_retr(-1, sd); - + max_spiritballs = min(ARRAYLENGTH(sd->spirit_timer), 0x7FFF); - + if( !message || !*message || (number = atoi(message)) < 0 || number > max_spiritballs ) { char msg[CHAT_SIZE_MAX]; safesnprintf(msg, sizeof(msg), msg_txt(1028), max_spiritballs); // Please enter a party name (usage: @party <party_name>). - clif_displaymessage(fd, msg); - return -1; + clif->message(fd, msg); + return false; } - + if( sd->spiritball > 0 ) pc_delspiritball(sd, sd->spiritball, 1); sd->spiritball = number; - clif_spiritball(&sd->bl); + clif->spiritball(&sd->bl); // no message, player can look the difference - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(party) +ACMD(party) { char party[NAME_LENGTH]; nullpo_retr(-1, sd); - + memset(party, '\0', sizeof(party)); - + if (!message || !*message || sscanf(message, "%23[^\n]", party) < 1) { - clif_displaymessage(fd, msg_txt(1029)); // Please enter a party name (usage: @party <party_name>). - return -1; + clif->message(fd, msg_txt(1029)); // Please enter a party name (usage: @party <party_name>). + return false; } - + party_create(sd, party, 0, 0); - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(guild) +ACMD(guild) { - char guild[NAME_LENGTH]; + char guild_name[NAME_LENGTH]; int prev; nullpo_retr(-1, sd); - - memset(guild, '\0', sizeof(guild)); - - if (!message || !*message || sscanf(message, "%23[^\n]", guild) < 1) { - clif_displaymessage(fd, msg_txt(1030)); // Please enter a guild name (usage: @guild <guild_name>). - return -1; + + memset(guild_name, '\0', sizeof(guild_name)); + + if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { + clif->message(fd, msg_txt(1030)); // Please enter a guild name (usage: @guild <guild_name>). + return false; } - + prev = battle_config.guild_emperium_check; battle_config.guild_emperium_check = 0; - guild_create(sd, guild); + guild->create(sd, guild_name); battle_config.guild_emperium_check = prev; - - return 0; + + return true; } -ACMD_FUNC(breakguild) +ACMD(breakguild) { - int ret = 0; - struct guild *g; nullpo_retr(-1, sd); - + if (sd->status.guild_id) { // Check if the player has a guild - g = guild_search(sd->status.guild_id); // Search the guild + struct guild *g; + g = sd->guild; // Search the guild if (g) { // Check if guild was found if (sd->state.gmaster_flag) { // Check if player is guild master - ret = guild_break(sd, g->name); // Break guild + int ret = 0; + ret = guild->dobreak(sd, g->name); // Break guild if (ret) { // Check if anything went wrong - return 0; // Guild was broken + return true; // Guild was broken } else { - return -1; // Something went wrong + return false; // Something went wrong } } else { // Not guild master - clif_displaymessage(fd, msg_txt(1181)); // You need to be a Guild Master to use this command. - return -1; + clif->message(fd, msg_txt(1181)); // You need to be a Guild Master to use this command. + return false; } } else { // Guild was not found. HOW? - clif_displaymessage(fd, msg_txt(252)); // You are not in a guild. - return -1; + clif->message(fd, msg_txt(252)); // You are not in a guild. + return false; } } else { // Player does not have a guild - clif_displaymessage(fd, msg_txt(252)); // You are not in a guild. - return -1; + clif->message(fd, msg_txt(252)); // You are not in a guild. + return false; } - return 0; + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(agitstart) +ACMD(agitstart) { nullpo_retr(-1, sd); if (agit_flag == 1) { - clif_displaymessage(fd, msg_txt(73)); // War of Emperium is currently in progress. - return -1; + clif->message(fd, msg_txt(73)); // War of Emperium is currently in progress. + return false; } - + agit_flag = 1; - guild_agit_start(); - clif_displaymessage(fd, msg_txt(72)); // War of Emperium has been initiated. - - return 0; + guild->agit_start(); + clif->message(fd, msg_txt(72)); // War of Emperium has been initiated. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(agitstart2) +ACMD(agitstart2) { nullpo_retr(-1, sd); if (agit2_flag == 1) { - clif_displaymessage(fd, msg_txt(404)); // "War of Emperium SE is currently in progress." - return -1; + clif->message(fd, msg_txt(404)); // "War of Emperium SE is currently in progress." + return false; } - + agit2_flag = 1; - guild_agit2_start(); - clif_displaymessage(fd, msg_txt(403)); // "War of Emperium SE has been initiated." - - return 0; + guild->agit2_start(); + clif->message(fd, msg_txt(403)); // "War of Emperium SE has been initiated." + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(agitend) +ACMD(agitend) { nullpo_retr(-1, sd); if (agit_flag == 0) { - clif_displaymessage(fd, msg_txt(75)); // War of Emperium is currently not in progress. - return -1; + clif->message(fd, msg_txt(75)); // War of Emperium is currently not in progress. + return false; } - + agit_flag = 0; - guild_agit_end(); - clif_displaymessage(fd, msg_txt(74)); // War of Emperium has been ended. - - return 0; + guild->agit_end(); + clif->message(fd, msg_txt(74)); // War of Emperium has been ended. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(agitend2) +ACMD(agitend2) { nullpo_retr(-1, sd); if (agit2_flag == 0) { - clif_displaymessage(fd, msg_txt(406)); // "War of Emperium SE is currently not in progress." - return -1; + clif->message(fd, msg_txt(406)); // "War of Emperium SE is currently not in progress." + return false; } - + agit2_flag = 0; - guild_agit2_end(); - clif_displaymessage(fd, msg_txt(405)); // "War of Emperium SE has been ended." - - return 0; + guild->agit2_end(); + clif->message(fd, msg_txt(405)); // "War of Emperium SE has been ended." + + return true; } /*========================================== * @mapexit - shuts down the map server *------------------------------------------*/ -ACMD_FUNC(mapexit) +ACMD(mapexit) { nullpo_retr(-1, sd); - + do_shutdown(); - return 0; + return true; } /*========================================== * idsearch <part_of_name>: revrited by [Yor] *------------------------------------------*/ -ACMD_FUNC(idsearch) +ACMD(idsearch) { char item_name[100]; unsigned int i, match; struct item_data *item_array[MAX_SEARCH]; nullpo_retr(-1, sd); - + memset(item_name, '\0', sizeof(item_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%99s", item_name) < 0) { - clif_displaymessage(fd, msg_txt(1031)); // Please enter part of an item name (usage: @idsearch <part_of_item_name>). - return -1; + clif->message(fd, msg_txt(1031)); // Please enter part of an item name (usage: @idsearch <part_of_item_name>). + return false; } - + sprintf(atcmd_output, msg_txt(77), item_name); // The reference result of '%s' (name: id): - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); match = itemdb_searchname_array(item_array, MAX_SEARCH, item_name); if (match > MAX_SEARCH) { sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, match); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); match = MAX_SEARCH; } for(i = 0; i < match; i++) { sprintf(atcmd_output, msg_txt(78), item_array[i]->jname, item_array[i]->nameid); // %s: %d - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } sprintf(atcmd_output, msg_txt(79), match); // It is %d affair above. - clif_displaymessage(fd, atcmd_output); - - return 0; + clif->message(fd, atcmd_output); + + return true; } /*========================================== * Recall All Characters Online To Your Location *------------------------------------------*/ -ACMD_FUNC(recallall) +ACMD(recallall) { struct map_session_data* pl_sd; struct s_mapiterator* iter; int count; nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. - return -1; + clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + return false; } - + count = 0; iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if (sd->status.account_id != pl_sd->status.account_id && pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { @@ -3494,21 +3448,21 @@ ACMD_FUNC(recallall) } } } - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(92)); // All characters recalled! + mapit->free(iter); + + clif->message(fd, msg_txt(92)); // All characters recalled! if (count) { sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - - return 0; + + return true; } /*========================================== * Recall online characters of a guild to your location *------------------------------------------*/ -ACMD_FUNC(guildrecall) +ACMD(guildrecall) { struct map_session_data* pl_sd; struct s_mapiterator* iter; @@ -3516,31 +3470,31 @@ ACMD_FUNC(guildrecall) char guild_name[NAME_LENGTH]; struct guild *g; nullpo_retr(-1, sd); - + memset(guild_name, '\0', sizeof(guild_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { - clif_displaymessage(fd, msg_txt(1034)); // Please enter a guild name/ID (usage: @guildrecall <guild_name/ID>). - return -1; + clif->message(fd, msg_txt(1034)); // Please enter a guild name/ID (usage: @guildrecall <guild_name/ID>). + return false; } - + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. - return -1; + clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + return false; } - - if ((g = guild_searchname(guild_name)) == NULL && // name first to avoid error when name begin with a number - (g = guild_search(atoi(message))) == NULL) + + if ((g = guild->searchname(guild_name)) == NULL && // name first to avoid error when name begin with a number + (g = guild->search(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; + clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return false; } - + count = 0; - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.guild_id == g->guild_id) { @@ -3552,22 +3506,22 @@ ACMD_FUNC(guildrecall) pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); } } - mapit_free(iter); - + mapit->free(iter); + sprintf(atcmd_output, msg_txt(93), g->name); // All online characters of the %s guild have been recalled to your position. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); if (count) { sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - - return 0; + + return true; } /*========================================== * Recall online characters of a party to your location *------------------------------------------*/ -ACMD_FUNC(partyrecall) +ACMD(partyrecall) { struct map_session_data* pl_sd; struct s_mapiterator* iter; @@ -3575,31 +3529,31 @@ ACMD_FUNC(partyrecall) struct party_data *p; int count; nullpo_retr(-1, sd); - + memset(party_name, '\0', sizeof(party_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { - clif_displaymessage(fd, msg_txt(1035)); // Please enter a party name/ID (usage: @partyrecall <party_name/ID>). - return -1; + clif->message(fd, msg_txt(1035)); // Please enter a party name/ID (usage: @partyrecall <party_name/ID>). + return false; } - + if (sd->bl.m >= 0 && map[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) { - clif_displaymessage(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. - return -1; + clif->message(fd, msg_txt(1032)); // You are not authorized to warp somenone to your current map. + return false; } - + if ((p = party_searchname(party_name)) == NULL && // name first to avoid error when name begin with a number (p = party_search(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(96)); // Incorrect name or ID, or no one from the party is online. - return -1; + clif->message(fd, msg_txt(96)); // Incorrect name or ID, or no one from the party is online. + return false; } - + count = 0; - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id) { @@ -3611,182 +3565,181 @@ ACMD_FUNC(partyrecall) pc_setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN); } } - mapit_free(iter); - + mapit->free(iter); + sprintf(atcmd_output, msg_txt(95), p->party.name); // All online characters of the %s party have been recalled to your position. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); if (count) { sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(reloaditemdb) +ACMD(reloaditemdb) { nullpo_retr(-1, sd); itemdb_reload(); - clif_displaymessage(fd, msg_txt(97)); // Item database has been reloaded. - - return 0; + clif->message(fd, msg_txt(97)); // Item database has been reloaded. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(reloadmobdb) -{ +ACMD(reloadmobdb) { nullpo_retr(-1, sd); mob_reload(); read_petdb(); - merc_reload(); + homun->reload(); read_mercenarydb(); read_mercenary_skilldb(); reload_elementaldb(); - clif_displaymessage(fd, msg_txt(98)); // Monster database has been reloaded. - - return 0; + clif->message(fd, msg_txt(98)); // Monster database has been reloaded. + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(reloadskilldb) +ACMD(reloadskilldb) { nullpo_retr(-1, sd); - skill_reload(); - merc_skill_reload(); + skill->reload(); + homun->reload_skill(); reload_elemental_skilldb(); read_mercenary_skilldb(); - clif_displaymessage(fd, msg_txt(99)); // Skill database has been reloaded. - - return 0; + clif->message(fd, msg_txt(99)); // Skill database has been reloaded. + + return true; } /*========================================== * @reloadatcommand - reloads conf/atcommand.conf conf/groups.conf *------------------------------------------*/ void atcommand_doload(); -ACMD_FUNC(reloadatcommand) { +ACMD(reloadatcommand) { config_t run_test; - + if (conf_read_file(&run_test, "conf/groups.conf")) { - clif_displaymessage(fd, msg_txt(1036)); // Error reading groups.conf, reload failed. - return -1; + clif->message(fd, msg_txt(1036)); // Error reading groups.conf, reload failed. + return false; } - + config_destroy(&run_test); - + if (conf_read_file(&run_test, ATCOMMAND_CONF_FILENAME)) { - clif_displaymessage(fd, msg_txt(1037)); // Error reading atcommand.conf, reload failed. - return -1; + clif->message(fd, msg_txt(1037)); // Error reading atcommand.conf, reload failed. + return false; } - + config_destroy(&run_test); - + atcommand_doload(); pc_groups_reload(); - clif_displaymessage(fd, msg_txt(254)); - return 0; + clif->message(fd, msg_txt(254)); + return true; } /*========================================== * @reloadbattleconf - reloads /conf/battle.conf *------------------------------------------*/ -ACMD_FUNC(reloadbattleconf) +ACMD(reloadbattleconf) { struct Battle_Config prev_config; memcpy(&prev_config, &battle_config, sizeof(prev_config)); - - battle_config_read(BATTLE_CONF_FILENAME); - + + battle->config_read(BATTLE_CONF_FILENAME); + if( prev_config.item_rate_mvp != battle_config.item_rate_mvp - || prev_config.item_rate_common != battle_config.item_rate_common - || prev_config.item_rate_common_boss != battle_config.item_rate_common_boss - || prev_config.item_rate_card != battle_config.item_rate_card - || prev_config.item_rate_card_boss != battle_config.item_rate_card_boss - || prev_config.item_rate_equip != battle_config.item_rate_equip - || prev_config.item_rate_equip_boss != battle_config.item_rate_equip_boss - || prev_config.item_rate_heal != battle_config.item_rate_heal - || prev_config.item_rate_heal_boss != battle_config.item_rate_heal_boss - || prev_config.item_rate_use != battle_config.item_rate_use - || prev_config.item_rate_use_boss != battle_config.item_rate_use_boss - || prev_config.item_rate_treasure != battle_config.item_rate_treasure - || prev_config.item_rate_adddrop != battle_config.item_rate_adddrop - || prev_config.logarithmic_drops != battle_config.logarithmic_drops - || prev_config.item_drop_common_min != battle_config.item_drop_common_min - || prev_config.item_drop_common_max != battle_config.item_drop_common_max - || prev_config.item_drop_card_min != battle_config.item_drop_card_min - || prev_config.item_drop_card_max != battle_config.item_drop_card_max - || prev_config.item_drop_equip_min != battle_config.item_drop_equip_min - || prev_config.item_drop_equip_max != battle_config.item_drop_equip_max - || prev_config.item_drop_mvp_min != battle_config.item_drop_mvp_min - || prev_config.item_drop_mvp_max != battle_config.item_drop_mvp_max - || prev_config.item_drop_heal_min != battle_config.item_drop_heal_min - || prev_config.item_drop_heal_max != battle_config.item_drop_heal_max - || prev_config.item_drop_use_min != battle_config.item_drop_use_min - || prev_config.item_drop_use_max != battle_config.item_drop_use_max - || prev_config.item_drop_treasure_min != battle_config.item_drop_treasure_min - || prev_config.item_drop_treasure_max != battle_config.item_drop_treasure_max - || prev_config.base_exp_rate != battle_config.base_exp_rate - || prev_config.job_exp_rate != battle_config.job_exp_rate - ) + || prev_config.item_rate_common != battle_config.item_rate_common + || prev_config.item_rate_common_boss != battle_config.item_rate_common_boss + || prev_config.item_rate_card != battle_config.item_rate_card + || prev_config.item_rate_card_boss != battle_config.item_rate_card_boss + || prev_config.item_rate_equip != battle_config.item_rate_equip + || prev_config.item_rate_equip_boss != battle_config.item_rate_equip_boss + || prev_config.item_rate_heal != battle_config.item_rate_heal + || prev_config.item_rate_heal_boss != battle_config.item_rate_heal_boss + || prev_config.item_rate_use != battle_config.item_rate_use + || prev_config.item_rate_use_boss != battle_config.item_rate_use_boss + || prev_config.item_rate_treasure != battle_config.item_rate_treasure + || prev_config.item_rate_adddrop != battle_config.item_rate_adddrop + || prev_config.logarithmic_drops != battle_config.logarithmic_drops + || prev_config.item_drop_common_min != battle_config.item_drop_common_min + || prev_config.item_drop_common_max != battle_config.item_drop_common_max + || prev_config.item_drop_card_min != battle_config.item_drop_card_min + || prev_config.item_drop_card_max != battle_config.item_drop_card_max + || prev_config.item_drop_equip_min != battle_config.item_drop_equip_min + || prev_config.item_drop_equip_max != battle_config.item_drop_equip_max + || prev_config.item_drop_mvp_min != battle_config.item_drop_mvp_min + || prev_config.item_drop_mvp_max != battle_config.item_drop_mvp_max + || prev_config.item_drop_heal_min != battle_config.item_drop_heal_min + || prev_config.item_drop_heal_max != battle_config.item_drop_heal_max + || prev_config.item_drop_use_min != battle_config.item_drop_use_min + || prev_config.item_drop_use_max != battle_config.item_drop_use_max + || prev_config.item_drop_treasure_min != battle_config.item_drop_treasure_min + || prev_config.item_drop_treasure_max != battle_config.item_drop_treasure_max + || prev_config.base_exp_rate != battle_config.base_exp_rate + || prev_config.job_exp_rate != battle_config.job_exp_rate + ) { // Exp or Drop rates changed. mob_reload(); //Needed as well so rate changes take effect. chrif_ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common); } - clif_displaymessage(fd, msg_txt(255)); - return 0; + clif->message(fd, msg_txt(255)); + return true; } /*========================================== * @reloadstatusdb - reloads job_db1.txt job_db2.txt job_db2-2.txt refine_db.txt size_fix.txt *------------------------------------------*/ -ACMD_FUNC(reloadstatusdb) +ACMD(reloadstatusdb) { status_readdb(); - clif_displaymessage(fd, msg_txt(256)); - return 0; + clif->message(fd, msg_txt(256)); + return true; } /*========================================== * @reloadpcdb - reloads exp.txt skill_tree.txt attr_fix.txt statpoint.txt *------------------------------------------*/ -ACMD_FUNC(reloadpcdb) +ACMD(reloadpcdb) { pc_readdb(); - clif_displaymessage(fd, msg_txt(257)); - return 0; + clif->message(fd, msg_txt(257)); + return true; } /*========================================== * @reloadmotd - reloads motd.txt *------------------------------------------*/ -ACMD_FUNC(reloadmotd) +ACMD(reloadmotd) { pc_read_motd(); - clif_displaymessage(fd, msg_txt(268)); - return 0; + clif->message(fd, msg_txt(268)); + return true; } /*========================================== * @reloadscript - reloads all scripts (npcs, warps, mob spawns, ...) *------------------------------------------*/ -ACMD_FUNC(reloadscript) +ACMD(reloadscript) { nullpo_retr(-1, sd); //atcommand_broadcast( fd, sd, "@broadcast", "Server is reloading scripts..." ); //atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" ); - + flush_fifos(); map_reloadnpc(true); // reload config files seeking for npcs script_reload(); npc_reload(); - - clif_displaymessage(fd, msg_txt(100)); // Scripts have been reloaded. - - return 0; + + clif->message(fd, msg_txt(100)); // Scripts have been reloaded. + + return true; } /*========================================== @@ -3795,69 +3748,74 @@ ACMD_FUNC(reloadscript) * 0 = no additional information * 1 = Show users in that map and their location * 2 = Shows NPCs in that map - * 3 = Shows the shops/chats in that map (not implemented) + * 3 = Shows the chats in that map + TODO# add the missing mapflags e.g. adjust_skill_damage to display *------------------------------------------*/ -ACMD_FUNC(mapinfo) -{ +ACMD(mapinfo) { struct map_session_data* pl_sd; struct s_mapiterator* iter; struct npc_data *nd = NULL; struct chat_data *cd = NULL; char direction[12]; - int i, m_id, chat_num, list = 0; + int i, m_id, chat_num = 0, list = 0, vend_num = 0; unsigned short m_index; char mapname[24]; - + nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(mapname, '\0', sizeof(mapname)); memset(direction, '\0', sizeof(direction)); - + sscanf(message, "%d %23[^\n]", &list, mapname); - + if (list < 0 || list > 3) { - clif_displaymessage(fd, msg_txt(1038)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). - return -1; + clif->message(fd, msg_txt(1038)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). + return false; } - + if (mapname[0] == '\0') { safestrncpy(mapname, mapindex_id2name(sd->mapindex), MAP_NAME_LENGTH); m_id = map_mapindex2mapid(sd->mapindex); } else { m_id = map_mapname2mapid(mapname); } - + if (m_id < 0) { - clif_displaymessage(fd, msg_txt(1)); // Map not found. - return -1; + clif->message(fd, msg_txt(1)); // Map not found. + return false; } m_index = mapindex_name2id(mapname); //This one shouldn't fail since the previous seek did not. - - clif_displaymessage(fd, msg_txt(1039)); // ------ Map Info ------ - + + clif->message(fd, msg_txt(1039)); // ------ Map Info ------ + // count chats (for initial message) chat_num = 0; iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) - if( (cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) != NULL && pl_sd->mapindex == m_index && cd->usersd[0] == pl_sd ) - chat_num++; - mapit_free(iter); - - sprintf(atcmd_output, msg_txt(1040), mapname, map[m_id].users, map[m_id].npc_num, chat_num); // Map Name: %s | Players In Map: %d | NPCs In Map: %d | Chats In Map: %d - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1041)); // ------ Map Flags ------ + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { + if( pl_sd->mapindex == m_index ) { + if( pl_sd->state.vending ) + vend_num++; + else if( (cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) != NULL && cd->usersd[0] == pl_sd ) + chat_num++; + } + } + mapit->free(iter); + + sprintf(atcmd_output, msg_txt(1040), mapname, map[m_id].zone->name, map[m_id].users, map[m_id].npc_num, chat_num, vend_num); // Map: %s (Zone:%s) | Players: %d | NPCs: %d | Chats: %d | Vendings: %d + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1041)); // ------ Map Flags ------ if (map[m_id].flag.town) - clif_displaymessage(fd, msg_txt(1042)); // Town Map - + clif->message(fd, msg_txt(1042)); // Town Map + if (battle_config.autotrade_mapflag == map[m_id].flag.autotrade) - clif_displaymessage(fd, msg_txt(1043)); // Autotrade Enabled + clif->message(fd, msg_txt(1043)); // Autotrade Enabled else - clif_displaymessage(fd, msg_txt(1044)); // Autotrade Disabled - + clif->message(fd, msg_txt(1044)); // Autotrade Disabled + if (map[m_id].flag.battleground) - clif_displaymessage(fd, msg_txt(1045)); // Battlegrounds ON - + clif->message(fd, msg_txt(1045)); // Battlegrounds ON + strcpy(atcmd_output,msg_txt(1046)); // PvP Flags: if (map[m_id].flag.pvp) strcat(atcmd_output, msg_txt(1047)); // Pvp ON | @@ -3869,8 +3827,8 @@ ACMD_FUNC(mapinfo) strcat(atcmd_output, msg_txt(1050)); // NightmareDrop | if (map[m_id].flag.pvp_nocalcrank) strcat(atcmd_output, msg_txt(1051)); // NoCalcRank | - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + strcpy(atcmd_output,msg_txt(1052)); // GvG Flags: if (map[m_id].flag.gvg) strcat(atcmd_output, msg_txt(1053)); // GvG ON | @@ -3880,8 +3838,8 @@ ACMD_FUNC(mapinfo) strcat(atcmd_output, msg_txt(1055)); // GvG Castle | if (map[m_id].flag.gvg_noparty) strcat(atcmd_output, msg_txt(1056)); // NoParty | - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + strcpy(atcmd_output,msg_txt(1057)); // Teleport Flags: if (map[m_id].flag.noteleport) strcat(atcmd_output, msg_txt(1058)); // NoTeleport | @@ -3893,30 +3851,28 @@ ACMD_FUNC(mapinfo) strcat(atcmd_output, msg_txt(1061)); // NoWarpTo | if (map[m_id].flag.noreturn) strcat(atcmd_output, msg_txt(1062)); // NoReturn | - if (map[m_id].flag.nogo) - strcat(atcmd_output, msg_txt(1063)); // NoGo | if (map[m_id].flag.nomemo) strcat(atcmd_output, msg_txt(1064)); // NoMemo | - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1065), // No Exp Penalty: %s | No Zeny Penalty: %s - (map[m_id].flag.noexppenalty) ? msg_txt(1066) : msg_txt(1067), (map[m_id].flag.nozenypenalty) ? msg_txt(1066) : msg_txt(1067)); // On / Off - clif_displaymessage(fd, atcmd_output); - + (map[m_id].flag.noexppenalty) ? msg_txt(1066) : msg_txt(1067), (map[m_id].flag.nozenypenalty) ? msg_txt(1066) : msg_txt(1067)); // On / Off + clif->message(fd, atcmd_output); + if (map[m_id].flag.nosave) { if (!map[m_id].save.map) - clif_displaymessage(fd, msg_txt(1068)); // No Save (Return to last Save Point) + clif->message(fd, msg_txt(1068)); // No Save (Return to last Save Point) else if (map[m_id].save.x == -1 || map[m_id].save.y == -1 ) { sprintf(atcmd_output, msg_txt(1069), mapindex_id2name(map[m_id].save.map)); // No Save, Save Point: %s,Random - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } else { sprintf(atcmd_output, msg_txt(1070), // No Save, Save Point: %s,%d,%d - mapindex_id2name(map[m_id].save.map),map[m_id].save.x,map[m_id].save.y); - clif_displaymessage(fd, atcmd_output); + mapindex_id2name(map[m_id].save.map),map[m_id].save.x,map[m_id].save.y); + clif->message(fd, atcmd_output); } } - + strcpy(atcmd_output,msg_txt(1071)); // Weather Flags: if (map[m_id].flag.snow) strcat(atcmd_output, msg_txt(1072)); // Snow | @@ -3932,15 +3888,10 @@ ACMD_FUNC(mapinfo) strcat(atcmd_output, msg_txt(1077)); // Fireworks | if (map[m_id].flag.leaves) strcat(atcmd_output, msg_txt(1078)); // Leaves | - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //if (map[m_id].flag.rain) - // strcat(atcmd_output, msg_txt(1079)); // Rain | if (map[m_id].flag.nightenabled) strcat(atcmd_output, msg_txt(1080)); // Displays Night | - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + strcpy(atcmd_output,msg_txt(1081)); // Other Flags: if (map[m_id].flag.nobranch) strcat(atcmd_output, msg_txt(1082)); // NoBranch | @@ -3958,8 +3909,8 @@ ACMD_FUNC(mapinfo) strcat(atcmd_output, msg_txt(1088)); // AllowKS | if (map[m_id].flag.reset) strcat(atcmd_output, msg_txt(1089)); // Reset | - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + strcpy(atcmd_output,msg_txt(1090)); // Other Flags: if (map[m_id].nocommand) strcat(atcmd_output, msg_txt(1091)); // NoCommand | @@ -3975,411 +3926,411 @@ ACMD_FUNC(mapinfo) strcat(atcmd_output, msg_txt(1096)); // PartyLock | if (map[m_id].flag.guildlock) strcat(atcmd_output, msg_txt(1097)); // GuildLock | - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + switch (list) { - case 0: - // Do nothing. It's list 0, no additional display. - break; - case 1: - clif_displaymessage(fd, msg_txt(1098)); // ----- Players in Map ----- - iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) - { - if (pl_sd->mapindex == m_index) { - sprintf(atcmd_output, msg_txt(1099), // Player '%s' (session #%d) | Location: %d,%d - pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y); - clif_displaymessage(fd, atcmd_output); + case 0: + // Do nothing. It's list 0, no additional display. + break; + case 1: + clif->message(fd, msg_txt(1098)); // ----- Players in Map ----- + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) + { + if (pl_sd->mapindex == m_index) { + sprintf(atcmd_output, msg_txt(1099), // Player '%s' (session #%d) | Location: %d,%d + pl_sd->status.name, pl_sd->fd, pl_sd->bl.x, pl_sd->bl.y); + clif->message(fd, atcmd_output); + } } - } - mapit_free(iter); - break; - case 2: - clif_displaymessage(fd, msg_txt(1100)); // ----- NPCs in Map ----- - for (i = 0; i < map[m_id].npc_num;) - { - nd = map[m_id].npc[i]; - switch(nd->ud.dir) { - case 0: strcpy(direction, msg_txt(1101)); break; // North - case 1: strcpy(direction, msg_txt(1102)); break; // North West - case 2: strcpy(direction, msg_txt(1103)); break; // West - case 3: strcpy(direction, msg_txt(1104)); break; // South West - case 4: strcpy(direction, msg_txt(1105)); break; // South - case 5: strcpy(direction, msg_txt(1106)); break; // South East - case 6: strcpy(direction, msg_txt(1107)); break; // East - case 7: strcpy(direction, msg_txt(1108)); break; // North East - case 9: strcpy(direction, msg_txt(1109)); break; // North - default: strcpy(direction, msg_txt(1110)); break; // Unknown + mapit->free(iter); + break; + case 2: + clif->message(fd, msg_txt(1100)); // ----- NPCs in Map ----- + for (i = 0; i < map[m_id].npc_num;) + { + nd = map[m_id].npc[i]; + switch(nd->ud.dir) { + case 0: strcpy(direction, msg_txt(1101)); break; // North + case 1: strcpy(direction, msg_txt(1102)); break; // North West + case 2: strcpy(direction, msg_txt(1103)); break; // West + case 3: strcpy(direction, msg_txt(1104)); break; // South West + case 4: strcpy(direction, msg_txt(1105)); break; // South + case 5: strcpy(direction, msg_txt(1106)); break; // South East + case 6: strcpy(direction, msg_txt(1107)); break; // East + case 7: strcpy(direction, msg_txt(1108)); break; // North East + case 9: strcpy(direction, msg_txt(1109)); break; // North + default: strcpy(direction, msg_txt(1110)); break; // Unknown + } + if(strcmp(nd->name,nd->exname) == 0) + sprintf(atcmd_output, msg_txt(1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d + ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y); + else + sprintf(atcmd_output, msg_txt(1112), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d + ++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y); + clif->message(fd, atcmd_output); } - if(strcmp(nd->name,nd->exname) == 0) - sprintf(atcmd_output, msg_txt(1111), // NPC %d: %s | Direction: %s | Sprite: %d | Location: %d %d - ++i, nd->name, direction, nd->class_, nd->bl.x, nd->bl.y); - else - sprintf(atcmd_output, msg_txt(1112), // NPC %d: %s::%s | Direction: %s | Sprite: %d | Location: %d %d - ++i, nd->name, nd->exname, direction, nd->class_, nd->bl.x, nd->bl.y); - clif_displaymessage(fd, atcmd_output); - } - break; - case 3: - clif_displaymessage(fd, msg_txt(1113)); // ----- Chats in Map ----- - iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) - { - if ((cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) != NULL && - pl_sd->mapindex == m_index && - cd->usersd[0] == pl_sd) + break; + case 3: + clif->message(fd, msg_txt(1113)); // ----- Chats in Map ----- + iter = mapit_getallusers(); + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { - sprintf(atcmd_output, msg_txt(1114), // Chat: %s | Player: %s | Location: %d %d - cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y); - clif_displaymessage(fd, atcmd_output); - sprintf(atcmd_output, msg_txt(1115), // Users: %d/%d | Password: %s | Public: %s - cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(1116) : msg_txt(1117)); // Yes / No - clif_displaymessage(fd, atcmd_output); + if ((cd = (struct chat_data*)map_id2bl(pl_sd->chatID)) != NULL && + pl_sd->mapindex == m_index && + cd->usersd[0] == pl_sd) + { + sprintf(atcmd_output, msg_txt(1114), // Chat: %s | Player: %s | Location: %d %d + cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y); + clif->message(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1115), // Users: %d/%d | Password: %s | Public: %s + cd->users, cd->limit, cd->pass, (cd->pub) ? msg_txt(1116) : msg_txt(1117)); // Yes / No + clif->message(fd, atcmd_output); + } } - } - mapit_free(iter); - break; - default: // normally impossible to arrive here - clif_displaymessage(fd, msg_txt(1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). - return -1; - break; + mapit->free(iter); + break; + default: // normally impossible to arrive here + clif->message(fd, msg_txt(1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>). + return false; + break; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(mount_peco) +ACMD(mount_peco) { nullpo_retr(-1, sd); - - if (sd->disguise) { - clif_displaymessage(fd, msg_txt(212)); // Cannot mount while in disguise. - return -1; + + if (sd->disguise != -1) { + clif->message(fd, msg_txt(212)); // Cannot mount while in disguise. + return false; } - + if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT && pc_checkskill(sd,RK_DRAGONTRAINING) > 0 ) { if( !(sd->sc.option&OPTION_DRAGON1) ) { - clif_displaymessage(sd->fd,msg_txt(1119)); // You have mounted your Dragon. + clif->message(sd->fd,msg_txt(1119)); // You have mounted your Dragon. pc_setoption(sd, sd->sc.option|OPTION_DRAGON1); } else { - clif_displaymessage(sd->fd,msg_txt(1120)); // You have released your Dragon. + clif->message(sd->fd,msg_txt(1120)); // You have released your Dragon. pc_setoption(sd, sd->sc.option&~OPTION_DRAGON1); } - return 0; + return true; } if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER && pc_checkskill(sd,RA_WUGRIDER) > 0 ) { if( !pc_isridingwug(sd) ) { - clif_displaymessage(sd->fd,msg_txt(1121)); // You have mounted your Warg. + clif->message(sd->fd,msg_txt(1121)); // You have mounted your Warg. pc_setoption(sd, sd->sc.option|OPTION_WUGRIDER); } else { - clif_displaymessage(sd->fd,msg_txt(1122)); // You have released your Warg. + clif->message(sd->fd,msg_txt(1122)); // You have released your Warg. pc_setoption(sd, sd->sc.option&~OPTION_WUGRIDER); } - return 0; + return true; } if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) { if( !pc_ismadogear(sd) ) { - clif_displaymessage(sd->fd,msg_txt(1123)); // You have mounted your Mado Gear. + clif->message(sd->fd,msg_txt(1123)); // You have mounted your Mado Gear. pc_setoption(sd, sd->sc.option|OPTION_MADOGEAR); } else { - clif_displaymessage(sd->fd,msg_txt(1124)); // You have released your Mado Gear. + clif->message(sd->fd,msg_txt(1124)); // You have released your Mado Gear. pc_setoption(sd, sd->sc.option&~OPTION_MADOGEAR); } - return 0; + return true; } if (!pc_isriding(sd)) { // if actually no peco - + if (!pc_checkskill(sd, KN_RIDING)) { - clif_displaymessage(fd, msg_txt(213)); // You can not mount a Peco Peco with your current job. - return -1; + clif->message(fd, msg_txt(213)); // You can not mount a Peco Peco with your current job. + return false; } - + pc_setoption(sd, sd->sc.option | OPTION_RIDING); - clif_displaymessage(fd, msg_txt(102)); // You have mounted a Peco Peco. + clif->message(fd, msg_txt(102)); // You have mounted a Peco Peco. } else {//Dismount pc_setoption(sd, sd->sc.option & ~OPTION_RIDING); - clif_displaymessage(fd, msg_txt(214)); // You have released your Peco Peco. + clif->message(fd, msg_txt(214)); // You have released your Peco Peco. } - - return 0; + + return true; } /*========================================== *Spy Commands by Syrus22 *------------------------------------------*/ -ACMD_FUNC(guildspy) +ACMD(guildspy) { char guild_name[NAME_LENGTH]; struct guild *g; nullpo_retr(-1, sd); - + memset(guild_name, '\0', sizeof(guild_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!enable_spy) { - clif_displaymessage(fd, msg_txt(1125)); // The mapserver has spy command support disabled. - return -1; + clif->message(fd, msg_txt(1125)); // The mapserver has spy command support disabled. + return false; } if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { - clif_displaymessage(fd, msg_txt(1126)); // Please enter a guild name/ID (usage: @guildspy <guild_name/ID>). - return -1; + clif->message(fd, msg_txt(1126)); // Please enter a guild name/ID (usage: @guildspy <guild_name/ID>). + return false; } - - if ((g = guild_searchname(guild_name)) != NULL || // name first to avoid error when name begin with a number - (g = guild_search(atoi(message))) != NULL) { + + if ((g = guild->searchname(guild_name)) != NULL || // name first to avoid error when name begin with a number + (g = guild->search(atoi(message))) != NULL) { if (sd->guildspy == g->guild_id) { sd->guildspy = 0; sprintf(atcmd_output, msg_txt(103), g->name); // No longer spying on the %s guild. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } else { sd->guildspy = g->guild_id; sprintf(atcmd_output, msg_txt(104), g->name); // Spying on the %s guild. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } } else { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the specified guild is online. - return -1; + clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the specified guild is online. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(partyspy) +ACMD(partyspy) { char party_name[NAME_LENGTH]; struct party_data *p; nullpo_retr(-1, sd); - + memset(party_name, '\0', sizeof(party_name)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!enable_spy) { - clif_displaymessage(fd, msg_txt(1125)); // The mapserver has spy command support disabled. - return -1; + clif->message(fd, msg_txt(1125)); // The mapserver has spy command support disabled. + return false; } - + if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) { - clif_displaymessage(fd, msg_txt(1127)); // Please enter a party name/ID (usage: @partyspy <party_name/ID>). - return -1; + clif->message(fd, msg_txt(1127)); // Please enter a party name/ID (usage: @partyspy <party_name/ID>). + return false; } - + if ((p = party_searchname(party_name)) != NULL || // name first to avoid error when name begin with a number (p = party_search(atoi(message))) != NULL) { if (sd->partyspy == p->party.party_id) { sd->partyspy = 0; sprintf(atcmd_output, msg_txt(105), p->party.name); // No longer spying on the %s party. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } else { sd->partyspy = p->party.party_id; sprintf(atcmd_output, msg_txt(106), p->party.name); // Spying on the %s party. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } } else { - clif_displaymessage(fd, msg_txt(96)); // Incorrect name/ID, or no one from the specified party is online. - return -1; + clif->message(fd, msg_txt(96)); // Incorrect name/ID, or no one from the specified party is online. + return false; } - - return 0; + + return true; } /*========================================== * @repairall [Valaris] *------------------------------------------*/ -ACMD_FUNC(repairall) +ACMD(repairall) { int count, i; nullpo_retr(-1, sd); - + count = 0; for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute == 1) { sd->status.inventory[i].attribute = 0; - clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); + clif->produce_effect(sd, 0, sd->status.inventory[i].nameid); count++; } } - + if (count > 0) { - clif_misceffect(&sd->bl, 3); - clif_equiplist(sd); - clif_displaymessage(fd, msg_txt(107)); // All items have been repaired. + clif->misceffect(&sd->bl, 3); + clif->equiplist(sd); + clif->message(fd, msg_txt(107)); // All items have been repaired. } else { - clif_displaymessage(fd, msg_txt(108)); // No item need to be repaired. - return -1; + clif->message(fd, msg_txt(108)); // No item need to be repaired. + return false; } - - return 0; + + return true; } /*========================================== * @nuke [Valaris] *------------------------------------------*/ -ACMD_FUNC(nuke) +ACMD(nuke) { struct map_session_data *pl_sd; nullpo_retr(-1, sd); - + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1128)); // Please enter a player name (usage: @nuke <char name>). - return -1; + clif->message(fd, msg_txt(1128)); // Please enter a player name (usage: @nuke <char name>). + return false; } - + if ((pl_sd = map_nick2sd(atcmd_player_name)) != NULL) { if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kill only lower or same GM level - skill_castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, gettick(), 0); - clif_displaymessage(fd, msg_txt(109)); // Player has been nuked! + skill->castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, gettick(), 0); + clif->message(fd, msg_txt(109)); // Player has been nuked! } else { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; + clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return false; } } else { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - - return 0; + + return true; } /*========================================== * @tonpc *------------------------------------------*/ -ACMD_FUNC(tonpc) +ACMD(tonpc) { char npcname[NAME_LENGTH+1]; struct npc_data *nd; - + nullpo_retr(-1, sd); - + memset(npcname, 0, sizeof(npcname)); - + if (!message || !*message || sscanf(message, "%23[^\n]", npcname) < 1) { - clif_displaymessage(fd, msg_txt(1129)); // Please enter a NPC name (usage: @tonpc <NPC_name>). - return -1; + clif->message(fd, msg_txt(1129)); // Please enter a NPC name (usage: @tonpc <NPC_name>). + return false; } - + if ((nd = npc_name2id(npcname)) != NULL) { if (pc_setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0) - clif_displaymessage(fd, msg_txt(0)); // Warped. + clif->message(fd, msg_txt(0)); // Warped. else - return -1; + return false; } else { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; + clif->message(fd, msg_txt(111)); // This NPC doesn't exist. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(shownpc) +ACMD(shownpc) { char NPCname[NAME_LENGTH+1]; nullpo_retr(-1, sd); - + memset(NPCname, '\0', sizeof(NPCname)); - + if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { - clif_displaymessage(fd, msg_txt(1130)); // Please enter a NPC name (usage: @enablenpc <NPC_name>). - return -1; + clif->message(fd, msg_txt(1130)); // Please enter a NPC name (usage: @enablenpc <NPC_name>). + return false; } - + if (npc_name2id(NPCname) != NULL) { npc_enable(NPCname, 1); - clif_displaymessage(fd, msg_txt(110)); // Npc Enabled. + clif->message(fd, msg_txt(110)); // Npc Enabled. } else { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; + clif->message(fd, msg_txt(111)); // This NPC doesn't exist. + return false; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(hidenpc) +ACMD(hidenpc) { char NPCname[NAME_LENGTH+1]; nullpo_retr(-1, sd); - + memset(NPCname, '\0', sizeof(NPCname)); - + if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) { - clif_displaymessage(fd, msg_txt(1131)); // Please enter a NPC name (usage: @hidenpc <NPC_name>). - return -1; + clif->message(fd, msg_txt(1131)); // Please enter a NPC name (usage: @hidenpc <NPC_name>). + return false; } - + if (npc_name2id(NPCname) == NULL) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; + clif->message(fd, msg_txt(111)); // This NPC doesn't exist. + return false; } - + npc_enable(NPCname, 0); - clif_displaymessage(fd, msg_txt(112)); // Npc Disabled. - return 0; + clif->message(fd, msg_txt(112)); // Npc Disabled. + return true; } -ACMD_FUNC(loadnpc) +ACMD(loadnpc) { FILE *fp; - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1132)); // Please enter a script file name (usage: @loadnpc <file name>). - return -1; + clif->message(fd, msg_txt(1132)); // Please enter a script file name (usage: @loadnpc <file name>). + return false; } - + // check if script file exists if ((fp = fopen(message, "r")) == NULL) { - clif_displaymessage(fd, msg_txt(261)); - return -1; + clif->message(fd, msg_txt(261)); + return false; } fclose(fp); - + // add to list of script sources and run it npc_addsrcfile(message); npc_parsesrcfile(message,true); npc_read_event_script(); - - clif_displaymessage(fd, msg_txt(262)); - - return 0; + + clif->message(fd, msg_txt(262)); + + return true; } -ACMD_FUNC(unloadnpc) +ACMD(unloadnpc) { struct npc_data *nd; char NPCname[NAME_LENGTH+1]; nullpo_retr(-1, sd); - + memset(NPCname, '\0', sizeof(NPCname)); - + if (!message || !*message || sscanf(message, "%24[^\n]", NPCname) < 1) { - clif_displaymessage(fd, msg_txt(1133)); // Please enter a NPC name (usage: @npcoff <NPC_name>). - return -1; + clif->message(fd, msg_txt(1133)); // Please enter a NPC name (usage: @npcoff <NPC_name>). + return false; } - + if ((nd = npc_name2id(NPCname)) == NULL) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; + clif->message(fd, msg_txt(111)); // This NPC doesn't exist. + return false; } - + npc_unload_duplicates(nd); npc_unload(nd,true); npc_read_event_script(); - clif_displaymessage(fd, msg_txt(112)); // Npc Disabled. - return 0; + clif->message(fd, msg_txt(112)); // Npc Disabled. + return true; } /*========================================== @@ -4390,17 +4341,17 @@ char* txt_time(unsigned int duration) int days, hours, minutes, seconds; char temp[CHAT_SIZE_MAX]; static char temp1[CHAT_SIZE_MAX]; - + memset(temp, '\0', sizeof(temp)); memset(temp1, '\0', sizeof(temp1)); - + days = duration / (60 * 60 * 24); duration = duration - (60 * 60 * 24 * days); hours = duration / (60 * 60); duration = duration - (60 * 60 * hours); minutes = duration / 60; seconds = duration - (60 * minutes); - + if (days == 1) sprintf(temp, msg_txt(219), days); // %d day else if (days > 1) @@ -4417,7 +4368,7 @@ char* txt_time(unsigned int duration) sprintf(temp1, msg_txt(225), temp, seconds); // %s and %d second else if (seconds > 1) sprintf(temp1, msg_txt(226), temp, seconds); // %s and %d seconds - + return temp1; } @@ -4425,7 +4376,7 @@ char* txt_time(unsigned int duration) * @time/@date/@serverdate/@servertime: Display the date/time of the server (by [Yor] * Calculation management of GM modification (@day/@night GM commands) is done *------------------------------------------*/ -ACMD_FUNC(servertime) +ACMD(servertime) { const struct TimerData * timer_data; const struct TimerData * timer_data2; @@ -4433,65 +4384,65 @@ ACMD_FUNC(servertime) struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ... char temp[CHAT_SIZE_MAX]; nullpo_retr(-1, sd); - + memset(temp, '\0', sizeof(temp)); - + time(&time_server); // get time in seconds since 1/1/1970 datetime = localtime(&time_server); // convert seconds in structure // like sprintf, but only for date/time (Sunday, November 02 2003 15:12:52) strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X. - clif_displaymessage(fd, temp); - + clif->message(fd, temp); + if (battle_config.night_duration == 0 && battle_config.day_duration == 0) { if (night_flag == 0) - clif_displaymessage(fd, msg_txt(231)); // Game time: The game is in permanent daylight. + clif->message(fd, msg_txt(231)); // Game time: The game is in permanent daylight. else - clif_displaymessage(fd, msg_txt(232)); // Game time: The game is in permanent night. + clif->message(fd, msg_txt(232)); // Game time: The game is in permanent night. } else if (battle_config.night_duration == 0) if (night_flag == 1) { // we start with night timer_data = get_timer(day_timer_tid); sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in night for %s. - clif_displaymessage(fd, temp); - clif_displaymessage(fd, msg_txt(234)); // Game time: After, the game will be in permanent daylight. - } else - clif_displaymessage(fd, msg_txt(231)); // Game time: The game is in permanent daylight. - else if (battle_config.day_duration == 0) - if (night_flag == 0) { // we start with day - timer_data = get_timer(night_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. - clif_displaymessage(fd, temp); - clif_displaymessage(fd, msg_txt(236)); // Game time: After, the game will be in permanent night. + clif->message(fd, temp); + clif->message(fd, msg_txt(234)); // Game time: After, the game will be in permanent daylight. } else - clif_displaymessage(fd, msg_txt(232)); // Game time: The game is in permanent night. - else { - if (night_flag == 0) { - timer_data = get_timer(night_timer_tid); - timer_data2 = get_timer(day_timer_tid); - sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. - clif_displaymessage(fd, temp); - if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0) - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)); // Game time: After, the game will be in night for %s. - else - sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)); // Game time: After, the game will be in night for %s. - clif_displaymessage(fd, temp); - sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. - clif_displaymessage(fd, temp); - } else { - timer_data = get_timer(day_timer_tid); - timer_data2 = get_timer(night_timer_tid); - sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,gettick()) / 1000)); // Game time: The game is actualy in night for %s. - clif_displaymessage(fd, temp); - if (DIFF_TICK(timer_data->tick,timer_data2->tick) > 0) - sprintf(temp, msg_txt(239), txt_time((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000)); // Game time: After, the game will be in daylight for %s. - else - sprintf(temp, msg_txt(239), txt_time(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000)); // Game time: After, the game will be in daylight for %s. - clif_displaymessage(fd, temp); - sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. - clif_displaymessage(fd, temp); - } - } - - return 0; + clif->message(fd, msg_txt(231)); // Game time: The game is in permanent daylight. + else if (battle_config.day_duration == 0) + if (night_flag == 0) { // we start with day + timer_data = get_timer(night_timer_tid); + sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. + clif->message(fd, temp); + clif->message(fd, msg_txt(236)); // Game time: After, the game will be in permanent night. + } else + clif->message(fd, msg_txt(232)); // Game time: The game is in permanent night. + else { + if (night_flag == 0) { + timer_data = get_timer(night_timer_tid); + timer_data2 = get_timer(day_timer_tid); + sprintf(temp, msg_txt(235), txt_time(DIFF_TICK(timer_data->tick,gettick())/1000)); // Game time: The game is actualy in daylight for %s. + clif->message(fd, temp); + if (DIFF_TICK(timer_data->tick, timer_data2->tick) > 0) + sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data->interval,DIFF_TICK(timer_data->tick,timer_data2->tick)) / 1000)); // Game time: After, the game will be in night for %s. + else + sprintf(temp, msg_txt(237), txt_time(DIFF_TICK(timer_data2->tick,timer_data->tick)/1000)); // Game time: After, the game will be in night for %s. + clif->message(fd, temp); + sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. + clif->message(fd, temp); + } else { + timer_data = get_timer(day_timer_tid); + timer_data2 = get_timer(night_timer_tid); + sprintf(temp, msg_txt(233), txt_time(DIFF_TICK(timer_data->tick,gettick()) / 1000)); // Game time: The game is actualy in night for %s. + clif->message(fd, temp); + if (DIFF_TICK(timer_data->tick,timer_data2->tick) > 0) + sprintf(temp, msg_txt(239), txt_time((timer_data->interval - DIFF_TICK(timer_data->tick, timer_data2->tick)) / 1000)); // Game time: After, the game will be in daylight for %s. + else + sprintf(temp, msg_txt(239), txt_time(DIFF_TICK(timer_data2->tick, timer_data->tick) / 1000)); // Game time: After, the game will be in daylight for %s. + clif->message(fd, temp); + sprintf(temp, msg_txt(238), txt_time(timer_data->interval / 1000)); // Game time: A day cycle has a normal duration of %s. + clif->message(fd, temp); + } + } + + return true; } //Added by Coltaro @@ -4503,7 +4454,7 @@ static void get_jail_time(int jailtime, int* year, int* month, int* day, int* ho const int factor_month = 43200; //30*24*60 = 43200 const int factor_day = 1440; //24*60 = 1440 const int factor_hour = 60; - + *year = jailtime/factor_year; jailtime -= *year*factor_year; *month = jailtime/factor_month; @@ -4513,7 +4464,7 @@ static void get_jail_time(int jailtime, int* year, int* month, int* day, int* ho *hour = jailtime/factor_hour; jailtime -= *hour*factor_hour; *minute = jailtime; - + *year = *year > 0? *year : 0; *month = *month > 0? *month : 0; *day = *day > 0? *day : 0; @@ -4526,97 +4477,97 @@ static void get_jail_time(int jailtime, int* year, int* month, int* day, int* ho * @jail <char_name> by [Yor] * Special warp! No check with nowarp and nowarpto flag *------------------------------------------*/ -ACMD_FUNC(jail) +ACMD(jail) { struct map_session_data *pl_sd; int x, y; unsigned short m_index; nullpo_retr(-1, sd); - + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1134)); // Please enter a player name (usage: @jail <char_name>). - return -1; + clif->message(fd, msg_txt(1134)); // Please enter a player name (usage: @jail <char_name>). + return false; } - + if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; + clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return false; } - + if (pl_sd->sc.data[SC_JAILED]) { - clif_displaymessage(fd, msg_txt(118)); // Player warped in jails. - return -1; + clif->message(fd, msg_txt(118)); // Player warped in jails. + return false; } - + switch(rnd() % 2) { //Jail Locations - case 0: - m_index = mapindex_name2id(MAP_JAIL); - x = 24; - y = 75; - break; - default: - m_index = mapindex_name2id(MAP_JAIL); - x = 49; - y = 75; - break; + case 0: + m_index = mapindex_name2id(MAP_JAIL); + x = 24; + y = 75; + break; + default: + m_index = mapindex_name2id(MAP_JAIL); + x = 49; + y = 75; + break; } - + //Duration of INT_MAX to specify infinity. sc_start4(&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000); - clif_displaymessage(pl_sd->fd, msg_txt(117)); // GM has send you in jails. - clif_displaymessage(fd, msg_txt(118)); // Player warped in jails. - return 0; + clif->message(pl_sd->fd, msg_txt(117)); // GM has send you in jails. + clif->message(fd, msg_txt(118)); // Player warped in jails. + return true; } /*========================================== * @unjail/@discharge <char_name> by [Yor] * Special warp! No check with nowarp and nowarpto flag *------------------------------------------*/ -ACMD_FUNC(unjail) +ACMD(unjail) { struct map_session_data *pl_sd; - + memset(atcmd_player_name, '\0', sizeof(atcmd_player_name)); - + if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1135)); // Please enter a player name (usage: @unjail/@discharge <char_name>). - return -1; + clif->message(fd, msg_txt(1135)); // Please enter a player name (usage: @unjail/@discharge <char_name>). + return false; } - + if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM - - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; + + clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return false; } - + if (!pl_sd->sc.data[SC_JAILED]) { - clif_displaymessage(fd, msg_txt(119)); // This player is not in jails. - return -1; + clif->message(fd, msg_txt(119)); // This player is not in jails. + return false; } - + //Reset jail time to 1 sec. sc_start(&pl_sd->bl,SC_JAILED,100,1,1000); - clif_displaymessage(pl_sd->fd, msg_txt(120)); // A GM has discharged you from jail. - clif_displaymessage(fd, msg_txt(121)); // Player unjailed. - return 0; + clif->message(pl_sd->fd, msg_txt(120)); // A GM has discharged you from jail. + clif->message(fd, msg_txt(121)); // Player unjailed. + return true; } -ACMD_FUNC(jailfor) +ACMD(jailfor) { struct map_session_data *pl_sd = NULL; int year, month, day, hour, minute, value; @@ -4624,14 +4575,14 @@ ACMD_FUNC(jailfor) int jailtime = 0,x,y; short m_index = 0; nullpo_retr(-1, sd); - - if (!message || !*message || sscanf(message, "%s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { - clif_displaymessage(fd, msg_txt(400)); //Usage: @jailfor <time> <character name> - return -1; + + if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) { + clif->message(fd, msg_txt(400)); //Usage: @jailfor <time> <character name> + return false; } - + atcmd_output[sizeof(atcmd_output)-1] = '\0'; - + modif_p = atcmd_output; year = month = day = hour = minute = 0; while (modif_p[0] != '\0') { @@ -4666,50 +4617,50 @@ ACMD_FUNC(jailfor) } } } - + if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0) { - clif_displaymessage(fd, msg_txt(1136)); // Invalid time for jail command. - return -1; + clif->message(fd, msg_txt(1136)); // Invalid time for jail command. + return false; } - + if ((pl_sd = map_nick2sd(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; + clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return false; } - + jailtime = year*12*30*24*60 + month*30*24*60 + day*24*60 + hour*60 + minute; //In minutes - + if(jailtime==0) { - clif_displaymessage(fd, msg_txt(1136)); // Invalid time for jail command. - return -1; + clif->message(fd, msg_txt(1136)); // Invalid time for jail command. + return false; } - + //Added by Coltaro if(pl_sd->sc.data[SC_JAILED] && - pl_sd->sc.data[SC_JAILED]->val1 != INT_MAX) + pl_sd->sc.data[SC_JAILED]->val1 != INT_MAX) { //Update the player's jail time jailtime += pl_sd->sc.data[SC_JAILED]->val1; if (jailtime <= 0) { jailtime = 0; - clif_displaymessage(pl_sd->fd, msg_txt(120)); // GM has discharge you. - clif_displaymessage(fd, msg_txt(121)); // Player unjailed + clif->message(pl_sd->fd, msg_txt(120)); // GM has discharge you. + clif->message(fd, msg_txt(121)); // Player unjailed } else { get_jail_time(jailtime,&year,&month,&day,&hour,&minute); sprintf(atcmd_output,msg_txt(402),msg_txt(1137),year,month,day,hour,minute); //%s in jail for %d years, %d months, %d days, %d hours and %d minutes - clif_displaymessage(pl_sd->fd, atcmd_output); + clif->message(pl_sd->fd, atcmd_output); sprintf(atcmd_output,msg_txt(402),msg_txt(1138),year,month,day,hour,minute); //This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } } else if (jailtime < 0) { - clif_displaymessage(fd, msg_txt(1136)); - return -1; + clif->message(fd, msg_txt(1136)); + return false; } - + //Jail locations, add more as you wish. switch(rnd()%2) { @@ -4722,56 +4673,56 @@ ACMD_FUNC(jailfor) x = 24; y = 75; break; } - + sc_start4(&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status_change_timer). - return 0; + return true; } //By Coltaro -ACMD_FUNC(jailtime) +ACMD(jailtime) { int year, month, day, hour, minute; - + nullpo_retr(-1, sd); - + if (!sd->sc.data[SC_JAILED]) { - clif_displaymessage(fd, msg_txt(1139)); // You are not in jail. - return -1; + clif->message(fd, msg_txt(1139)); // You are not in jail. + return false; } - + if (sd->sc.data[SC_JAILED]->val1 == INT_MAX) { - clif_displaymessage(fd, msg_txt(1140)); // You have been jailed indefinitely. - return 0; + clif->message(fd, msg_txt(1140)); // You have been jailed indefinitely. + return true; } - + if (sd->sc.data[SC_JAILED]->val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?) - clif_displaymessage(fd, msg_txt(1141)); // You have been jailed for an unknown amount of time. - return -1; + clif->message(fd, msg_txt(1141)); // You have been jailed for an unknown amount of time. + return false; } - + //Get remaining jail time get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute); sprintf(atcmd_output,msg_txt(402),msg_txt(1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes - - clif_displaymessage(fd, atcmd_output); - - return 0; + + clif->message(fd, atcmd_output); + + return true; } /*========================================== * @disguise <mob_id> by [Valaris] (simplified by [Yor]) *------------------------------------------*/ -ACMD_FUNC(disguise) +ACMD(disguise) { int id = 0; nullpo_retr(-1, sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>). - return -1; + clif->message(fd, msg_txt(1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>). + return false; } - + if ((id = atoi(message)) > 0) { //Acquired an ID if (!mobdb_checkid(id) && !npcdb_checkid(id)) @@ -4784,75 +4735,75 @@ ACMD_FUNC(disguise) id = nd->class_; } } - + if (id == 0) { - clif_displaymessage(fd, msg_txt(123)); // Invalid Monster/NPC name/ID specified. - return -1; + clif->message(fd, msg_txt(123)); // Invalid Monster/NPC name/ID specified. + return false; } - + if(pc_isriding(sd)) { - clif_displaymessage(fd, msg_txt(1144)); // Character cannot be disguised while mounted. - return -1; + clif->message(fd, msg_txt(1144)); // Character cannot be disguised while mounted. + return false; } - + pc_disguise(sd, id); - clif_displaymessage(fd, msg_txt(122)); // Disguise applied. - - return 0; + clif->message(fd, msg_txt(122)); // Disguise applied. + + return true; } /*========================================== * DisguiseAll *------------------------------------------*/ -ACMD_FUNC(disguiseall) +ACMD(disguiseall) { int mob_id=0; struct map_session_data *pl_sd; struct s_mapiterator* iter; nullpo_retr(-1, sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/ID>). - return -1; + clif->message(fd, msg_txt(1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/ID>). + return false; } - + if ((mob_id = mobdb_searchname(message)) == 0) // check name first (to avoid possible name begining by a number) mob_id = atoi(message); - + if (!mobdb_checkid(mob_id) && !npcdb_checkid(mob_id)) { //if mob or npc... - clif_displaymessage(fd, msg_txt(123)); // Monster/NPC name/id not found. - return -1; + clif->message(fd, msg_txt(123)); // Monster/NPC name/id not found. + return false; } - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) pc_disguise(pl_sd, mob_id); - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(122)); // Disguise applied. - return 0; + mapit->free(iter); + + clif->message(fd, msg_txt(122)); // Disguise applied. + return true; } /*========================================== * DisguiseGuild *------------------------------------------*/ -ACMD_FUNC(disguiseguild) +ACMD(disguiseguild) { int id = 0, i; - char monster[NAME_LENGTH], guild[NAME_LENGTH]; + char monster[NAME_LENGTH], guild_name[NAME_LENGTH]; struct map_session_data *pl_sd; struct guild *g; - + memset(monster, '\0', sizeof(monster)); - memset(guild, '\0', sizeof(guild)); - - if( !message || !*message || sscanf(message, "%23[^,], %23[^\r\n]", monster, guild) < 2 ) { - clif_displaymessage(fd, msg_txt(1146)); // Please enter a mob name/ID and guild name/ID (usage: @disguiseguild <mob name/ID>, <guild name/ID>). - return -1; + memset(guild_name, '\0', sizeof(guild_name)); + + if( !message || !*message || sscanf(message, "%23[^,], %23[^\r\n]", monster, guild_name) < 2 ) { + clif->message(fd, msg_txt(1146)); // Please enter a mob name/ID and guild name/ID (usage: @disguiseguild <mob name/ID>, <guild name/ID>). + return false; } - + if( (id = atoi(monster)) > 0 ) { if( !mobdb_checkid(id) && !npcdb_checkid(id) ) id = 0; @@ -4863,381 +4814,380 @@ ACMD_FUNC(disguiseguild) id = nd->class_; } } - + if( id == 0 ) { - clif_displaymessage(fd, msg_txt(123)); // Monster/NPC name/id hasn't been found. - return -1; + clif->message(fd, msg_txt(123)); // Monster/NPC name/id hasn't been found. + return false; } - - if( (g = guild_searchname(guild)) == NULL && (g = guild_search(atoi(guild))) == NULL ) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; + + if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(guild_name))) == NULL ) { + clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return false; } - + for( i = 0; i < g->max_member; i++ ) if( (pl_sd = g->member[i].sd) && !pc_isriding(pl_sd) ) pc_disguise(pl_sd, id); - - clif_displaymessage(fd, msg_txt(122)); // Disguise applied. - return 0; + + clif->message(fd, msg_txt(122)); // Disguise applied. + return true; } /*========================================== * @undisguise by [Yor] *------------------------------------------*/ -ACMD_FUNC(undisguise) +ACMD(undisguise) { nullpo_retr(-1, sd); - if (sd->disguise) { - pc_disguise(sd, 0); - clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. + if (sd->disguise != -1) { + pc_disguise(sd, -1); + clif->message(fd, msg_txt(124)); // Undisguise applied. } else { - clif_displaymessage(fd, msg_txt(125)); // You're not disguised. - return -1; + clif->message(fd, msg_txt(125)); // You're not disguised. + return false; } - - return 0; + + return true; } /*========================================== * UndisguiseAll *------------------------------------------*/ -ACMD_FUNC(undisguiseall) -{ +ACMD(undisguiseall) { struct map_session_data *pl_sd; struct s_mapiterator* iter; nullpo_retr(-1, sd); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) - if( pl_sd->disguise ) - pc_disguise(pl_sd, 0); - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. - - return 0; + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) + if( pl_sd->disguise != -1 ) + pc_disguise(pl_sd, -1); + mapit->free(iter); + + clif->message(fd, msg_txt(124)); // Undisguise applied. + + return true; } /*========================================== * UndisguiseGuild *------------------------------------------*/ -ACMD_FUNC(undisguiseguild) +ACMD(undisguiseguild) { char guild_name[NAME_LENGTH]; struct map_session_data *pl_sd; struct guild *g; int i; nullpo_retr(-1, sd); - + memset(guild_name, '\0', sizeof(guild_name)); - + if(!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) { - clif_displaymessage(fd, msg_txt(1147)); // Please enter guild name/ID (usage: @undisguiseguild <guild name/ID>). - return -1; + clif->message(fd, msg_txt(1147)); // Please enter guild name/ID (usage: @undisguiseguild <guild name/ID>). + return false; } - - if( (g = guild_searchname(guild_name)) == NULL && (g = guild_search(atoi(message))) == NULL ) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; + + if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(message))) == NULL ) { + clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return false; } - + for(i = 0; i < g->max_member; i++) - if( (pl_sd = g->member[i].sd) && pl_sd->disguise ) - pc_disguise(pl_sd, 0); - - clif_displaymessage(fd, msg_txt(124)); // Undisguise applied. - - return 0; + if( (pl_sd = g->member[i].sd) && pl_sd->disguise != -1 ) + pc_disguise(pl_sd, -1); + + clif->message(fd, msg_txt(124)); // Undisguise applied. + + return true; } /*========================================== * @exp by [Skotlex] *------------------------------------------*/ -ACMD_FUNC(exp) +ACMD(exp) { char output[CHAT_SIZE_MAX]; double nextb, nextj; nullpo_retr(-1, sd); memset(output, '\0', sizeof(output)); - + nextb = pc_nextbaseexp(sd); if (nextb) nextb = sd->status.base_exp*100.0/nextb; - + nextj = pc_nextjobexp(sd); if (nextj) nextj = sd->status.job_exp*100.0/nextj; - + sprintf(output, msg_txt(1148), sd->status.base_level, nextb, sd->status.job_level, nextj); // Base Level: %d (%.3f%%) | Job Level: %d (%.3f%%) - clif_displaymessage(fd, output); - return 0; + clif->message(fd, output); + return true; } /*========================================== * @broadcast by [Valaris] *------------------------------------------*/ -ACMD_FUNC(broadcast) +ACMD(broadcast) { nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1149)); // Please enter a message (usage: @broadcast <message>). - return -1; + clif->message(fd, msg_txt(1149)); // Please enter a message (usage: @broadcast <message>). + return false; } - + sprintf(atcmd_output, "%s: %s", sd->status.name, message); intif_broadcast(atcmd_output, strlen(atcmd_output) + 1, 0); - - return 0; + + return true; } /*========================================== * @localbroadcast by [Valaris] *------------------------------------------*/ -ACMD_FUNC(localbroadcast) +ACMD(localbroadcast) { nullpo_retr(-1, sd); - + memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1150)); // Please enter a message (usage: @localbroadcast <message>). - return -1; + clif->message(fd, msg_txt(1150)); // Please enter a message (usage: @localbroadcast <message>). + return false; } - + sprintf(atcmd_output, "%s: %s", sd->status.name, message); - - clif_broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); - - return 0; + + clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, 0, ALL_SAMEMAP); + + return true; } /*========================================== * @email <actual@email> <new@email> by [Yor] *------------------------------------------*/ -ACMD_FUNC(email) +ACMD(email) { char actual_email[100]; char new_email[100]; nullpo_retr(-1, sd); - + memset(actual_email, '\0', sizeof(actual_email)); memset(new_email, '\0', sizeof(new_email)); - + if (!message || !*message || sscanf(message, "%99s %99s", actual_email, new_email) < 2) { - clif_displaymessage(fd, msg_txt(1151)); // Please enter 2 emails (usage: @email <actual@email> <new@email>). - return -1; + clif->message(fd, msg_txt(1151)); // Please enter 2 emails (usage: @email <actual@email> <new@email>). + return false; } - + if (e_mail_check(actual_email) == 0) { - clif_displaymessage(fd, msg_txt(144)); // Invalid actual email. If you have default e-mail, give a@a.com. - return -1; + clif->message(fd, msg_txt(144)); // Invalid actual email. If you have default e-mail, give a@a.com. + return false; } else if (e_mail_check(new_email) == 0) { - clif_displaymessage(fd, msg_txt(145)); // Invalid new email. Please enter a real e-mail. - return -1; + clif->message(fd, msg_txt(145)); // Invalid new email. Please enter a real e-mail. + return false; } else if (strcmpi(new_email, "a@a.com") == 0) { - clif_displaymessage(fd, msg_txt(146)); // New email must be a real e-mail. - return -1; + clif->message(fd, msg_txt(146)); // New email must be a real e-mail. + return false; } else if (strcmpi(actual_email, new_email) == 0) { - clif_displaymessage(fd, msg_txt(147)); // New email must be different of the actual e-mail. - return -1; + clif->message(fd, msg_txt(147)); // New email must be different of the actual e-mail. + return false; } - + chrif_changeemail(sd->status.account_id, actual_email, new_email); - clif_displaymessage(fd, msg_txt(148)); // Information sended to login-server via char-server. - return 0; + clif->message(fd, msg_txt(148)); // Information sended to login-server via char-server. + return true; } /*========================================== *@effect *------------------------------------------*/ -ACMD_FUNC(effect) +ACMD(effect) { int type = 0, flag = 0; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%d", &type) < 1) { - clif_displaymessage(fd, msg_txt(1152)); // Please enter an effect number (usage: @effect <effect number>). - return -1; + clif->message(fd, msg_txt(1152)); // Please enter an effect number (usage: @effect <effect number>). + return false; } - - clif_specialeffect(&sd->bl, type, (send_target)flag); - clif_displaymessage(fd, msg_txt(229)); // Your effect has changed. - return 0; + + clif->specialeffect(&sd->bl, type, (send_target)flag); + clif->message(fd, msg_txt(229)); // Your effect has changed. + return true; } /*========================================== * @killer by MouseJstr * enable killing players even when not in pvp *------------------------------------------*/ -ACMD_FUNC(killer) +ACMD(killer) { nullpo_retr(-1, sd); sd->state.killer = !sd->state.killer; - + if(sd->state.killer) - clif_displaymessage(fd, msg_txt(241)); + clif->message(fd, msg_txt(241)); else { - clif_displaymessage(fd, msg_txt(292)); + clif->message(fd, msg_txt(292)); pc_stop_attack(sd); } - return 0; + return true; } /*========================================== * @killable by MouseJstr * enable other people killing you *------------------------------------------*/ -ACMD_FUNC(killable) +ACMD(killable) { nullpo_retr(-1, sd); sd->state.killable = !sd->state.killable; - + if(sd->state.killable) - clif_displaymessage(fd, msg_txt(242)); + clif->message(fd, msg_txt(242)); else { - clif_displaymessage(fd, msg_txt(288)); + clif->message(fd, msg_txt(288)); map_foreachinrange(atcommand_stopattack,&sd->bl, AREA_SIZE, BL_CHAR, sd->bl.id); } - return 0; + return true; } /*========================================== * @skillon by MouseJstr * turn skills on for the map *------------------------------------------*/ -ACMD_FUNC(skillon) +ACMD(skillon) { nullpo_retr(-1, sd); map[sd->bl.m].flag.noskill = 0; - clif_displaymessage(fd, msg_txt(244)); - return 0; + clif->message(fd, msg_txt(244)); + return true; } /*========================================== * @skilloff by MouseJstr * Turn skills off on the map *------------------------------------------*/ -ACMD_FUNC(skilloff) +ACMD(skilloff) { nullpo_retr(-1, sd); map[sd->bl.m].flag.noskill = 1; - clif_displaymessage(fd, msg_txt(243)); - return 0; + clif->message(fd, msg_txt(243)); + return true; } /*========================================== * @npcmove by MouseJstr * move a npc *------------------------------------------*/ -ACMD_FUNC(npcmove) +ACMD(npcmove) { int x = 0, y = 0, m; struct npc_data *nd = 0; nullpo_retr(-1, sd); memset(atcmd_player_name, '\0', sizeof atcmd_player_name); - + if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &x, &y, atcmd_player_name) < 3) { - clif_displaymessage(fd, msg_txt(1153)); // Usage: @npcmove <X> <Y> <npc_name> - return -1; + clif->message(fd, msg_txt(1153)); // Usage: @npcmove <X> <Y> <npc_name> + return false; } - + if ((nd = npc_name2id(atcmd_player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist. - return -1; + clif->message(fd, msg_txt(111)); // This NPC doesn't exist. + return false; } - + if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) { - clif_displaymessage(fd, msg_txt(1154)); // NPC is not on this map. - return -1; //Not on a map. + clif->message(fd, msg_txt(1154)); // NPC is not on this map. + return false; //Not on a map. } - + x = cap_value(x, 0, map[m].xs-1); y = cap_value(y, 0, map[m].ys-1); - map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + map_foreachinrange(clif->outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); map_moveblock(&nd->bl, x, y, gettick()); - map_foreachinrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); - clif_displaymessage(fd, msg_txt(1155)); // NPC moved. - - return 0; + map_foreachinrange(clif->insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + clif->message(fd, msg_txt(1155)); // NPC moved. + + return true; } /*========================================== * @addwarp by MouseJstr * Create a new static warp point. *------------------------------------------*/ -ACMD_FUNC(addwarp) +ACMD(addwarp) { char mapname[32], warpname[NAME_LENGTH+1]; int x,y; unsigned short m; struct npc_data* nd; - + nullpo_retr(-1, sd); memset(warpname, '\0', sizeof(warpname)); - + if (!message || !*message || sscanf(message, "%31s %d %d %23[^\n]", mapname, &x, &y, warpname) < 4) { - clif_displaymessage(fd, msg_txt(1156)); // Usage: @addwarp <mapname> <X> <Y> <npc name> - return -1; + clif->message(fd, msg_txt(1156)); // Usage: @addwarp <mapname> <X> <Y> <npc name> + return false; } - + m = mapindex_name2id(mapname); if( m == 0 ) { sprintf(atcmd_output, msg_txt(1157), mapname); // Unknown map '%s'. - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + nd = npc_add_warp(warpname, sd->bl.m, sd->bl.x, sd->bl.y, 2, 2, m, x, y); if( nd == NULL ) - return -1; - + return false; + sprintf(atcmd_output, msg_txt(1158), nd->exname); // New warp NPC '%s' created. - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } /*========================================== * @follow by [MouseJstr] * Follow a player .. staying no more then 5 spaces away *------------------------------------------*/ -ACMD_FUNC(follow) +ACMD(follow) { struct map_session_data *pl_sd = NULL; nullpo_retr(-1, sd); - + if (!message || !*message) { if (sd->followtarget == -1) - return -1; - + return false; + pc_stop_following (sd); - clif_displaymessage(fd, msg_txt(1159)); // Follow mode OFF. - return 0; + clif->message(fd, msg_txt(1159)); // Follow mode OFF. + return true; } - + if ( (pl_sd = map_nick2sd((char *)message)) == NULL ) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if (sd->followtarget == pl_sd->bl.id) { pc_stop_following (sd); - clif_displaymessage(fd, msg_txt(1159)); // Follow mode OFF. + clif->message(fd, msg_txt(1159)); // Follow mode OFF. } else { pc_follow(sd, pl_sd->bl.id); - clif_displaymessage(fd, msg_txt(1160)); // Follow mode ON. + clif->message(fd, msg_txt(1160)); // Follow mode ON. } - - return 0; + + return true; } @@ -5245,37 +5195,37 @@ ACMD_FUNC(follow) * @dropall by [MouseJstr] * Drop all your possession on the ground *------------------------------------------*/ -ACMD_FUNC(dropall) +ACMD(dropall) { int i; nullpo_retr(-1, sd); for (i = 0; i < MAX_INVENTORY; i++) { - if (sd->status.inventory[i].amount) { - if(sd->status.inventory[i].equip != 0) - pc_unequipitem(sd, i, 3); + if (sd->status.inventory[i].amount) { + if(sd->status.inventory[i].equip != 0) + pc_unequipitem(sd, i, 3); pc_dropitem(sd, i, sd->status.inventory[i].amount); } } - return 0; + return true; } /*========================================== * @storeall by [MouseJstr] * Put everything into storage *------------------------------------------*/ -ACMD_FUNC(storeall) +ACMD(storeall) { int i; nullpo_retr(-1, sd); - + if (sd->state.storage_flag != 1) { //Open storage. if( storage_storageopen(sd) == 1 ) { - clif_displaymessage(fd, msg_txt(1161)); // You currently cannot open your storage. - return -1; + clif->message(fd, msg_txt(1161)); // You currently cannot open your storage. + return false; } } - + for (i = 0; i < MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { if(sd->status.inventory[i].equip != 0) @@ -5284,60 +5234,60 @@ ACMD_FUNC(storeall) } } storage_storageclose(sd); - - clif_displaymessage(fd, msg_txt(1162)); // All items stored. - return 0; + + clif->message(fd, msg_txt(1162)); // All items stored. + return true; } -ACMD_FUNC(clearstorage) +ACMD(clearstorage) { int i, j; nullpo_retr(-1, sd); - + if (sd->state.storage_flag == 1) { - clif_displaymessage(fd, msg_txt(250)); - return -1; + clif->message(fd, msg_txt(250)); + return false; } - + j = sd->status.storage.storage_amount; for (i = 0; i < j; ++i) { storage_delitem(sd, i, sd->status.storage.items[i].amount); } storage_storageclose(sd); - - clif_displaymessage(fd, msg_txt(1394)); // Your storage was cleaned. - return 0; + + clif->message(fd, msg_txt(1394)); // Your storage was cleaned. + return true; } -ACMD_FUNC(cleargstorage) +ACMD(cleargstorage) { int i, j; struct guild *g; struct guild_storage *gstorage; nullpo_retr(-1, sd); - - g = guild_search(sd->status.guild_id); - + + g = sd->guild; + if (g == NULL) { - clif_displaymessage(fd, msg_txt(43)); - return -1; + clif->message(fd, msg_txt(43)); + return false; } - + if (sd->state.storage_flag == 1) { - clif_displaymessage(fd, msg_txt(250)); - return -1; + clif->message(fd, msg_txt(250)); + return false; } - + if (sd->state.storage_flag == 2) { - clif_displaymessage(fd, msg_txt(251)); - return -1; + clif->message(fd, msg_txt(251)); + return false; } - + gstorage = guild2storage2(sd->status.guild_id); if (gstorage == NULL) {// Doesn't have opened @gstorage yet, so we skip the deletion since *shouldn't* have any item there. - return -1; + return false; } - + j = gstorage->storage_amount; gstorage->lock = 1; // Lock @gstorage: do not allow any item to be retrieved or stored from any guild member for (i = 0; i < j; ++i) { @@ -5345,69 +5295,89 @@ ACMD_FUNC(cleargstorage) } storage_guild_storageclose(sd); gstorage->lock = 0; // Cleaning done, release lock - - clif_displaymessage(fd, msg_txt(1395)); // Your guild storage was cleaned. - return 0; + + clif->message(fd, msg_txt(1395)); // Your guild storage was cleaned. + return true; } -ACMD_FUNC(clearcart) +ACMD(clearcart) { int i; nullpo_retr(-1, sd); - + if (pc_iscarton(sd) == 0) { - clif_displaymessage(fd, msg_txt(1396)); // You do not have a cart to be cleaned. - return -1; + clif->message(fd, msg_txt(1396)); // You do not have a cart to be cleaned. + return false; } - + if (sd->state.vending == 1) { //Somehow... - return -1; + return false; } - + for( i = 0; i < MAX_CART; i++ ) if(sd->status.cart[i].nameid > 0) pc_cart_delitem(sd, i, sd->status.cart[i].amount, 1, LOG_TYPE_OTHER); - - clif_clearcart(fd); - clif_updatestatus(sd,SP_CARTINFO); - - clif_displaymessage(fd, msg_txt(1397)); // Your cart was cleaned. - return 0; + + clif->clearcart(fd); + clif->updatestatus(sd,SP_CARTINFO); + + clif->message(fd, msg_txt(1397)); // Your cart was cleaned. + return true; } /*========================================== * @skillid by [MouseJstr] * lookup a skill by name *------------------------------------------*/ -ACMD_FUNC(skillid) -{ - int skillen, idx; - nullpo_retr(-1, sd); - - if (!message || !*message) - { - clif_displaymessage(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>). - return -1; +#define MAX_SKILLID_PARTIAL_RESULTS 5 +#define MAX_SKILLID_PARTIAL_RESULTS_LEN 74 /* "skill " (6) + "%d:" (up to 5) + "%s" (up to 30) + " (%s)" (up to 33) */ +ACMD(skillid) { + int skillen, idx, i, found = 0; + DBIterator* iter; + DBKey key; + DBData *data; + char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN]; + + nullpo_retr(-1, sd); + + if (!message || !*message) { + clif->message(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>). + return false; } - + skillen = strlen(message); - - for (idx = 0; idx < MAX_SKILL_DB; idx++) { - if (strnicmp(skill_db[idx].name, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0) - { - sprintf(atcmd_output, msg_txt(1164), idx, skill_db[idx].desc); // skill %d: %s - clif_displaymessage(fd, atcmd_output); - } + + iter = db_iterator(skilldb_name2id); + + for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) { + idx = skill->get_index(DB->data2i(data)); + if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill_db[idx].desc, message, skillen) == 0) { + sprintf(atcmd_output, msg_txt(1164), DB->data2i(data), skill_db[idx].desc, key.str); // skill %d: %s (%s) + clif->message(fd, atcmd_output); + } else if ( found < MAX_SKILLID_PARTIAL_RESULTS && ( stristr(key.str,message) || stristr(skill_db[idx].desc,message) ) ) { + snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(1164), DB->data2i(data), skill_db[idx].desc, key.str); + } + } + + dbi_destroy(iter); + + if( found ) { + sprintf(atcmd_output, msg_txt(1398), found); // -- Displaying first %d partial matches + clif->message(fd, atcmd_output); } - - return 0; + + for(i = 0; i < found; i++) { /* partials */ + clif->message(fd, partials[i]); + } + + return true; } /*========================================== * @useskill by [MouseJstr] * A way of using skills without having to find them in the skills menu *------------------------------------------*/ -ACMD_FUNC(useskill) +ACMD(useskill) { struct map_session_data *pl_sd = NULL; struct block_list *bl; @@ -5415,36 +5385,36 @@ ACMD_FUNC(useskill) uint16 skill_lv; char target[100]; nullpo_retr(-1, sd); - + if(!message || !*message || sscanf(message, "%hu %hu %23[^\n]", &skill_id, &skill_lv, target) != 3) { - clif_displaymessage(fd, msg_txt(1165)); // Usage: @useskill <skill ID> <skill level> <target> - return -1; + clif->message(fd, msg_txt(1165)); // Usage: @useskill <skill ID> <skill level> <target> + return false; } - + if(!strcmp(target,"self")) pl_sd = sd; //quick keyword else if ( (pl_sd = map_nick2sd(target)) == NULL ){ - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; + clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return false; } - + if (skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL - && sd->hd && merc_is_hom_active(sd->hd)) // (If used with @useskill, put the homunc as dest) + && sd->hd && homun_alive(sd->hd)) // (If used with @useskill, put the homunc as dest) bl = &sd->hd->bl; else bl = &sd->bl; - - if (skill_get_inf(skill_id)&INF_GROUND_SKILL) + + if (skill->get_inf(skill_id)&INF_GROUND_SKILL) unit_skilluse_pos(bl, pl_sd->bl.x, pl_sd->bl.y, skill_id, skill_lv); else unit_skilluse_id(bl, pl_sd->bl.id, skill_id, skill_lv); - - return 0; + + return true; } /*========================================== @@ -5452,32 +5422,32 @@ ACMD_FUNC(useskill) * Debug command to locate new skill IDs. It sends the * three possible skill-effect packets to the area. *------------------------------------------*/ -ACMD_FUNC(displayskill) +ACMD(displayskill) { struct status_data * status; unsigned int tick; uint16 skill_id; uint16 skill_lv = 1; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%hu %hu", &skill_id, &skill_lv) < 1) { - clif_displaymessage(fd, msg_txt(1166)); // Usage: @displayskill <skill ID> {<skill level>} - return -1; + clif->message(fd, msg_txt(1166)); // Usage: @displayskill <skill ID> {<skill level>} + return false; } status = status_get_status_data(&sd->bl); tick = gettick(); - clif_skill_damage(&sd->bl,&sd->bl, tick, status->amotion, status->dmotion, 1, 1, skill_id, skill_lv, 5); - clif_skill_nodamage(&sd->bl, &sd->bl, skill_id, skill_lv, 1); - clif_skill_poseffect(&sd->bl, skill_id, skill_lv, sd->bl.x, sd->bl.y, tick); - return 0; + clif->skill_damage(&sd->bl,&sd->bl, tick, status->amotion, status->dmotion, 1, 1, skill_id, skill_lv, 5); + clif->skill_nodamage(&sd->bl, &sd->bl, skill_id, skill_lv, 1); + clif->skill_poseffect(&sd->bl, skill_id, skill_lv, sd->bl.x, sd->bl.y, tick); + return true; } /*========================================== * @skilltree by [MouseJstr] * prints the skill tree for a player required to get to a skill *------------------------------------------*/ -ACMD_FUNC(skilltree) +ACMD(skilltree) { struct map_session_data *pl_sd = NULL; uint16 skill_id; @@ -5485,48 +5455,48 @@ ACMD_FUNC(skilltree) char target[NAME_LENGTH]; struct skill_tree_entry *ent; nullpo_retr(-1, sd); - + if(!message || !*message || sscanf(message, "%hu %23[^\r\n]", &skill_id, target) != 2) { - clif_displaymessage(fd, msg_txt(1167)); // Usage: @skilltree <skill ID> <target> - return -1; + clif->message(fd, msg_txt(1167)); // Usage: @skilltree <skill ID> <target> + return false; } - + if ( (pl_sd = map_nick2sd(target)) == NULL ) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + c = pc_calc_skilltree_normalize_job(pl_sd); c = pc_mapid2jobid(c, pl_sd->status.sex); - + sprintf(atcmd_output, msg_txt(1168), job_name(c), pc_checkskill(pl_sd, NV_BASIC)); // Player is using %s skill tree (%d basic points). - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + ARR_FIND( 0, MAX_SKILL_TREE, j, skill_tree[c][j].id == 0 || skill_tree[c][j].id == skill_id ); if( j == MAX_SKILL_TREE || skill_tree[c][j].id == 0 ) { - clif_displaymessage(fd, msg_txt(1169)); // The player cannot use that skill. - return 0; + clif->message(fd, msg_txt(1169)); // The player cannot use that skill. + return true; } - + ent = &skill_tree[c][j]; - + meets = 1; for(j=0;j<MAX_PC_SKILL_REQUIRE;j++) { if( ent->need[j].id && pc_checkskill(sd,ent->need[j].id) < ent->need[j].lv) { sprintf(atcmd_output, msg_txt(1170), ent->need[j].lv, skill_db[ent->need[j].id].desc); // Player requires level %d of skill %s. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); meets = 0; } } if (meets == 1) { - clif_displaymessage(fd, msg_txt(1171)); // The player meets all the requirements for that skill. + clif->message(fd, msg_txt(1171)); // The player meets all the requirements for that skill. } - - return 0; + + return true; } // Hand a ring with partners name on it to this char @@ -5535,16 +5505,16 @@ void getring (struct map_session_data* sd) int flag, item_id; struct item item_tmp; item_id = (sd->status.sex) ? WEDDING_RING_M : WEDDING_RING_F; - + memset(&item_tmp, 0, sizeof(item_tmp)); item_tmp.nameid = item_id; item_tmp.identify = 1; item_tmp.card[0] = 255; item_tmp.card[2] = sd->status.partner_id; item_tmp.card[3] = sd->status.partner_id >> 16; - + if((flag = pc_additem(sd,&item_tmp,1,LOG_TYPE_COMMAND))) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } @@ -5553,66 +5523,66 @@ void getring (struct map_session_data* sd) * @marry by [MouseJstr], fixed by Lupus * Marry two players *------------------------------------------*/ -ACMD_FUNC(marry) +ACMD(marry) { struct map_session_data *pl_sd = NULL; char player_name[NAME_LENGTH] = ""; - + nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%23s", player_name) != 1) { - clif_displaymessage(fd, msg_txt(1172)); // Usage: @marry <char name> - return -1; + clif->message(fd, msg_txt(1172)); // Usage: @marry <char name> + return false; } - + if ((pl_sd = map_nick2sd(player_name)) == NULL) { - clif_displaymessage(fd, msg_txt(3)); - return -1; + clif->message(fd, msg_txt(3)); + return false; } - + if (pc_marriage(sd, pl_sd) == 0) { - clif_displaymessage(fd, msg_txt(1173)); // They are married... wish them well. - clif_wedding_effect(&pl_sd->bl); //wedding effect and music [Lupus] + clif->message(fd, msg_txt(1173)); // They are married... wish them well. + clif->wedding_effect(&pl_sd->bl); //wedding effect and music [Lupus] getring(sd); // Auto-give named rings (Aru) getring(pl_sd); - return 0; + return true; } - - clif_displaymessage(fd, msg_txt(1174)); // The two cannot wed because one is either a baby or already married. - return -1; + + clif->message(fd, msg_txt(1174)); // The two cannot wed because one is either a baby or already married. + return false; } /*========================================== * @divorce by [MouseJstr], fixed by [Lupus] * divorce two players *------------------------------------------*/ -ACMD_FUNC(divorce) +ACMD(divorce) { nullpo_retr(-1, sd); - + if (pc_divorce(sd) != 0) { sprintf(atcmd_output, msg_txt(1175), sd->status.name); // '%s' is not married. - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + sprintf(atcmd_output, msg_txt(1176), sd->status.name); // '%s' and his/her partner are now divorced. - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } /*========================================== * @changelook by [Celest] *------------------------------------------*/ -ACMD_FUNC(changelook) +ACMD(changelook) { int i, j = 0, k = 0; int pos[7] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES,LOOK_ROBE }; - + if((i = sscanf(message, "%d %d", &j, &k)) < 1) { - clif_displaymessage(fd, msg_txt(1177)); // Usage: @changelook {<position>} <view id> - clif_displaymessage(fd, msg_txt(1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe - return -1; + clif->message(fd, msg_txt(1177)); // Usage: @changelook {<position>} <view id> + clif->message(fd, msg_txt(1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe + return false; } else if ( i == 2 ) { if (j < 1 || j > 7) j = 1; @@ -5621,151 +5591,151 @@ ACMD_FUNC(changelook) k = j; // swap j = LOOK_HEAD_TOP; } - - clif_changelook(&sd->bl,j,k); - - return 0; + + clif->changelook(&sd->bl,j,k); + + return true; } /*========================================== * @autotrade by durf [Lupus] [Paradox924X] * Turns on/off Autotrade for a specific player *------------------------------------------*/ -ACMD_FUNC(autotrade) -{ +ACMD(autotrade) { nullpo_retr(-1, sd); - + if( map[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag ) { - clif_displaymessage(fd, msg_txt(1179)); // Autotrade is not allowed on this map. - return -1; + clif->message(fd, msg_txt(1179)); // Autotrade is not allowed on this map. + return false; } - + if( pc_isdead(sd) ) { - clif_displaymessage(fd, msg_txt(1180)); // You cannot autotrade when dead. - return -1; + clif->message(fd, msg_txt(1180)); // You cannot autotrade when dead. + return false; } - + if( !sd->state.vending && !sd->state.buyingstore ) { //check if player is vending or buying - clif_displaymessage(fd, msg_txt(549)); // "You should have a shop open to use @autotrade." - return -1; + clif->message(fd, msg_txt(549)); // "You should have a shop open to use @autotrade." + return false; } - + sd->state.autotrade = 1; - if( battle_config.at_timeout ) - { + if( battle_config.at_timeout ) { int timeout = atoi(message); status_change_start(&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0); } - clif_authfail_fd(fd, 15); - - return 0; + + clif->chsys_quit(sd); + + clif->authfail_fd(sd->fd, 15); + + return true; } /*========================================== * @changegm by durf (changed by Lupus) * Changes Master of your Guild to a specified guild member *------------------------------------------*/ -ACMD_FUNC(changegm) +ACMD(changegm) { struct guild *g; struct map_session_data *pl_sd; nullpo_retr(-1, sd); - - if (sd->status.guild_id == 0 || (g = guild_search(sd->status.guild_id)) == NULL || strcmp(g->master,sd->status.name)) { - clif_displaymessage(fd, msg_txt(1181)); // You need to be a Guild Master to use this command. - return -1; + + if (sd->status.guild_id == 0 || (g = sd->guild) == NULL || strcmp(g->master,sd->status.name)) { + clif->message(fd, msg_txt(1181)); // You need to be a Guild Master to use this command. + return false; } - + if( map[sd->bl.m].flag.guildlock || map[sd->bl.m].flag.gvg_castle ) { - clif_displaymessage(fd, msg_txt(1182)); // You cannot change guild leaders on this map. - return -1; + clif->message(fd, msg_txt(1182)); // You cannot change guild leaders on this map. + return false; } - + if( !message[0] ) { - clif_displaymessage(fd, msg_txt(1183)); // Usage: @changegm <guild_member_name> - return -1; + clif->message(fd, msg_txt(1183)); // Usage: @changegm <guild_member_name> + return false; } - + if((pl_sd=map_nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) { - clif_displaymessage(fd, msg_txt(1184)); // Target character must be online and be a guild member. - return -1; + clif->message(fd, msg_txt(1184)); // Target character must be online and be a guild member. + return false; } - - guild_gm_change(sd->status.guild_id, pl_sd); - return 0; + + guild->gm_change(sd->status.guild_id, pl_sd); + return true; } /*========================================== * @changeleader by Skotlex * Changes the leader of a party. *------------------------------------------*/ -ACMD_FUNC(changeleader) +ACMD(changeleader) { nullpo_retr(-1, sd); - + if( !message[0] ) { - clif_displaymessage(fd, msg_txt(1185)); // Usage: @changeleader <party_member_name> - return -1; + clif->message(fd, msg_txt(1185)); // Usage: @changeleader <party_member_name> + return false; } - + if (party_changeleader(sd, map_nick2sd((char *) message))) - return 0; - return -1; + return true; + return false; } /*========================================== * @partyoption by Skotlex * Used to change the item share setting of a party. *------------------------------------------*/ -ACMD_FUNC(partyoption) +ACMD(partyoption) { struct party_data *p; int mi, option; char w1[16], w2[16]; nullpo_retr(-1, sd); - + if (sd->status.party_id == 0 || (p = party_search(sd->status.party_id)) == NULL) { - clif_displaymessage(fd, msg_txt(282)); - return -1; + clif->message(fd, msg_txt(282)); + return false; } - + ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd ); if (mi == MAX_PARTY) - return -1; //Shouldn't happen - + return false; //Shouldn't happen + if (!p->party.member[mi].leader) { - clif_displaymessage(fd, msg_txt(282)); - return -1; + clif->message(fd, msg_txt(282)); + return false; } - + if(!message || !*message || sscanf(message, "%15s %15s", w1, w2) < 2) { - clif_displaymessage(fd, msg_txt(1186)); // Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no> - return -1; + clif->message(fd, msg_txt(1186)); // Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no> + return false; } - + option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0); - + //Change item share type. if (option != p->party.item) party_changeoption(sd, p->party.exp, option); else - clif_displaymessage(fd, msg_txt(286)); - - return 0; + clif->message(fd, msg_txt(286)); + + return true; } /*========================================== * @autoloot by Upa-Kun * Turns on/off AutoLoot for a specific player *------------------------------------------*/ -ACMD_FUNC(autoloot) +ACMD(autoloot) { int rate; - double drate; nullpo_retr(-1, sd); // autoloot command without value if(!message || !*message) @@ -5775,31 +5745,32 @@ ACMD_FUNC(autoloot) else rate = 10000; } else { + double drate; drate = atof(message); rate = (int)(drate*100); } if (rate < 0) rate = 0; if (rate > 10000) rate = 10000; - + sd->state.autoloot = rate; if (sd->state.autoloot) { snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1187),((double)sd->state.autoloot)/100.); // Autolooting items with drop rates of %0.02f%% and below. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); }else - clif_displaymessage(fd, msg_txt(1188)); // Autoloot is now off. - - return 0; + clif->message(fd, msg_txt(1188)); // Autoloot is now off. + + return true; } /*========================================== * @alootid *------------------------------------------*/ -ACMD_FUNC(autolootitem) +ACMD(autolootitem) { struct item_data *item_data = NULL; int i; int action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset - + if (message && *message) { if (message[0] == '+') { message++; @@ -5812,79 +5783,79 @@ ACMD_FUNC(autolootitem) else if (!strcmp(message,"reset")) action = 4; } - + if (action < 3) // add or remove { if ((item_data = itemdb_exists(atoi(message))) == NULL) item_data = itemdb_searchname(message); if (!item_data) { // No items founds in the DB with Id or Name - clif_displaymessage(fd, msg_txt(1189)); // Item not found. - return -1; + clif->message(fd, msg_txt(1189)); // Item not found. + return false; } } - + switch(action) { - case 1: - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); - if (i != AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1190)); // You're already autolooting this item. - return -1; - } - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == 0); - if (i == AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1191)); // Your autolootitem list is full. Remove some items first with @autolootid -<item name or ID>. - return -1; - } - sd->state.autolootid[i] = item_data->nameid; // Autoloot Activated - sprintf(atcmd_output, msg_txt(1192), item_data->name, item_data->jname, item_data->nameid); // Autolooting item: '%s'/'%s' {%d} - clif_displaymessage(fd, atcmd_output); - sd->state.autolooting = 1; - break; - case 2: - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); - if (i == AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1193)); // You're currently not autolooting this item. - return -1; - } - sd->state.autolootid[i] = 0; - sprintf(atcmd_output, msg_txt(1194), item_data->name, item_data->jname, item_data->nameid); // Removed item: '%s'/'%s' {%d} from your autolootitem list. - clif_displaymessage(fd, atcmd_output); - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); - if (i == AUTOLOOTITEM_SIZE) { - sd->state.autolooting = 0; - } - break; - case 3: - sprintf(atcmd_output, msg_txt(1195), AUTOLOOTITEM_SIZE); // You can have %d items on your autolootitem list. - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1196)); // To add an item to the list, use "@alootid +<item name or ID>". To remove an item, use "@alootid -<item name or ID>". - clif_displaymessage(fd, msg_txt(1197)); // "@alootid reset" will clear your autolootitem list. - ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); - if (i == AUTOLOOTITEM_SIZE) { - clif_displaymessage(fd, msg_txt(1198)); // Your autolootitem list is empty. - } else { - clif_displaymessage(fd, msg_txt(1199)); // Items on your autolootitem list: - for(i = 0; i < AUTOLOOTITEM_SIZE; i++) - { - if (sd->state.autolootid[i] == 0) - continue; - if (!(item_data = itemdb_exists(sd->state.autolootid[i]))) { - ShowDebug("Non-existant item %d on autolootitem list (account_id: %d, char_id: %d)", sd->state.autolootid[i], sd->status.account_id, sd->status.char_id); - continue; + case 1: + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); + if (i != AUTOLOOTITEM_SIZE) { + clif->message(fd, msg_txt(1190)); // You're already autolooting this item. + return false; + } + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == 0); + if (i == AUTOLOOTITEM_SIZE) { + clif->message(fd, msg_txt(1191)); // Your autolootitem list is full. Remove some items first with @autolootid -<item name or ID>. + return false; + } + sd->state.autolootid[i] = item_data->nameid; // Autoloot Activated + sprintf(atcmd_output, msg_txt(1192), item_data->name, item_data->jname, item_data->nameid); // Autolooting item: '%s'/'%s' {%d} + clif->message(fd, atcmd_output); + sd->state.autolooting = 1; + break; + case 2: + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid); + if (i == AUTOLOOTITEM_SIZE) { + clif->message(fd, msg_txt(1193)); // You're currently not autolooting this item. + return false; + } + sd->state.autolootid[i] = 0; + sprintf(atcmd_output, msg_txt(1194), item_data->name, item_data->jname, item_data->nameid); // Removed item: '%s'/'%s' {%d} from your autolootitem list. + clif->message(fd, atcmd_output); + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); + if (i == AUTOLOOTITEM_SIZE) { + sd->state.autolooting = 0; + } + break; + case 3: + sprintf(atcmd_output, msg_txt(1195), AUTOLOOTITEM_SIZE); // You can have %d items on your autolootitem list. + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1196)); // To add an item to the list, use "@alootid +<item name or ID>". To remove an item, use "@alootid -<item name or ID>". + clif->message(fd, msg_txt(1197)); // "@alootid reset" will clear your autolootitem list. + ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] != 0); + if (i == AUTOLOOTITEM_SIZE) { + clif->message(fd, msg_txt(1198)); // Your autolootitem list is empty. + } else { + clif->message(fd, msg_txt(1199)); // Items on your autolootitem list: + for(i = 0; i < AUTOLOOTITEM_SIZE; i++) + { + if (sd->state.autolootid[i] == 0) + continue; + if (!(item_data = itemdb_exists(sd->state.autolootid[i]))) { + ShowDebug("Non-existant item %d on autolootitem list (account_id: %d, char_id: %d)", sd->state.autolootid[i], sd->status.account_id, sd->status.char_id); + continue; + } + sprintf(atcmd_output, "'%s'/'%s' {%d}", item_data->name, item_data->jname, item_data->nameid); + clif->message(fd, atcmd_output); } - sprintf(atcmd_output, "'%s'/'%s' {%d}", item_data->name, item_data->jname, item_data->nameid); - clif_displaymessage(fd, atcmd_output); } - } - break; - case 4: - memset(sd->state.autolootid, 0, sizeof(sd->state.autolootid)); - clif_displaymessage(fd, msg_txt(1200)); // Your autolootitem list has been reset. - sd->state.autolooting = 0; - break; + break; + case 4: + memset(sd->state.autolootid, 0, sizeof(sd->state.autolootid)); + clif->message(fd, msg_txt(1200)); // Your autolootitem list has been reset. + sd->state.autolooting = 0; + break; } - return 0; + return true; } /** * No longer available, keeping here just in case it's back someday. [Ind] @@ -5892,156 +5863,156 @@ ACMD_FUNC(autolootitem) /*========================================== * It is made to rain. *------------------------------------------*/ -//ACMD_FUNC(rain) +//ACMD(rain) //{ // nullpo_retr(-1, sd); // if (map[sd->bl.m].flag.rain) { // map[sd->bl.m].flag.rain=0; -// clif_weather(sd->bl.m); -// clif_displaymessage(fd, msg_txt(1201)); // The rain has stopped. +// clif->weather(sd->bl.m); +// clif->message(fd, msg_txt(1201)); // The rain has stopped. // } else { // map[sd->bl.m].flag.rain=1; -// clif_weather(sd->bl.m); -// clif_displaymessage(fd, msg_txt(1202)); // It has started to rain. +// clif->weather(sd->bl.m); +// clif->message(fd, msg_txt(1202)); // It has started to rain. // } -// return 0; +// return true; //} /*========================================== * It is made to snow. *------------------------------------------*/ -ACMD_FUNC(snow) +ACMD(snow) { nullpo_retr(-1, sd); if (map[sd->bl.m].flag.snow) { map[sd->bl.m].flag.snow=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1203)); // Snow has stopped falling. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1203)); // Snow has stopped falling. } else { map[sd->bl.m].flag.snow=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1204)); // It has started to snow. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1204)); // It has started to snow. } - - return 0; + + return true; } /*========================================== * Cherry tree snowstorm is made to fall. (Sakura) *------------------------------------------*/ -ACMD_FUNC(sakura) +ACMD(sakura) { nullpo_retr(-1, sd); if (map[sd->bl.m].flag.sakura) { map[sd->bl.m].flag.sakura=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1205)); // Cherry tree leaves no longer fall. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1205)); // Cherry tree leaves no longer fall. } else { map[sd->bl.m].flag.sakura=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1206)); // Cherry tree leaves have begun to fall. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1206)); // Cherry tree leaves have begun to fall. } - return 0; + return true; } /*========================================== * Clouds appear. *------------------------------------------*/ -ACMD_FUNC(clouds) +ACMD(clouds) { nullpo_retr(-1, sd); if (map[sd->bl.m].flag.clouds) { map[sd->bl.m].flag.clouds=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1207)); // The clouds has disappear. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1207)); // The clouds has disappear. } else { map[sd->bl.m].flag.clouds=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1208)); // Clouds appear. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1208)); // Clouds appear. } - - return 0; + + return true; } /*========================================== * Different type of clouds using effect 516 *------------------------------------------*/ -ACMD_FUNC(clouds2) +ACMD(clouds2) { nullpo_retr(-1, sd); if (map[sd->bl.m].flag.clouds2) { map[sd->bl.m].flag.clouds2=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1209)); // The alternative clouds disappear. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1209)); // The alternative clouds disappear. } else { map[sd->bl.m].flag.clouds2=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1210)); // Alternative clouds appear. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1210)); // Alternative clouds appear. } - - return 0; + + return true; } /*========================================== * Fog hangs over. *------------------------------------------*/ -ACMD_FUNC(fog) +ACMD(fog) { nullpo_retr(-1, sd); if (map[sd->bl.m].flag.fog) { map[sd->bl.m].flag.fog=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1211)); // The fog has gone. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1211)); // The fog has gone. } else { map[sd->bl.m].flag.fog=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1212)); // Fog hangs over. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1212)); // Fog hangs over. } - return 0; + return true; } /*========================================== * Fallen leaves fall. *------------------------------------------*/ -ACMD_FUNC(leaves) +ACMD(leaves) { nullpo_retr(-1, sd); if (map[sd->bl.m].flag.leaves) { map[sd->bl.m].flag.leaves=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1213)); // Leaves no longer fall. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1213)); // Leaves no longer fall. } else { map[sd->bl.m].flag.leaves=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1214)); // Fallen leaves fall. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1214)); // Fallen leaves fall. } - - return 0; + + return true; } /*========================================== * Fireworks appear. *------------------------------------------*/ -ACMD_FUNC(fireworks) +ACMD(fireworks) { nullpo_retr(-1, sd); if (map[sd->bl.m].flag.fireworks) { map[sd->bl.m].flag.fireworks=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1215)); // Fireworks have ended. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1215)); // Fireworks have ended. } else { map[sd->bl.m].flag.fireworks=1; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(1216)); // Fireworks have launched. + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(1216)); // Fireworks have launched. } - - return 0; + + return true; } /*========================================== * Clearing Weather Effects by Dexity *------------------------------------------*/ -ACMD_FUNC(clearweather) +ACMD(clearweather) { nullpo_retr(-1, sd); /** @@ -6055,87 +6026,87 @@ ACMD_FUNC(clearweather) map[sd->bl.m].flag.fog=0; map[sd->bl.m].flag.fireworks=0; map[sd->bl.m].flag.leaves=0; - clif_weather(sd->bl.m); - clif_displaymessage(fd, msg_txt(291)); - - return 0; + clif->weather(sd->bl.m); + clif->message(fd, msg_txt(291)); + + return true; } /*=============================================================== * Sound Command - plays a sound for everyone around! [Codemaster] *---------------------------------------------------------------*/ -ACMD_FUNC(sound) +ACMD(sound) { char sound_file[100]; - + memset(sound_file, '\0', sizeof(sound_file)); - - if(!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) { - clif_displaymessage(fd, msg_txt(1217)); // Please enter a sound filename (usage: @sound <filename>). - return -1; + + if(!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) { + clif->message(fd, msg_txt(1217)); // Please enter a sound filename (usage: @sound <filename>). + return false; } - + if(strstr(sound_file, ".wav") == NULL) strcat(sound_file, ".wav"); - - clif_soundeffectall(&sd->bl, sound_file, 0, AREA); - - return 0; + + clif->soundeffectall(&sd->bl, sound_file, 0, AREA); + + return true; } /*========================================== * MOB Search *------------------------------------------*/ -ACMD_FUNC(mobsearch) +ACMD(mobsearch) { char mob_name[100]; int mob_id; int number = 0; struct s_mapiterator* it; - + nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%99[^\n]", mob_name) < 1) { - clif_displaymessage(fd, msg_txt(1218)); // Please enter a monster name (usage: @mobsearch <monster name>). - return -1; + clif->message(fd, msg_txt(1218)); // Please enter a monster name (usage: @mobsearch <monster name>). + return false; } - + if ((mob_id = atoi(mob_name)) == 0) - mob_id = mobdb_searchname(mob_name); + mob_id = mobdb_searchname(mob_name); if(mob_id > 0 && mobdb_checkid(mob_id) == 0){ snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1219),mob_name); // Invalid mob ID %s! - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } if(mob_id == atoi(mob_name) && mob_db(mob_id)->jname) - strcpy(mob_name,mob_db(mob_id)->jname); // --ja-- -// strcpy(mob_name,mob_db(mob_id)->name); // --en-- - + strcpy(mob_name,mob_db(mob_id)->jname); // --ja-- + // strcpy(mob_name,mob_db(mob_id)->name); // --en-- + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1220), mob_name, mapindex_id2name(sd->mapindex)); // Mob Search... %s %s - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + it = mapit_geteachmob(); for(;;) { - TBL_MOB* md = (TBL_MOB*)mapit_next(it); + TBL_MOB* md = (TBL_MOB*)mapit->next(it); if( md == NULL ) break;// no more mobs - + if( md->bl.m != sd->bl.m ) continue; if( mob_id != -1 && md->class_ != mob_id ) continue; - + ++number; if( md->spawn_timer == INVALID_TIMER ) snprintf(atcmd_output, sizeof(atcmd_output), "%2d[%3d:%3d] %s", number, md->bl.x, md->bl.y, md->name); else snprintf(atcmd_output, sizeof(atcmd_output), "%2d[%s] %s", number, "dead", md->name); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - mapit_free(it); - - return 0; + mapit->free(it); + + return true; } /*========================================== @@ -6146,21 +6117,21 @@ static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) { nullpo_ret(bl); map_clearflooritem(bl); - + return 0; } -ACMD_FUNC(cleanmap) +ACMD(cleanmap) { map_foreachinmap(atcommand_cleanfloor_sub, sd->bl.m, BL_ITEM); - clif_displaymessage(fd, msg_txt(1221)); // All dropped items have been cleaned up. - return 0; + clif->message(fd, msg_txt(1221)); // All dropped items have been cleaned up. + return true; } -ACMD_FUNC(cleanarea) +ACMD(cleanarea) { int x0 = 0, y0 = 0, x1 = 0, y1 = 0; - + if (!message || !*message || sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) < 1) { map_foreachinarea(atcommand_cleanfloor_sub, sd->bl.m, sd->bl.x - (AREA_SIZE * 2), sd->bl.y - (AREA_SIZE * 2), sd->bl.x + (AREA_SIZE * 2), sd->bl.y + (AREA_SIZE * 2), BL_ITEM); } @@ -6170,83 +6141,83 @@ ACMD_FUNC(cleanarea) else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 4) { map_foreachinarea(atcommand_cleanfloor_sub, sd->bl.m, x0, y0, x1, y1, BL_ITEM); } - - clif_displaymessage(fd, msg_txt(1221)); // All dropped items have been cleaned up. - return 0; + + clif->message(fd, msg_txt(1221)); // All dropped items have been cleaned up. + return true; } /*========================================== * make a NPC/PET talk * @npctalkc [SnakeDrak] *------------------------------------------*/ -ACMD_FUNC(npctalk) +ACMD(npctalk) { char name[NAME_LENGTH],mes[100],temp[100]; struct npc_data *nd; bool ifcolor=(*(command + 8) != 'c' && *(command + 8) != 'C')?0:1; unsigned long color=0; - + if (sd->sc.count && //no "chatting" while muted. (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; - + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return false; + if(!ifcolor) { if (!message || !*message || sscanf(message, "%23[^,], %99[^\n]", name, mes) < 2) { - clif_displaymessage(fd, msg_txt(1222)); // Please enter the correct parameters (usage: @npctalk <npc name>, <message>). - return -1; + clif->message(fd, msg_txt(1222)); // Please enter the correct parameters (usage: @npctalk <npc name>, <message>). + return false; } } else { if (!message || !*message || sscanf(message, "%lx %23[^,], %99[^\n]", &color, name, mes) < 3) { - clif_displaymessage(fd, msg_txt(1223)); // Please enter the correct parameters (usage: @npctalkc <color> <npc name>, <message>). - return -1; + clif->message(fd, msg_txt(1223)); // Please enter the correct parameters (usage: @npctalkc <color> <npc name>, <message>). + return false; } } - + if (!(nd = npc_name2id(name))) { - clif_displaymessage(fd, msg_txt(111)); // This NPC doesn't exist - return -1; + clif->message(fd, msg_txt(111)); // This NPC doesn't exist + return false; } - + strtok(name, "#"); // discard extra name identifier if present snprintf(temp, sizeof(temp), "%s : %s", name, mes); - - if(ifcolor) clif_messagecolor(&nd->bl,color,temp); - else clif_message(&nd->bl, temp); - - return 0; + + if(ifcolor) clif->messagecolor(&nd->bl,color,temp); + else clif->disp_overhead(&nd->bl, temp); + + return true; } -ACMD_FUNC(pettalk) +ACMD(pettalk) { char mes[100],temp[100]; struct pet_data *pd; - + nullpo_retr(-1, sd); - + if ( battle_config.min_chat_delay ) { if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) - return 0; + return true; sd->cantalk_tick = gettick() + battle_config.min_chat_delay; } - + if(!sd->status.pet_id || !(pd=sd->pd)) { - clif_displaymessage(fd, msg_txt(184)); - return -1; + clif->message(fd, msg_txt(184)); + return false; } - + if (sd->sc.count && //no "chatting" while muted. (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; - + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return false; + if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { - clif_displaymessage(fd, msg_txt(1224)); // Please enter a message (usage: @pettalk <message>). - return -1; + clif->message(fd, msg_txt(1224)); // Please enter a message (usage: @pettalk <message>). + return false; } - + if (message[0] == '/') {// pet emotion processing const char* emo[] = { @@ -6266,127 +6237,127 @@ ACMD_FUNC(pettalk) if( i < ARRAYLENGTH(emo) ) { if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second - sd->emotionlasttime = time(NULL); - return 0; + sd->emotionlasttime = time(NULL); + return true; } sd->emotionlasttime = time(NULL); - - clif_emotion(&pd->bl, i); - return 0; + + clif->emotion(&pd->bl, i); + return true; } } - + snprintf(temp, sizeof temp ,"%s : %s", pd->pet.name, mes); - clif_message(&pd->bl, temp); - - return 0; + clif->disp_overhead(&pd->bl, temp); + + return true; } /// @users - displays the number of players present on each map (and percentage) /// #users displays on the target user instead of self -ACMD_FUNC(users) +ACMD(users) { char buf[CHAT_SIZE_MAX]; int i; int users[MAX_MAPINDEX]; int users_all; struct s_mapiterator* iter; - + memset(users, 0, sizeof(users)); users_all = 0; - + // count users on each map iter = mapit_getallusers(); for(;;) { - struct map_session_data* sd2 = (struct map_session_data*)mapit_next(iter); + struct map_session_data* sd2 = (struct map_session_data*)mapit->next(iter); if( sd2 == NULL ) break;// no more users - + if( sd2->mapindex >= MAX_MAPINDEX ) continue;// invalid mapindex - + if( users[sd2->mapindex] < INT_MAX ) ++users[sd2->mapindex]; if( users_all < INT_MAX ) ++users_all; } - mapit_free(iter); - + mapit->free(iter); + // display results for each map for( i = 0; i < MAX_MAPINDEX; ++i ) { if( users[i] == 0 ) continue;// empty - + safesnprintf(buf, sizeof(buf), "%s: %d (%.2f%%)", mapindex_id2name(i), users[i], (float)(100.0f*users[i]/users_all)); - clif_displaymessage(sd->fd, buf); + clif->message(sd->fd, buf); } - + // display overall count safesnprintf(buf, sizeof(buf), "all: %d", users_all); - clif_displaymessage(sd->fd, buf); - - return 0; + clif->message(sd->fd, buf); + + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(reset) +ACMD(reset) { pc_resetstate(sd); pc_resetskill(sd,1); sprintf(atcmd_output, msg_txt(208), sd->status.name); // '%s' skill and stats points reseted! - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } /*========================================== * *------------------------------------------*/ -ACMD_FUNC(summon) +ACMD(summon) { char name[NAME_LENGTH]; int mob_id = 0; int duration = 0; struct mob_data *md; unsigned int tick=gettick(); - + nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1) { - clif_displaymessage(fd, msg_txt(1225)); // Please enter a monster name (usage: @summon <monster name> {duration}). - return -1; + clif->message(fd, msg_txt(1225)); // Please enter a monster name (usage: @summon <monster name> {duration}). + return false; } - + if (duration < 1) duration =1; else if (duration > 60) duration =60; - + if ((mob_id = atoi(name)) == 0) mob_id = mobdb_searchname(name); if(mob_id == 0 || mobdb_checkid(mob_id) == 0) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; + clif->message(fd, msg_txt(40)); // Invalid monster ID or name. + return false; } - + md = mob_once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_SMALL, AI_NONE); - + if(!md) - return -1; - + return false; + md->master_id=sd->bl.id; md->special_state.ai=1; md->deletetimer=add_timer(tick+(duration*60000),mob_timer_delete,md->bl.id,0); - clif_specialeffect(&md->bl,344,AREA); + clif->specialeffect(&md->bl,344,AREA); mob_spawn(md); sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); - clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick); - clif_displaymessage(fd, msg_txt(39)); // All monster summoned! - - return 0; + clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick); + clif->message(fd, msg_txt(39)); // All monster summoned! + + return true; } /*========================================== @@ -6394,117 +6365,116 @@ ACMD_FUNC(summon) * Temporarily move player to another group * Useful during beta testing to allow players to use GM commands for short periods of time *------------------------------------------*/ -ACMD_FUNC(adjgroup) +ACMD(adjgroup) { int new_group = 0; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%d", &new_group) != 1) { - clif_displaymessage(fd, msg_txt(1226)); // Usage: @adjgroup <group_id> - return -1; + clif->message(fd, msg_txt(1226)); // Usage: @adjgroup <group_id> + return false; } - + if (!pc_group_exists(new_group)) { - clif_displaymessage(fd, msg_txt(1227)); // Specified group does not exist. - return -1; + clif->message(fd, msg_txt(1227)); // Specified group does not exist. + return false; } - + sd->group_id = new_group; pc_group_pc_load(sd);/* update cache */ - clif_displaymessage(fd, msg_txt(1228)); // Group changed successfully. - clif_displaymessage(sd->fd, msg_txt(1229)); // Your group has changed. - return 0; + clif->message(fd, msg_txt(1228)); // Group changed successfully. + clif->message(sd->fd, msg_txt(1229)); // Your group has changed. + return true; } /*========================================== * @trade by [MouseJstr] * Open a trade window with a remote player *------------------------------------------*/ -ACMD_FUNC(trade) +ACMD(trade) { struct map_session_data *pl_sd = NULL; nullpo_retr(-1, sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1230)); // Please enter a player name (usage: @trade <char name>). - return -1; + clif->message(fd, msg_txt(1230)); // Please enter a player name (usage: @trade <char name>). + return false; } - + if ( (pl_sd = map_nick2sd((char *)message)) == NULL ) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + trade_traderequest(sd, pl_sd); - return 0; + return true; } /*========================================== * @setbattleflag by [MouseJstr] * set a battle_config flag without having to reboot *------------------------------------------*/ -ACMD_FUNC(setbattleflag) +ACMD(setbattleflag) { char flag[128], value[128]; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%127s %127s", flag, value) != 2) { - clif_displaymessage(fd, msg_txt(1231)); // Usage: @setbattleflag <flag> <value> - return -1; - } - - if (battle_set_value(flag, value) == 0) - { - clif_displaymessage(fd, msg_txt(1232)); // Unknown battle_config flag. - return -1; + clif->message(fd, msg_txt(1231)); // Usage: @setbattleflag <flag> <value> + return false; } - - clif_displaymessage(fd, msg_txt(1233)); // Set battle_config as requested. - - return 0; + + if (battle->config_set_value(flag, value) == 0) { + clif->message(fd, msg_txt(1232)); // Unknown battle_config flag. + return false; + } + + clif->message(fd, msg_txt(1233)); // Set battle_config as requested. + + return true; } /*========================================== * @unmute [Valaris] *------------------------------------------*/ -ACMD_FUNC(unmute) +ACMD(unmute) { struct map_session_data *pl_sd = NULL; nullpo_retr(-1, sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1234)); // Please enter a player name (usage: @unmute <char name>). - return -1; + clif->message(fd, msg_txt(1234)); // Please enter a player name (usage: @unmute <char name>). + return false; } - + if ( (pl_sd = map_nick2sd((char *)message)) == NULL ) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if(!pl_sd->sc.data[SC_NOCHAT]) { - clif_displaymessage(sd->fd,msg_txt(1235)); // Player is not muted. - return -1; + clif->message(sd->fd,msg_txt(1235)); // Player is not muted. + return false; } - + pl_sd->status.manner = 0; status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); - clif_displaymessage(sd->fd,msg_txt(1236)); // Player unmuted. - - return 0; + clif->message(sd->fd,msg_txt(1236)); // Player unmuted. + + return true; } /*========================================== * @uptime by MC Cameri *------------------------------------------*/ -ACMD_FUNC(uptime) +ACMD(uptime) { unsigned long seconds = 0, day = 24*60*60, hour = 60*60, - minute = 60, days = 0, hours = 0, minutes = 0; + minute = 60, days = 0, hours = 0, minutes = 0; nullpo_retr(-1, sd); - + seconds = get_uptime(); days = seconds/day; seconds -= (seconds/day>0)?(seconds/day)*day:0; @@ -6512,18 +6482,18 @@ ACMD_FUNC(uptime) seconds -= (seconds/hour>0)?(seconds/hour)*hour:0; minutes = seconds/minute; seconds -= (seconds/minute>0)?(seconds/minute)*minute:0; - + snprintf(atcmd_output, sizeof(atcmd_output), msg_txt(245), days, hours, minutes, seconds); - clif_displaymessage(fd, atcmd_output); - - return 0; + clif->message(fd, atcmd_output); + + return true; } /*========================================== * @changesex <sex> * => Changes one's sex. Argument sex can be 0 or 1, m or f, male or female. *------------------------------------------*/ -ACMD_FUNC(changesex) +ACMD(changesex) { int i; nullpo_retr(-1, sd); @@ -6532,38 +6502,38 @@ ACMD_FUNC(changesex) for( i=0; i<EQI_MAX; i++ ) if( sd->equip_index[i] >= 0 ) pc_unequipitem(sd, sd->equip_index[i], 3); chrif_changesex(sd); - return 0; + return true; } /*================================================ * @mute - Mutes a player for a set amount of time *------------------------------------------------*/ -ACMD_FUNC(mute) +ACMD(mute) { struct map_session_data *pl_sd = NULL; int manner; nullpo_retr(-1, sd); - + if (!message || !*message || sscanf(message, "%d %23[^\n]", &manner, atcmd_player_name) < 1) { - clif_displaymessage(fd, msg_txt(1237)); // Usage: @mute <time> <char name> - return -1; + clif->message(fd, msg_txt(1237)); // Usage: @mute <time> <char name> + return false; } - + if ( (pl_sd = map_nick2sd(atcmd_player_name)) == NULL ) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return -1; + clif->message(fd, msg_txt(3)); // Character not found. + return false; } - + if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { - clif_displaymessage(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. - return -1; + clif->message(fd, msg_txt(81)); // Your GM level don't authorise you to do this action on this player. + return false; } - - clif_manner_message(sd, 0); - clif_manner_message(pl_sd, 5); - + + clif->manner_message(sd, 0); + clif->manner_message(pl_sd, 5); + if( pl_sd->status.manner < manner ) { pl_sd->status.manner -= manner; sc_start(&pl_sd->bl,SC_NOCHAT,100,0,0); @@ -6571,124 +6541,125 @@ ACMD_FUNC(mute) pl_sd->status.manner = 0; status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER); } - - clif_GM_silence(sd, pl_sd, (manner > 0 ? 1 : 0)); - - return 0; + + clif->GM_silence(sd, pl_sd, (manner > 0 ? 1 : 0)); + + return true; } /*========================================== * @refresh (like @jumpto <<yourself>>) *------------------------------------------*/ -ACMD_FUNC(refresh) +ACMD(refresh) { nullpo_retr(-1, sd); - clif_refresh(sd); - return 0; + clif->refresh(sd); + return true; } -ACMD_FUNC(refreshall) +ACMD(refreshall) { struct map_session_data* iter_sd; struct s_mapiterator* iter; nullpo_retr(-1, sd); - + iter = mapit_getallusers(); - for (iter_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); iter_sd = (TBL_PC*)mapit_next(iter)) - clif_refresh(iter_sd); - mapit_free(iter); - return 0; + for (iter_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); iter_sd = (TBL_PC*)mapit->next(iter)) + clif->refresh(iter_sd); + mapit->free(iter); + return true; } /*========================================== * @identify * => GM's magnifier. *------------------------------------------*/ -ACMD_FUNC(identify) +ACMD(identify) { int i,num; - + nullpo_retr(-1, sd); - + for(i=num=0;i<MAX_INVENTORY;i++){ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){ num++; } } if (num > 0) { - clif_item_identify_list(sd); + clif->item_identify_list(sd); } else { - clif_displaymessage(fd,msg_txt(1238)); // There are no items to appraise. + clif->message(fd,msg_txt(1238)); // There are no items to appraise. } - return 0; + return true; } /*========================================== * @gmotd (Global MOTD) * by davidsiaw :P *------------------------------------------*/ -ACMD_FUNC(gmotd) +ACMD(gmotd) { - char buf[CHAT_SIZE_MAX]; - size_t len; FILE* fp; - + if( ( fp = fopen(motd_txt, "r") ) != NULL ) { + char buf[CHAT_SIZE_MAX]; + size_t len; + while( fgets(buf, sizeof(buf), fp) ) { if( buf[0] == '/' && buf[1] == '/' ) { continue; } - + len = strlen(buf); - + while( len && ( buf[len-1] == '\r' || buf[len-1] == '\n' ) ) {// strip trailing EOL characters len--; } - + if( len ) { buf[len] = 0; - + intif_broadcast(buf, len+1, 0); } } fclose(fp); } - return 0; + return true; } -ACMD_FUNC(misceffect) +ACMD(misceffect) { int effect = 0; nullpo_retr(-1, sd); if (!message || !*message) - return -1; + return false; if (sscanf(message, "%d", &effect) < 1) - return -1; - clif_misceffect(&sd->bl,effect); - - return 0; + return false; + clif->misceffect(&sd->bl,effect); + + return true; } /*========================================== * MAIL SYSTEM *------------------------------------------*/ -ACMD_FUNC(mail) +ACMD(mail) { nullpo_ret(sd); mail_openmail(sd); - return 0; + return true; } /*========================================== * Show Monster DB Info v 1.0 * originally by [Lupus] *------------------------------------------*/ -ACMD_FUNC(mobinfo) +ACMD(mobinfo) { unsigned char msize[3][7] = {"Small", "Medium", "Large"}; unsigned char mrace[12][11] = {"Formless", "Undead", "Beast", "Plant", "Insect", "Fish", "Demon", "Demi-Human", "Angel", "Dragon", "Boss", "Non-Boss"}; @@ -6698,15 +6669,15 @@ ACMD_FUNC(mobinfo) struct mob_db *mob, *mob_array[MAX_SEARCH]; int count; int i, j, k; - + memset(atcmd_output, '\0', sizeof(atcmd_output)); memset(atcmd_output2, '\0', sizeof(atcmd_output2)); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1239)); // Please enter a monster name/ID (usage: @mobinfo <monster_name_or_monster_ID>). - return -1; + clif->message(fd, msg_txt(1239)); // Please enter a monster name/ID (usage: @mobinfo <monster_name_or_monster_ID>). + return false; } - + // If monster identifier/name argument is a name if ((i = mobdb_checkid(atoi(message)))) { @@ -6714,40 +6685,40 @@ ACMD_FUNC(mobinfo) count = 1; } else count = mobdb_searchname_array(mob_array, MAX_SEARCH, message); - + if (!count) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; + clif->message(fd, msg_txt(40)); // Invalid monster ID or name. + return false; } - + if (count > MAX_SEARCH) { sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); count = MAX_SEARCH; } for (k = 0; k < count; k++) { mob = mob_array[k]; - + // stats if (mob->mexp) sprintf(atcmd_output, msg_txt(1240), mob->name, mob->jname, mob->sprite, mob->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d) else sprintf(atcmd_output, msg_txt(1241), mob->name, mob->jname, mob->sprite, mob->vd.class_); // Monster: '%s'/'%s'/'%s' (%d) - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1242), mob->lv, mob->status.max_hp, mob->base_exp, mob->job_exp,MOB_HIT(mob), MOB_FLEE(mob)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output, msg_txt(1243), // DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d - mob->status.def, mob->status.mdef,mob->status.str, mob->status.agi, - mob->status.vit, mob->status.int_, mob->status.dex, mob->status.luk); - clif_displaymessage(fd, atcmd_output); - + mob->status.def, mob->status.mdef,mob->status.str, mob->status.agi, + mob->status.vit, mob->status.int_, mob->status.dex, mob->status.luk); + clif->message(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d) - mob->status.rhw.atk, mob->status.rhw.atk2, mob->status.rhw.range, - mob->range2 , mob->range3, msize[mob->status.size], - mrace[mob->status.race], melement[mob->status.def_ele], mob->status.ele_lv); - clif_displaymessage(fd, atcmd_output); + mob->status.rhw.atk, mob->status.rhw.atk2, mob->status.rhw.range, + mob->range2 , mob->range3, msize[mob->status.size], + mrace[mob->status.race], melement[mob->status.def_ele], mob->status.ele_lv); + clif->message(fd, atcmd_output); // drops - clif_displaymessage(fd, msg_txt(1245)); // Drops: + clif->message(fd, msg_txt(1245)); // Drops: strcpy(atcmd_output, " "); j = 0; for (i = 0; i < MAX_MOB_DROP; i++) { @@ -6755,25 +6726,25 @@ ACMD_FUNC(mobinfo) if (mob->dropitem[i].nameid <= 0 || mob->dropitem[i].p < 1 || (item_data = itemdb_exists(mob->dropitem[i].nameid)) == NULL) continue; droprate = mob->dropitem[i].p; - + if (item_data->slot) sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, (float)droprate / 100); else sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)droprate / 100); strcat(atcmd_output, atcmd_output2); if (++j % 3 == 0) { - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); strcpy(atcmd_output, " "); } } if (j == 0) - clif_displaymessage(fd, msg_txt(1246)); // This monster has no drops. + clif->message(fd, msg_txt(1246)); // This monster has no drops. else if (j % 3 != 0) - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); // mvp if (mob->mexp) { sprintf(atcmd_output, msg_txt(1247), mob->mexp); // MVP Bonus EXP:%u - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); strcpy(atcmd_output, msg_txt(1248)); // MVP Items: j = 0; for (i = 0; i < MAX_MVP_DROP; i++) { @@ -6789,58 +6760,58 @@ ACMD_FUNC(mobinfo) } } if (j == 0) - clif_displaymessage(fd, msg_txt(1249)); // This monster has no MVP prizes. + clif->message(fd, msg_txt(1249)); // This monster has no MVP prizes. else - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } } - return 0; + return true; } /*========================================= -* @showmobs by KarLaeda -* => For 15 sec displays the mobs on minimap -*------------------------------------------*/ -ACMD_FUNC(showmobs) + * @showmobs by KarLaeda + * => For 15 sec displays the mobs on minimap + *------------------------------------------*/ +ACMD(showmobs) { char mob_name[100]; int mob_id; int number = 0; struct s_mapiterator* it; - + nullpo_retr(-1, sd); - + if(sscanf(message, "%99[^\n]", mob_name) < 0) - return -1; - + return false; + if((mob_id = atoi(mob_name)) == 0) mob_id = mobdb_searchname(mob_name); if(mob_id > 0 && mobdb_checkid(mob_id) == 0){ snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1250),mob_name); // Invalid mob id %s! - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } - + if(mob_db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)){ // If player group does not have access to boss mobs. - clif_displaymessage(fd, msg_txt(1251)); // Can't show boss mobs! - return 0; + clif->message(fd, msg_txt(1251)); // Can't show boss mobs! + return true; } - + if(mob_id == atoi(mob_name) && mob_db(mob_id)->jname) strcpy(mob_name,mob_db(mob_id)->jname); // --ja-- - //strcpy(mob_name,mob_db(mob_id)->name); // --en-- - + //strcpy(mob_name,mob_db(mob_id)->name); // --en-- + snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1252), // Mob Search... %s %s - mob_name, mapindex_id2name(sd->mapindex)); - clif_displaymessage(fd, atcmd_output); - + mob_name, mapindex_id2name(sd->mapindex)); + clif->message(fd, atcmd_output); + it = mapit_geteachmob(); for(;;) { - TBL_MOB* md = (TBL_MOB*)mapit_next(it); + TBL_MOB* md = (TBL_MOB*)mapit->next(it); if( md == NULL ) break;// no more mobs - + if( md->bl.m != sd->bl.m ) continue; if( mob_id != -1 && md->class_ != mob_id ) @@ -6849,444 +6820,445 @@ ACMD_FUNC(showmobs) continue; // hide slaves and player summoned mobs if( md->spawn_timer != INVALID_TIMER ) continue; // hide mobs waiting for respawn - + ++number; - clif_viewpoint(sd, 1, 0, md->bl.x, md->bl.y, number, 0xFFFFFF); + clif->viewpoint(sd, 1, 0, md->bl.x, md->bl.y, number, 0xFFFFFF); } - mapit_free(it); - - return 0; + mapit->free(it); + + return true; } /*========================================== * homunculus level up [orn] *------------------------------------------*/ -ACMD_FUNC(homlevel) +ACMD(homlevel) { TBL_HOM * hd; - int level = 0, i = 0; - + int level = 0; + nullpo_retr(-1, sd); - + if ( !message || !*message || ( level = atoi(message) ) < 1 ) { - clif_displaymessage(fd, msg_txt(1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>). - return -1; + clif->message(fd, msg_txt(1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>). + return false; } - - if ( !merc_is_hom_active(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + + if ( !homun_alive(sd->hd) ) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - + hd = sd->hd; - - for (i = 1; i <= level && hd->exp_next; i++){ + + if ( battle_config.hom_max_level == hd->homunculus.level ) // Already reach maximum level + return true; + + do{ hd->homunculus.exp += hd->exp_next; - merc_hom_levelup(hd); - } + } while( hd->homunculus.level < level && homun->levelup(hd) ); + status_calc_homunculus(hd,0); status_percent_heal(&hd->bl, 100, 100); - clif_specialeffect(&hd->bl,568,AREA); - return 0; + clif->specialeffect(&hd->bl,568,AREA); + return true; } /*========================================== * homunculus evolution H [orn] *------------------------------------------*/ -ACMD_FUNC(homevolution) +ACMD(homevolution) { nullpo_retr(-1, sd); - - if ( !merc_is_hom_active(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + + if ( !homun_alive(sd->hd) ) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - - if ( !merc_hom_evolution(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1255)); // Your homunculus doesn't evolve. - return -1; + + if ( !homun->evolve(sd->hd) ) { + clif->message(fd, msg_txt(1255)); // Your homunculus doesn't evolve. + return false; } - clif_homskillinfoblock(sd); - return 0; + clif->homskillinfoblock(sd); + return true; } -ACMD_FUNC(hommutate) -{ - int homun_id, m_class = 0, m_id; +ACMD(hommutate) { + int homun_id; + enum homun_type m_class, m_id; nullpo_retr(-1, sd); - - if (!merc_is_hom_active(sd->hd)) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + + if (!homun_alive(sd->hd)) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - + if (!message || !*message) { homun_id = 6048 + (rnd() % 4); } else { homun_id = atoi(message); } - - m_class = hom_class2mapid(sd->hd->homunculus.class_); - m_id = hom_class2mapid(homun_id); - - if (m_class != -1 && m_id != -1 && m_class&HOM_EVO && m_id&HOM_S && sd->hd->homunculus.level >= 99) { - hom_mutate(sd->hd, homun_id); + + m_class = homun->class2type(sd->hd->homunculus.class_); + m_id = homun->class2type(homun_id); + + if (m_class != -1 && m_id != -1 && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99) { + homun->mutate(sd->hd, homun_id); } else { - clif_emotion(&sd->hd->bl, E_SWT); + clif->emotion(&sd->hd->bl, E_SWT); } - return 0; + return true; } /*========================================== * call choosen homunculus [orn] *------------------------------------------*/ -ACMD_FUNC(makehomun) -{ +ACMD(makehomun) { int homunid; nullpo_retr(-1, sd); - + if ( sd->status.hom_id ) { - clif_displaymessage(fd, msg_txt(450)); - return -1; + clif->message(fd, msg_txt(450)); + return false; } - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>). - return -1; + clif->message(fd, msg_txt(1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>). + return false; } - + homunid = atoi(message); if( homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1 ) { - clif_displaymessage(fd, msg_txt(1257)); // Invalid Homunculus ID. - return -1; + clif->message(fd, msg_txt(1257)); // Invalid Homunculus ID. + return false; } - - merc_create_homunculus_request(sd,homunid); - return 0; + + homun->creation_request(sd,homunid); + return true; } /*========================================== * modify homunculus intimacy [orn] *------------------------------------------*/ -ACMD_FUNC(homfriendly) +ACMD(homfriendly) { int friendly = 0; - + nullpo_retr(-1, sd); - - if ( !merc_is_hom_active(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + + if ( !homun_alive(sd->hd) ) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1258)); // Please enter a friendly value (usage: @homfriendly <friendly value [0-1000]>). - return -1; + clif->message(fd, msg_txt(1258)); // Please enter a friendly value (usage: @homfriendly <friendly value [0-1000]>). + return false; } - + friendly = atoi(message); friendly = cap_value(friendly, 0, 1000); - + sd->hd->homunculus.intimacy = friendly * 100 ; - clif_send_homdata(sd,SP_INTIMATE,friendly); - return 0; + clif->send_homdata(sd,SP_INTIMATE,friendly); + return true; } /*========================================== * modify homunculus hunger [orn] *------------------------------------------*/ -ACMD_FUNC(homhungry) +ACMD(homhungry) { int hungry = 0; - + nullpo_retr(-1, sd); - - if ( !merc_is_hom_active(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + + if ( !homun_alive(sd->hd) ) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1259)); // Please enter a hunger value (usage: @homhungry <hunger value [0-100]>). - return -1; + clif->message(fd, msg_txt(1259)); // Please enter a hunger value (usage: @homhungry <hunger value [0-100]>). + return false; } - + hungry = atoi(message); hungry = cap_value(hungry, 0, 100); - + sd->hd->homunculus.hunger = hungry; - clif_send_homdata(sd,SP_HUNGRY,hungry); - return 0; + clif->send_homdata(sd,SP_HUNGRY,hungry); + return true; } /*========================================== * make the homunculus speak [orn] *------------------------------------------*/ -ACMD_FUNC(homtalk) +ACMD(homtalk) { char mes[100],temp[100]; - + nullpo_retr(-1, sd); - + if ( battle_config.min_chat_delay ) { if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) - return 0; + return true; sd->cantalk_tick = gettick() + battle_config.min_chat_delay; } - + if (sd->sc.count && //no "chatting" while muted. (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; - - if ( !merc_is_hom_active(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return false; + + if ( !homun_alive(sd->hd) ) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - + if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) { - clif_displaymessage(fd, msg_txt(1260)); // Please enter a message (usage: @homtalk <message>). - return -1; + clif->message(fd, msg_txt(1260)); // Please enter a message (usage: @homtalk <message>). + return false; } - + snprintf(temp, sizeof temp ,"%s : %s", sd->hd->homunculus.name, mes); - clif_message(&sd->hd->bl, temp); - - return 0; + clif->disp_overhead(&sd->hd->bl, temp); + + return true; } /*========================================== * Show homunculus stats *------------------------------------------*/ -ACMD_FUNC(hominfo) +ACMD(hominfo) { struct homun_data *hd; struct status_data *status; nullpo_retr(-1, sd); - - if ( !merc_is_hom_active(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + + if ( !homun_alive(sd->hd) ) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - + hd = sd->hd; status = status_get_status_data(&hd->bl); - clif_displaymessage(fd, msg_txt(1261)); // Homunculus stats: - + clif->message(fd, msg_txt(1261)); // Homunculus stats: + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1262), // HP: %d/%d - SP: %d/%d - status->hp, status->max_hp, status->sp, status->max_sp); - clif_displaymessage(fd, atcmd_output); - + status->hp, status->max_hp, status->sp, status->max_sp); + clif->message(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1263), // ATK: %d - MATK: %d~%d - status->rhw.atk2 +status->batk, status->matk_min, status->matk_max); - clif_displaymessage(fd, atcmd_output); - + status->rhw.atk2 +status->batk, status->matk_min, status->matk_max); + clif->message(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1264), // Hungry: %d - Intimacy: %u - hd->homunculus.hunger, hd->homunculus.intimacy/100); - clif_displaymessage(fd, atcmd_output); - + hd->homunculus.hunger, hd->homunculus.intimacy/100); + clif->message(fd, atcmd_output); + snprintf(atcmd_output, sizeof(atcmd_output) , - msg_txt(1265), // Stats: Str %d / Agi %d / Vit %d / Int %d / Dex %d / Luk %d - status->str, status->agi, status->vit, - status->int_, status->dex, status->luk); - clif_displaymessage(fd, atcmd_output); - - return 0; + msg_txt(1265), // Stats: Str %d / Agi %d / Vit %d / Int %d / Dex %d / Luk %d + status->str, status->agi, status->vit, + status->int_, status->dex, status->luk); + clif->message(fd, atcmd_output); + + return true; } -ACMD_FUNC(homstats) +ACMD(homstats) { struct homun_data *hd; struct s_homunculus_db *db; struct s_homunculus *hom; int lv, min, max, evo; - + nullpo_retr(-1, sd); - - if ( !merc_is_hom_active(sd->hd) ) { - clif_displaymessage(fd, msg_txt(1254)); // You do not have a homunculus. - return -1; + + if ( !homun_alive(sd->hd) ) { + clif->message(fd, msg_txt(1254)); // You do not have a homunculus. + return false; } - + hd = sd->hd; - + hom = &hd->homunculus; db = hd->homunculusDB; lv = hom->level; - + snprintf(atcmd_output, sizeof(atcmd_output) , - msg_txt(1266), lv, db->name); // Homunculus growth stats (Lv %d %s): - clif_displaymessage(fd, atcmd_output); + msg_txt(1266), lv, db->name); // Homunculus growth stats (Lv %d %s): + clif->message(fd, atcmd_output); lv--; //Since the first increase is at level 2. - + evo = (hom->class_ == db->evo_class); min = db->base.HP +lv*db->gmin.HP +(evo?db->emin.HP:0); max = db->base.HP +lv*db->gmax.HP +(evo?db->emax.HP:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1267), hom->max_hp, min, max); // Max HP: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + min = db->base.SP +lv*db->gmin.SP +(evo?db->emin.SP:0); max = db->base.SP +lv*db->gmax.SP +(evo?db->emax.SP:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1268), hom->max_sp, min, max); // Max SP: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + min = db->base.str +lv*(db->gmin.str/10) +(evo?db->emin.str:0); max = db->base.str +lv*(db->gmax.str/10) +(evo?db->emax.str:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1269), hom->str/10, min, max); // Str: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + min = db->base.agi +lv*(db->gmin.agi/10) +(evo?db->emin.agi:0); max = db->base.agi +lv*(db->gmax.agi/10) +(evo?db->emax.agi:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1270), hom->agi/10, min, max); // Agi: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + min = db->base.vit +lv*(db->gmin.vit/10) +(evo?db->emin.vit:0); max = db->base.vit +lv*(db->gmax.vit/10) +(evo?db->emax.vit:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1271), hom->vit/10, min, max); // Vit: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + min = db->base.int_ +lv*(db->gmin.int_/10) +(evo?db->emin.int_:0); max = db->base.int_ +lv*(db->gmax.int_/10) +(evo?db->emax.int_:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1272), hom->int_/10, min, max); // Int: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + min = db->base.dex +lv*(db->gmin.dex/10) +(evo?db->emin.dex:0); max = db->base.dex +lv*(db->gmax.dex/10) +(evo?db->emax.dex:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1273), hom->dex/10, min, max); // Dex: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + min = db->base.luk +lv*(db->gmin.luk/10) +(evo?db->emin.luk:0); max = db->base.luk +lv*(db->gmax.luk/10) +(evo?db->emax.luk:0);; snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1274), hom->luk/10, min, max); // Luk: %d (%d~%d) - clif_displaymessage(fd, atcmd_output); - - return 0; + clif->message(fd, atcmd_output); + + return true; } -ACMD_FUNC(homshuffle) -{ +ACMD(homshuffle) { nullpo_retr(-1, sd); - + if(!sd->hd) - return -1; // nothing to do - - if(!merc_hom_shuffle(sd->hd)) - return -1; - - clif_displaymessage(sd->fd, msg_txt(1275)); // Homunculus stats altered. - atcommand_homstats(fd, sd, command, message); //Print out the new stats - return 0; + return false; // nothing to do + + if(!homun->shuffle(sd->hd)) + return false; + + clif->message(sd->fd, msg_txt(1275)); // Homunculus stats altered. + atcommand_homstats(fd, sd, command, message, info); //Print out the new stats + return true; } /*========================================== * Show Items DB Info v 1.0 * originally by [Lupus] *------------------------------------------*/ -ACMD_FUNC(iteminfo) +ACMD(iteminfo) { struct item_data *item_data, *item_array[MAX_SEARCH]; int i, count = 1; - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>). - return -1; + clif->message(fd, msg_txt(1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>). + return false; } if ((item_array[0] = itemdb_exists(atoi(message))) == NULL) count = itemdb_searchname_array(item_array, MAX_SEARCH, message); - + if (!count) { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; + clif->message(fd, msg_txt(19)); // Invalid item ID or name. + return false; } - + if (count > MAX_SEARCH) { sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); count = MAX_SEARCH; } for (i = 0; i < count; i++) { item_data = item_array[i]; sprintf(atcmd_output, msg_txt(1277), // Item: '%s'/'%s'[%d] (%d) Type: %s | Extra Effect: %s - item_data->name,item_data->jname,item_data->slot,item_data->nameid, - itemdb_typename(item_data->type), - (item_data->script==NULL)? msg_txt(1278) : msg_txt(1279) // None / With script - ); - clif_displaymessage(fd, atcmd_output); - + item_data->name,item_data->jname,item_data->slot,item_data->nameid, + itemdb_typename(item_data->type), + (item_data->script==NULL)? msg_txt(1278) : msg_txt(1279) // None / With script + ); + clif->message(fd, atcmd_output); + sprintf(atcmd_output, msg_txt(1280), item_data->value_buy, item_data->value_sell, item_data->weight/10. ); // NPC Buy:%dz, Sell:%dz | Weight: %.1f - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + if (item_data->maxchance == -1) strcpy(atcmd_output, msg_txt(1281)); // - Available in the shops only. else if (!battle_config.atcommand_mobinfo_type && item_data->maxchance) sprintf(atcmd_output, msg_txt(1282), (float)item_data->maxchance / 100 ); // - Maximal monsters drop chance: %02.02f%% else strcpy(atcmd_output, msg_txt(1283)); // - Monsters don't drop this item. - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + } - return 0; + return true; } /*========================================== * Show who drops the item. *------------------------------------------*/ -ACMD_FUNC(whodrops) +ACMD(whodrops) { struct item_data *item_data, *item_array[MAX_SEARCH]; int i,j, count = 1; - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>). - return -1; + clif->message(fd, msg_txt(1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>). + return false; } if ((item_array[0] = itemdb_exists(atoi(message))) == NULL) count = itemdb_searchname_array(item_array, MAX_SEARCH, message); - + if (!count) { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; + clif->message(fd, msg_txt(19)); // Invalid item ID or name. + return false; } - + if (count > MAX_SEARCH) { sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); count = MAX_SEARCH; } for (i = 0; i < count; i++) { item_data = item_array[i]; sprintf(atcmd_output, msg_txt(1285), item_data->jname,item_data->slot); // Item: '%s'[%d] - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + if (item_data->mob[0].chance == 0) { strcpy(atcmd_output, msg_txt(1286)); // - Item is not dropped by mobs. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } else { sprintf(atcmd_output, msg_txt(1287), MAX_SEARCH); // - Common mobs with highest drop chance (only max %d are listed): - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++) { sprintf(atcmd_output, "- %s (%02.02f%%)", mob_db(item_data->mob[j].id)->jname, item_data->mob[j].chance/100.); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } } } - return 0; + return true; } -ACMD_FUNC(whereis) +ACMD(whereis) { struct mob_db *mob, *mob_array[MAX_SEARCH]; int count; int i, j, k; - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1288)); // Please enter a monster name/ID (usage: @whereis <monster_name_or_monster_ID>). - return -1; + clif->message(fd, msg_txt(1288)); // Please enter a monster name/ID (usage: @whereis <monster_name_or_monster_ID>). + return false; } - + // If monster identifier/name argument is a name if ((i = mobdb_checkid(atoi(message)))) { @@ -7294,47 +7266,50 @@ ACMD_FUNC(whereis) count = 1; } else count = mobdb_searchname_array(mob_array, MAX_SEARCH, message); - + if (!count) { - clif_displaymessage(fd, msg_txt(40)); // Invalid monster ID or name. - return -1; + clif->message(fd, msg_txt(40)); // Invalid monster ID or name. + return false; } - + if (count > MAX_SEARCH) { sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); count = MAX_SEARCH; } for (k = 0; k < count; k++) { mob = mob_array[k]; snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1289), mob->jname); // %s spawns in: - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + for (i = 0; i < ARRAYLENGTH(mob->spawn) && mob->spawn[i].qty; i++) { j = map_mapindex2mapid(mob->spawn[i].mapindex); if (j < 0) continue; snprintf(atcmd_output, sizeof atcmd_output, "%s (%d)", map[j].name, mob->spawn[i].qty); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } if (i == 0) - clif_displaymessage(fd, msg_txt(1290)); // This monster does not spawn normally. + clif->message(fd, msg_txt(1290)); // This monster does not spawn normally. } - - return 0; + + return true; } -ACMD_FUNC(version) -{ - const char * revision; - - if ((revision = get_svn_revision()) != 0) { - sprintf(atcmd_output,msg_txt(1295),revision); // rAthena Version SVN r%s - clif_displaymessage(fd,atcmd_output); +ACMD(version) { + const char *git = get_git_hash(); + const char *svn = get_svn_revision(); + + if ( git[0] != HERC_UNKNOWN_VER ) { + sprintf(atcmd_output,msg_txt(1295),git); // Git Hash '%s' + clif->message(fd,atcmd_output); + } else if ( svn[0] != HERC_UNKNOWN_VER ) { + sprintf(atcmd_output,msg_txt(1436),git); // SVN r%s + clif->message(fd,atcmd_output); } else - clif_displaymessage(fd,msg_txt(1296)); // Cannot determine SVN revision. - - return 0; + clif->message(fd,msg_txt(1296)); // Cannot determine version + + return true; } /*========================================== @@ -7342,15 +7317,15 @@ ACMD_FUNC(version) *------------------------------------------*/ static int atcommand_mutearea_sub(struct block_list *bl,va_list ap) { - + int time, id; struct map_session_data *pl_sd = (struct map_session_data *)bl; if (pl_sd == NULL) return 0; - + id = va_arg(ap, int); time = va_arg(ap, int); - + if (id != bl->id && !pc_get_group_level(pl_sd)) { pl_sd->status.manner -= time; if (pl_sd->status.manner < 0) @@ -7361,248 +7336,248 @@ static int atcommand_mutearea_sub(struct block_list *bl,va_list ap) return 0; } -ACMD_FUNC(mutearea) +ACMD(mutearea) { int time; nullpo_ret(sd); - + if (!message || !*message) { - clif_displaymessage(fd, msg_txt(1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>). - return -1; + clif->message(fd, msg_txt(1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>). + return false; } - + time = atoi(message); - + map_foreachinarea(atcommand_mutearea_sub,sd->bl.m, - sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, - sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd->bl.id, time); - - return 0; + sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, + sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd->bl.id, time); + + return true; } -ACMD_FUNC(rates) +ACMD(rates) { char buf[CHAT_SIZE_MAX]; - + nullpo_ret(sd); memset(buf, '\0', sizeof(buf)); - + snprintf(buf, CHAT_SIZE_MAX, msg_txt(1298), // Experience rates: Base %.2fx / Job %.2fx - battle_config.base_exp_rate/100., battle_config.job_exp_rate/100.); - clif_displaymessage(fd, buf); + battle_config.base_exp_rate/100., battle_config.job_exp_rate/100.); + clif->message(fd, buf); snprintf(buf, CHAT_SIZE_MAX, msg_txt(1299), // Normal Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx - battle_config.item_rate_common/100., battle_config.item_rate_heal/100., battle_config.item_rate_use/100., battle_config.item_rate_equip/100., battle_config.item_rate_card/100.); - clif_displaymessage(fd, buf); + battle_config.item_rate_common/100., battle_config.item_rate_heal/100., battle_config.item_rate_use/100., battle_config.item_rate_equip/100., battle_config.item_rate_card/100.); + clif->message(fd, buf); snprintf(buf, CHAT_SIZE_MAX, msg_txt(1300), // Boss Drop Rates: Common %.2fx / Healing %.2fx / Usable %.2fx / Equipment %.2fx / Card %.2fx - battle_config.item_rate_common_boss/100., battle_config.item_rate_heal_boss/100., battle_config.item_rate_use_boss/100., battle_config.item_rate_equip_boss/100., battle_config.item_rate_card_boss/100.); - clif_displaymessage(fd, buf); + battle_config.item_rate_common_boss/100., battle_config.item_rate_heal_boss/100., battle_config.item_rate_use_boss/100., battle_config.item_rate_equip_boss/100., battle_config.item_rate_card_boss/100.); + clif->message(fd, buf); snprintf(buf, CHAT_SIZE_MAX, msg_txt(1301), // Other Drop Rates: MvP %.2fx / Card-Based %.2fx / Treasure %.2fx - battle_config.item_rate_mvp/100., battle_config.item_rate_adddrop/100., battle_config.item_rate_treasure/100.); - clif_displaymessage(fd, buf); - - return 0; + battle_config.item_rate_mvp/100., battle_config.item_rate_adddrop/100., battle_config.item_rate_treasure/100.); + clif->message(fd, buf); + + return true; } /*========================================== * @me by lordalfa * => Displays the OUTPUT string on top of the Visible players Heads. *------------------------------------------*/ -ACMD_FUNC(me) +ACMD(me) { char tempmes[CHAT_SIZE_MAX]; nullpo_retr(-1, sd); - + memset(tempmes, '\0', sizeof(tempmes)); memset(atcmd_output, '\0', sizeof(atcmd_output)); - + if (sd->sc.count && //no "chatting" while muted. (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || - (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) - return -1; - + (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT))) + return false; + if (!message || !*message || sscanf(message, "%199[^\n]", tempmes) < 0) { - clif_displaymessage(fd, msg_txt(1302)); // Please enter a message (usage: @me <message>). - return -1; + clif->message(fd, msg_txt(1302)); // Please enter a message (usage: @me <message>). + return false; } - + sprintf(atcmd_output, msg_txt(270), sd->status.name, tempmes); // *%s %s* - clif_disp_overhead(sd, atcmd_output); - - return 0; - + clif->disp_overhead(&sd->bl, atcmd_output); + + return true; + } /*========================================== * @size * => Resize your character sprite. [Valaris] *------------------------------------------*/ -ACMD_FUNC(size) +ACMD(size) { int size = 0; nullpo_retr(-1, sd); - + size = cap_value(atoi(message),SZ_SMALL,SZ_BIG); - + if(sd->state.size) { sd->state.size = SZ_SMALL; pc_setpos(sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_TELEPORT); } - + sd->state.size = size; if( size == SZ_MEDIUM ) - clif_specialeffect(&sd->bl,420,AREA); + clif->specialeffect(&sd->bl,420,AREA); else if( size == SZ_BIG ) - clif_specialeffect(&sd->bl,422,AREA); - - clif_displaymessage(fd, msg_txt(1303)); // Size change applied. - return 0; + clif->specialeffect(&sd->bl,422,AREA); + + clif->message(fd, msg_txt(1303)); // Size change applied. + return true; } -ACMD_FUNC(sizeall) +ACMD(sizeall) { int size; struct map_session_data *pl_sd; struct s_mapiterator* iter; - + size = atoi(message); size = cap_value(size,0,2); - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) { + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if( pl_sd->state.size != size ) { if( pl_sd->state.size ) { pl_sd->state.size = SZ_SMALL; pc_setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); } - + pl_sd->state.size = size; if( size == SZ_MEDIUM ) - clif_specialeffect(&pl_sd->bl,420,AREA); + clif->specialeffect(&pl_sd->bl,420,AREA); else if( size == SZ_BIG ) - clif_specialeffect(&pl_sd->bl,422,AREA); + clif->specialeffect(&pl_sd->bl,422,AREA); } } - mapit_free(iter); - - clif_displaymessage(fd, msg_txt(1303)); // Size change applied. - return 0; + mapit->free(iter); + + clif->message(fd, msg_txt(1303)); // Size change applied. + return true; } -ACMD_FUNC(sizeguild) +ACMD(sizeguild) { int size = 0, i; - char guild[NAME_LENGTH]; + char guild_name[NAME_LENGTH]; struct map_session_data *pl_sd; struct guild *g; nullpo_retr(-1, sd); - + memset(guild, '\0', sizeof(guild)); - - if( !message || !*message || sscanf(message, "%d %23[^\n]", &size, guild) < 2 ) { - clif_displaymessage(fd, msg_txt(1304)); // Please enter guild name/ID (usage: @sizeguild <size> <guild name/ID>). - return -1; + + if( !message || !*message || sscanf(message, "%d %23[^\n]", &size, guild_name) < 2 ) { + clif->message(fd, msg_txt(1304)); // Please enter guild name/ID (usage: @sizeguild <size> <guild name/ID>). + return false; } - - if( (g = guild_searchname(guild)) == NULL && (g = guild_search(atoi(guild))) == NULL ) { - clif_displaymessage(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. - return -1; + + if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(guild_name))) == NULL ) { + clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online. + return false; } - + size = cap_value(size,SZ_SMALL,SZ_BIG); - + for( i = 0; i < g->max_member; i++ ) { if( (pl_sd = g->member[i].sd) && pl_sd->state.size != size ) { if( pl_sd->state.size ) { pl_sd->state.size = SZ_SMALL; pc_setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT); } - + pl_sd->state.size = size; if( size == SZ_MEDIUM ) - clif_specialeffect(&pl_sd->bl,420,AREA); + clif->specialeffect(&pl_sd->bl,420,AREA); else if( size == SZ_BIG ) - clif_specialeffect(&pl_sd->bl,422,AREA); + clif->specialeffect(&pl_sd->bl,422,AREA); } } - - clif_displaymessage(fd, msg_txt(1303)); // Size change applied. - return 0; + + clif->message(fd, msg_txt(1303)); // Size change applied. + return true; } /*========================================== * @monsterignore * => Makes monsters ignore you. [Valaris] *------------------------------------------*/ -ACMD_FUNC(monsterignore) +ACMD(monsterignore) { nullpo_retr(-1, sd); - + if (!sd->state.monster_ignore) { sd->state.monster_ignore = 1; - clif_displaymessage(sd->fd, msg_txt(1305)); // You are now immune to attacks. + clif->message(sd->fd, msg_txt(1305)); // You are now immune to attacks. } else { sd->state.monster_ignore = 0; - clif_displaymessage(sd->fd, msg_txt(1306)); // Returned to normal state. + clif->message(sd->fd, msg_txt(1306)); // Returned to normal state. } - - return 0; + + return true; } /*========================================== * @fakename * => Gives your character a fake name. [Valaris] *------------------------------------------*/ -ACMD_FUNC(fakename) +ACMD(fakename) { nullpo_retr(-1, sd); - + if( !message || !*message ) { if( sd->fakename[0] ) { sd->fakename[0] = '\0'; - clif_charnameack(0, &sd->bl); - clif_displaymessage(sd->fd, msg_txt(1307)); // Returned to real name. - return 0; + clif->charnameack(0, &sd->bl); + clif->message(sd->fd, msg_txt(1307)); // Returned to real name. + return true; } - - clif_displaymessage(sd->fd, msg_txt(1308)); // You must enter a name. - return -1; + + clif->message(sd->fd, msg_txt(1308)); // You must enter a name. + return false; } - + if( strlen(message) < 2 ) { - clif_displaymessage(sd->fd, msg_txt(1309)); // Fake name must be at least two characters. - return -1; + clif->message(sd->fd, msg_txt(1309)); // Fake name must be at least two characters. + return false; } - + safestrncpy(sd->fakename, message, sizeof(sd->fakename)); - clif_charnameack(0, &sd->bl); - clif_displaymessage(sd->fd, msg_txt(1310)); // Fake name enabled. - - return 0; + clif->charnameack(0, &sd->bl); + clif->message(sd->fd, msg_txt(1310)); // Fake name enabled. + + return true; } /*========================================== * Ragnarok Resources *------------------------------------------*/ -ACMD_FUNC(mapflag) { -#define checkflag( cmd ) if ( map[ sd->bl.m ].flag.cmd ) clif_displaymessage(sd->fd,#cmd) +ACMD(mapflag) { +#define checkflag( cmd ) if ( map[ sd->bl.m ].flag.cmd ) clif->message(sd->fd,#cmd) #define setflag( cmd ) \ - if ( strcmp( flag_name , #cmd ) == 0 ){\ - map[ sd->bl.m ].flag.cmd = flag;\ - sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s value = %hd",#cmd,flag?"On":"Off",flag);\ - clif_displaymessage(sd->fd,atcmd_output);\ - return 0;\ - } - char flag_name[100]; +if ( strcmp( flag_name , #cmd ) == 0 ){\ +map[ sd->bl.m ].flag.cmd = flag;\ +sprintf(atcmd_output,"[ @mapflag ] %s flag has been set to %s value = %hd",#cmd,flag?"On":"Off",flag);\ +clif->message(sd->fd,atcmd_output);\ +return true;\ +} + char flag_name[100]; short flag=0,i; nullpo_retr(-1, sd); memset(flag_name, '\0', sizeof(flag_name)); - + if (!message || !*message || (sscanf(message, "%99s %hd", flag_name, &flag) < 1)) { - clif_displaymessage(sd->fd,msg_txt(1311)); // Enabled Mapflags in this map: - clif_displaymessage(sd->fd,"----------------------------------"); + clif->message(sd->fd,msg_txt(1311)); // Enabled Mapflags in this map: + clif->message(sd->fd,"----------------------------------"); checkflag(autotrade); checkflag(allowks); checkflag(nomemo); checkflag(noteleport); checkflag(noreturn); checkflag(monster_noteleport); checkflag(nosave); checkflag(nobranch); checkflag(noexppenalty); checkflag(pvp); checkflag(pvp_noparty); checkflag(pvp_noguild); @@ -7611,17 +7586,34 @@ ACMD_FUNC(mapflag) { checkflag(notrade); checkflag(noskill); checkflag(nowarp); checkflag(nowarpto); checkflag(noicewall); checkflag(snow); checkflag(clouds); checkflag(clouds2); checkflag(fog); checkflag(fireworks); checkflag(sakura); checkflag(leaves); - checkflag(nogo); checkflag(nobaseexp); + checkflag(nobaseexp); checkflag(nojobexp); checkflag(nomobloot); checkflag(nomvploot); checkflag(nightenabled); - checkflag(restricted); checkflag(nodrop); checkflag(novending); checkflag(loadevent); + checkflag(nodrop); checkflag(novending); checkflag(loadevent); checkflag(nochat); checkflag(partylock); checkflag(guildlock); checkflag(src4instance); - clif_displaymessage(sd->fd," "); - clif_displaymessage(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) - clif_displaymessage(sd->fd,msg_txt(1313)); // Type "@mapflag available" to list the available mapflags. + clif->message(sd->fd," "); + clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) + clif->message(sd->fd,msg_txt(1313)); // Type "@mapflag available" to list the available mapflags. return 1; } for (i = 0; flag_name[i]; i++) flag_name[i] = (char)tolower(flag_name[i]); //lowercase - + + if ( strcmp( flag_name , "gvg" ) == 0 ) { + if( flag && !map[sd->bl.m].flag.gvg ) + map_zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_GVG_NAME)); + else if ( !flag && map[sd->bl.m].flag.gvg ) + map_zone_change2(sd->bl.m,map[sd->bl.m].prev_zone); + } else if ( strcmp( flag_name , "pvp" ) == 0 ) { + if( flag && !map[sd->bl.m].flag.pvp ) + map_zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_PVP_NAME)); + else if ( !flag && map[sd->bl.m].flag.pvp ) + map_zone_change2(sd->bl.m,map[sd->bl.m].prev_zone); + } else if ( strcmp( flag_name , "battleground" ) == 0 ) { + if( flag && !map[sd->bl.m].flag.battleground ) + map_zone_change2(sd->bl.m,strdb_get(zone_db, MAP_ZONE_BG_NAME)); + else if ( !flag && map[sd->bl.m].flag.battleground ) + map_zone_change2(sd->bl.m,map[sd->bl.m].prev_zone); + } + setflag(autotrade); setflag(allowks); setflag(nomemo); setflag(noteleport); setflag(noreturn); setflag(monster_noteleport);setflag(nosave); setflag(nobranch); setflag(noexppenalty); setflag(pvp); setflag(pvp_noparty); setflag(pvp_noguild); @@ -7630,69 +7622,69 @@ ACMD_FUNC(mapflag) { setflag(notrade); setflag(noskill); setflag(nowarp); setflag(nowarpto); setflag(noicewall); setflag(snow); setflag(clouds); setflag(clouds2); setflag(fog); setflag(fireworks); setflag(sakura); setflag(leaves); - setflag(nogo); setflag(nobaseexp); + setflag(nobaseexp); setflag(nojobexp); setflag(nomobloot); setflag(nomvploot); setflag(nightenabled); - setflag(restricted); setflag(nodrop); setflag(novending); setflag(loadevent); + setflag(nodrop); setflag(novending); setflag(loadevent); setflag(nochat); setflag(partylock); setflag(guildlock); setflag(src4instance); - - clif_displaymessage(sd->fd,msg_txt(1314)); // Invalid flag name or flag. - clif_displaymessage(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) - clif_displaymessage(sd->fd,msg_txt(1315)); // Available Flags: - clif_displaymessage(sd->fd,"----------------------------------"); - clif_displaymessage(sd->fd,"town, autotrade, allowks, nomemo, noteleport, noreturn, monster_noteleport, nosave,"); - clif_displaymessage(sd->fd,"nobranch, noexppenalty, pvp, pvp_noparty, pvp_noguild, pvp_nightmaredrop,"); - clif_displaymessage(sd->fd,"pvp_nocalcrank, gvg_castle, gvg, gvg_dungeon, gvg_noparty, battleground,"); - clif_displaymessage(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,"); - clif_displaymessage(sd->fd,"fog, fireworks, sakura, leaves, nogo, nobaseexp, nojobexp, nomobloot,"); - clif_displaymessage(sd->fd,"nomvploot, nightenabled, restricted, nodrop, novending, loadevent, nochat, partylock,"); - clif_displaymessage(sd->fd,"guildlock, src4instance"); - + + clif->message(sd->fd,msg_txt(1314)); // Invalid flag name or flag. + clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On) + clif->message(sd->fd,msg_txt(1315)); // Available Flags: + clif->message(sd->fd,"----------------------------------"); + clif->message(sd->fd,"town, autotrade, allowks, nomemo, noteleport, noreturn, monster_noteleport, nosave,"); + clif->message(sd->fd,"nobranch, noexppenalty, pvp, pvp_noparty, pvp_noguild, pvp_nightmaredrop,"); + clif->message(sd->fd,"pvp_nocalcrank, gvg_castle, gvg, gvg_dungeon, gvg_noparty, battleground,"); + clif->message(sd->fd,"nozenypenalty, notrade, noskill, nowarp, nowarpto, noicewall, snow, clouds, clouds2,"); + clif->message(sd->fd,"fog, fireworks, sakura, leaves, nobaseexp, nojobexp, nomobloot,"); + clif->message(sd->fd,"nomvploot, nightenabled, nodrop, novending, loadevent, nochat, partylock,"); + clif->message(sd->fd,"guildlock, src4instance"); + #undef checkflag #undef setflag - - return 0; + + return true; } /*=================================== * Remove some messages *-----------------------------------*/ -ACMD_FUNC(showexp) +ACMD(showexp) { if (sd->state.showexp) { sd->state.showexp = 0; - clif_displaymessage(fd, msg_txt(1316)); // Gained exp will not be shown. - return 0; + clif->message(fd, msg_txt(1316)); // Gained exp will not be shown. + return true; } - + sd->state.showexp = 1; - clif_displaymessage(fd, msg_txt(1317)); // Gained exp is now shown. - return 0; + clif->message(fd, msg_txt(1317)); // Gained exp is now shown. + return true; } -ACMD_FUNC(showzeny) +ACMD(showzeny) { if (sd->state.showzeny) { sd->state.showzeny = 0; - clif_displaymessage(fd, msg_txt(1318)); // Gained zeny will not be shown. - return 0; + clif->message(fd, msg_txt(1318)); // Gained zeny will not be shown. + return true; } - + sd->state.showzeny = 1; - clif_displaymessage(fd, msg_txt(1319)); // Gained zeny is now shown. - return 0; + clif->message(fd, msg_txt(1319)); // Gained zeny is now shown. + return true; } -ACMD_FUNC(showdelay) +ACMD(showdelay) { if (sd->state.showdelay) { sd->state.showdelay = 0; - clif_displaymessage(fd, msg_txt(1320)); // Skill delay failures will not be shown. - return 0; + clif->message(fd, msg_txt(1320)); // Skill delay failures will not be shown. + return true; } - + sd->state.showdelay = 1; - clif_displaymessage(fd, msg_txt(1321)); // Skill delay failures are now shown. - return 0; + clif->message(fd, msg_txt(1321)); // Skill delay failures are now shown. + return true; } /*========================================== @@ -7704,191 +7696,191 @@ ACMD_FUNC(showdelay) * @reject - reject invitation * @leave - leave duel *------------------------------------------*/ -ACMD_FUNC(invite) +ACMD(invite) { unsigned int did = sd->duel_group; struct map_session_data *target_sd = map_nick2sd((char *)message); - - if(did <= 0) { + + if(did == 0) { // "Duel: @invite without @duel." - clif_displaymessage(fd, msg_txt(350)); - return 0; + clif->message(fd, msg_txt(350)); + return true; } - + if(duel_list[did].max_players_limit > 0 && - duel_list[did].members_count >= duel_list[did].max_players_limit) { - + duel_list[did].members_count >= duel_list[did].max_players_limit) { + // "Duel: Limit of players is reached." - clif_displaymessage(fd, msg_txt(351)); - return 0; + clif->message(fd, msg_txt(351)); + return true; } - + if(target_sd == NULL) { // "Duel: Player not found." - clif_displaymessage(fd, msg_txt(352)); - return 0; + clif->message(fd, msg_txt(352)); + return true; } - + if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) { // "Duel: Player already in duel." - clif_displaymessage(fd, msg_txt(353)); - return 0; + clif->message(fd, msg_txt(353)); + return true; } - + if(battle_config.duel_only_on_same_map && target_sd->bl.m != sd->bl.m) { sprintf(atcmd_output, msg_txt(364), message); - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } - + duel_invite(did, sd, target_sd); // "Duel: Invitation has been sent." - clif_displaymessage(fd, msg_txt(354)); - return 0; + clif->message(fd, msg_txt(354)); + return true; } -ACMD_FUNC(duel) +ACMD(duel) { - char output[CHAT_SIZE_MAX]; - unsigned int maxpl=0, newduel; - struct map_session_data *target_sd; - + unsigned int maxpl = 0; + if(sd->duel_group > 0) { duel_showinfo(sd->duel_group, sd); - return 0; + return true; } - + if(sd->duel_invite > 0) { // "Duel: @duel without @reject." - clif_displaymessage(fd, msg_txt(355)); - return 0; + clif->message(fd, msg_txt(355)); + return true; } - + if(!duel_checktime(sd)) { + char output[CHAT_SIZE_MAX]; // "Duel: You can take part in duel only one time per %d minutes." sprintf(output, msg_txt(356), battle_config.duel_time_interval); - clif_displaymessage(fd, output); - return 0; + clif->message(fd, output); + return true; } - + if( message[0] ) { if(sscanf(message, "%d", &maxpl) >= 1) { if(maxpl < 2 || maxpl > 65535) { - clif_displaymessage(fd, msg_txt(357)); // "Duel: Invalid value." - return 0; + clif->message(fd, msg_txt(357)); // "Duel: Invalid value." + return true; } duel_create(sd, maxpl); } else { + struct map_session_data *target_sd; target_sd = map_nick2sd((char *)message); if(target_sd != NULL) { + unsigned int newduel; if((newduel = duel_create(sd, 2)) != -1) { if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) { - clif_displaymessage(fd, msg_txt(353)); // "Duel: Player already in duel." - return 0; + clif->message(fd, msg_txt(353)); // "Duel: Player already in duel." + return true; } duel_invite(newduel, sd, target_sd); - clif_displaymessage(fd, msg_txt(354)); // "Duel: Invitation has been sent." + clif->message(fd, msg_txt(354)); // "Duel: Invitation has been sent." } } else { // "Duel: Player not found." - clif_displaymessage(fd, msg_txt(352)); - return 0; + clif->message(fd, msg_txt(352)); + return true; } } } else duel_create(sd, 0); - - return 0; + + return true; } -ACMD_FUNC(leave) +ACMD(leave) { if(sd->duel_group <= 0) { // "Duel: @leave without @duel." - clif_displaymessage(fd, msg_txt(358)); - return 0; + clif->message(fd, msg_txt(358)); + return true; } - + duel_leave(sd->duel_group, sd); - clif_displaymessage(fd, msg_txt(359)); // "Duel: You left the duel." - return 0; + clif->message(fd, msg_txt(359)); // "Duel: You left the duel." + return true; } -ACMD_FUNC(accept) +ACMD(accept) { - char output[CHAT_SIZE_MAX]; - if(!duel_checktime(sd)) { + char output[CHAT_SIZE_MAX]; // "Duel: You can take part in duel only one time per %d minutes." sprintf(output, msg_txt(356), battle_config.duel_time_interval); - clif_displaymessage(fd, output); - return 0; + clif->message(fd, output); + return true; } - + if(sd->duel_invite <= 0) { // "Duel: @accept without invititation." - clif_displaymessage(fd, msg_txt(360)); - return 0; + clif->message(fd, msg_txt(360)); + return true; } - + if( duel_list[sd->duel_invite].max_players_limit > 0 && duel_list[sd->duel_invite].members_count >= duel_list[sd->duel_invite].max_players_limit ) { // "Duel: Limit of players is reached." - clif_displaymessage(fd, msg_txt(351)); - return 0; + clif->message(fd, msg_txt(351)); + return true; } - + duel_accept(sd->duel_invite, sd); // "Duel: Invitation has been accepted." - clif_displaymessage(fd, msg_txt(361)); - return 0; + clif->message(fd, msg_txt(361)); + return true; } -ACMD_FUNC(reject) +ACMD(reject) { if(sd->duel_invite <= 0) { // "Duel: @reject without invititation." - clif_displaymessage(fd, msg_txt(362)); - return 0; + clif->message(fd, msg_txt(362)); + return true; } - + duel_reject(sd->duel_invite, sd); // "Duel: Invitation has been rejected." - clif_displaymessage(fd, msg_txt(363)); - return 0; + clif->message(fd, msg_txt(363)); + return true; } /*=================================== * Cash Points *-----------------------------------*/ -ACMD_FUNC(cash) +ACMD(cash) { char output[128]; int value; int ret=0; nullpo_retr(-1, sd); - + if( !message || !*message || (value = atoi(message)) == 0 ) { - clif_displaymessage(fd, msg_txt(1322)); // Please enter an amount. - return -1; + clif->message(fd, msg_txt(1322)); // Please enter an amount. + return false; } - + if( !strcmpi(command+1,"cash") ) { if( value > 0 ) { if( (ret=pc_getcash(sd, value, 0)) >= 0){ sprintf(output, msg_txt(505), ret, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } - else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value. + else clif->message(fd, msg_txt(149)); // Unable to decrease the number/value. } else { if( (ret=pc_paycash(sd, -value, 0)) >= 0){ sprintf(output, msg_txt(410), ret, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } - else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + else clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. } } else @@ -7896,254 +7888,202 @@ ACMD_FUNC(cash) if( value > 0 ) { if( (ret=pc_getcash(sd, 0, value)) >= 0){ sprintf(output, msg_txt(506), ret, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } - else clif_displaymessage(fd, msg_txt(149)); // Unable to decrease the number/value. + else clif->message(fd, msg_txt(149)); // Unable to decrease the number/value. } else { if( (ret=pc_paycash(sd, -value, -value)) >= 0){ sprintf(output, msg_txt(411), ret, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } - else clif_displaymessage(fd, msg_txt(41)); // Unable to decrease the number/value. + else clif->message(fd, msg_txt(41)); // Unable to decrease the number/value. } } - - return 0; + + return true; } // @clone/@slaveclone/@evilclone <playername> [Valaris] -ACMD_FUNC(clone) +ACMD(clone) { int x=0,y=0,flag=0,master=0,i=0; struct map_session_data *pl_sd=NULL; - + if (!message || !*message) { - clif_displaymessage(sd->fd,msg_txt(1323)); // You must enter a player name or ID. - return 0; + clif->message(sd->fd,msg_txt(1323)); // You must enter a player name or ID. + return true; } - + if((pl_sd=map_nick2sd((char *)message)) == NULL && (pl_sd=map_charid2sd(atoi(message))) == NULL) { - clif_displaymessage(fd, msg_txt(3)); // Character not found. - return 0; + clif->message(fd, msg_txt(3)); // Character not found. + return true; } - + if(pc_get_group_level(pl_sd) > pc_get_group_level(sd)) { - clif_displaymessage(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself. - return 0; + clif->message(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself. + return true; } - + if (strcmpi(command+1, "clone") == 0) flag = 1; else if (strcmpi(command+1, "slaveclone") == 0) { flag = 2; if(pc_isdead(sd)){ - clif_displaymessage(fd, msg_txt(129+flag*2)); - return 0; + clif->message(fd, msg_txt(129+flag*2)); + return true; } master = sd->bl.id; if (battle_config.atc_slave_clone_limit && mob_countslave(&sd->bl) >= battle_config.atc_slave_clone_limit) { - clif_displaymessage(fd, msg_txt(127)); // You've reached your slave clones limit. - return 0; + clif->message(fd, msg_txt(127)); // You've reached your slave clones limit. + return true; } } - + do { x = sd->bl.x + (rnd() % 10 - 5); y = sd->bl.y + (rnd() % 10 - 5); } while (map_getcell(sd->bl.m,x,y,CELL_CHKNOPASS) && i++ < 10); - + if (i >= 10) { x = sd->bl.x; y = sd->bl.y; } - + if((x = mob_clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) { - clif_displaymessage(fd, msg_txt(128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned. - return 0; - } - clif_displaymessage(fd, msg_txt(129+flag*2)); // Unable to spawn evil clone. Unable to spawn clone. Unable to spawn slave clone. - return 0; -} - -/*=================================== - * Main chat [LuzZza] - * Usage: @main <on|off|message> - *-----------------------------------*/ -ACMD_FUNC(main) -{ - if( message[0] ) { - - if(strcmpi(message, "on") == 0) { - if(!sd->state.mainchat) { - sd->state.mainchat = 1; - clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated. - } else { - clif_displaymessage(fd, msg_txt(381)); // Main chat already activated. - } - } else if(strcmpi(message, "off") == 0) { - if(sd->state.mainchat) { - sd->state.mainchat = 0; - clif_displaymessage(fd, msg_txt(382)); // Main chat has been disabled. - } else { - clif_displaymessage(fd, msg_txt(383)); // Main chat already disabled. - } - } else { - if(!sd->state.mainchat) { - sd->state.mainchat = 1; - clif_displaymessage(fd, msg_txt(380)); // Main chat has been activated. - } - if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) { - clif_displaymessage(fd, msg_txt(387)); - return -1; - } - - if ( battle_config.min_chat_delay ) { - if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) - return 0; - sd->cantalk_tick = gettick() + battle_config.min_chat_delay; - } - - // send the message using inter-server system - intif_main_message( sd, message ); - } - - } else { - - if(sd->state.mainchat) - clif_displaymessage(fd, msg_txt(384)); // Main chat currently enabled. Usage: @main <on|off>, @main <message>. - else - clif_displaymessage(fd, msg_txt(385)); // Main chat currently disabled. Usage: @main <on|off>, @main <message>. + clif->message(fd, msg_txt(128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned. + return true; } - return 0; + clif->message(fd, msg_txt(129+flag*2)); // Unable to spawn evil clone. Unable to spawn clone. Unable to spawn slave clone. + return true; } /*===================================== * Autorejecting Invites/Deals [LuzZza] * Usage: @noask *-------------------------------------*/ -ACMD_FUNC(noask) +ACMD(noask) { if(sd->state.noask) { - clif_displaymessage(fd, msg_txt(391)); // Autorejecting is deactivated. + clif->message(fd, msg_txt(391)); // Autorejecting is deactivated. sd->state.noask = 0; } else { - clif_displaymessage(fd, msg_txt(390)); // Autorejecting is activated. + clif->message(fd, msg_txt(390)); // Autorejecting is activated. sd->state.noask = 1; } - - return 0; + + return true; } /*===================================== * Send a @request message to all GMs of lowest_gm_level. * Usage: @request <petition> *-------------------------------------*/ -ACMD_FUNC(request) +ACMD(request) { if (!message || !*message) { - clif_displaymessage(sd->fd,msg_txt(277)); // Usage: @request <petition/message to online GMs>. - return -1; + clif->message(sd->fd,msg_txt(277)); // Usage: @request <petition/message to online GMs>. + return false; } - + sprintf(atcmd_output, msg_txt(278), message); // (@request): %s intif_wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output); - clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output)); - clif_displaymessage(sd->fd,msg_txt(279)); // @request sent. - return 0; + clif->disp_onlyself(sd, atcmd_output, strlen(atcmd_output)); + clif->message(sd->fd,msg_txt(279)); // @request sent. + return true; } /*========================================== * Feel (SG save map) Reset [HiddenDragon] *------------------------------------------*/ -ACMD_FUNC(feelreset) +ACMD(feelreset) { pc_resetfeel(sd); - clif_displaymessage(fd, msg_txt(1324)); // Reset 'Feeling' maps. - - return 0; + clif->message(fd, msg_txt(1324)); // Reset 'Feeling' maps. + + return true; } /*========================================== * AUCTION SYSTEM *------------------------------------------*/ -ACMD_FUNC(auction) +ACMD(auction) { nullpo_ret(sd); - - clif_Auction_openwindow(sd); - - return 0; + + clif->auction_openwindow(sd); + + return true; } /*========================================== * Kill Steal Protection *------------------------------------------*/ -ACMD_FUNC(ksprotection) +ACMD(ksprotection) { nullpo_retr(-1,sd); - + if( sd->state.noks ) { sd->state.noks = 0; - clif_displaymessage(fd, msg_txt(1325)); // [ K.S Protection Inactive ] + clif->message(fd, msg_txt(1325)); // [ K.S Protection Inactive ] } else { if( !message || !*message || !strcmpi(message, "party") ) { // Default is Party sd->state.noks = 2; - clif_displaymessage(fd, msg_txt(1326)); // [ K.S Protection Active - Option: Party ] + clif->message(fd, msg_txt(1326)); // [ K.S Protection Active - Option: Party ] } else if( !strcmpi(message, "self") ) { sd->state.noks = 1; - clif_displaymessage(fd, msg_txt(1327)); // [ K.S Protection Active - Option: Self ] + clif->message(fd, msg_txt(1327)); // [ K.S Protection Active - Option: Self ] } else if( !strcmpi(message, "guild") ) { sd->state.noks = 3; - clif_displaymessage(fd, msg_txt(1328)); // [ K.S Protection Active - Option: Guild ] + clif->message(fd, msg_txt(1328)); // [ K.S Protection Active - Option: Guild ] } else - clif_displaymessage(fd, msg_txt(1329)); // Usage: @noks <self|party|guild> + clif->message(fd, msg_txt(1329)); // Usage: @noks <self|party|guild> } - return 0; + return true; } /*========================================== * Map Kill Steal Protection Setting *------------------------------------------*/ -ACMD_FUNC(allowks) +ACMD(allowks) { nullpo_retr(-1,sd); - + if( map[sd->bl.m].flag.allowks ) { map[sd->bl.m].flag.allowks = 0; - clif_displaymessage(fd, msg_txt(1330)); // [ Map K.S Protection Active ] + clif->message(fd, msg_txt(1330)); // [ Map K.S Protection Active ] } else { map[sd->bl.m].flag.allowks = 1; - clif_displaymessage(fd, msg_txt(1331)); // [ Map K.S Protection Inactive ] + clif->message(fd, msg_txt(1331)); // [ Map K.S Protection Inactive ] } - return 0; + return true; } -ACMD_FUNC(resetstat) +ACMD(resetstat) { nullpo_retr(-1, sd); - + pc_resetstate(sd); sprintf(atcmd_output, msg_txt(207), sd->status.name); - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } -ACMD_FUNC(resetskill) +ACMD(resetskill) { nullpo_retr(-1,sd); - + pc_resetskill(sd,1); sprintf(atcmd_output, msg_txt(206), sd->status.name); - clif_displaymessage(fd, atcmd_output); - return 0; + clif->message(fd, atcmd_output); + return true; } /*========================================== @@ -8151,16 +8091,16 @@ ACMD_FUNC(resetskill) * #cartlist: Displays contents of target's cart. * #itemlist: Displays contents of target's inventory. *------------------------------------------*/ -ACMD_FUNC(itemlist) +ACMD(itemlist) { int i, j, count, counter; const char* location; const struct item* items; int size; StringBuf buf; - + nullpo_retr(-1, sd); - + if( strcmp(command+1, "storagelist") == 0 ) { location = "storage"; @@ -8168,49 +8108,49 @@ ACMD_FUNC(itemlist) size = MAX_STORAGE; } else - if( strcmp(command+1, "cartlist") == 0 ) - { - location = "cart"; - items = sd->status.cart; - size = MAX_CART; - } - else - if( strcmp(command+1, "itemlist") == 0 ) - { - location = "inventory"; - items = sd->status.inventory; - size = MAX_INVENTORY; - } - else - return 1; - - StringBuf_Init(&buf); - + if( strcmp(command+1, "cartlist") == 0 ) + { + location = "cart"; + items = sd->status.cart; + size = MAX_CART; + } + else + if( strcmp(command+1, "itemlist") == 0 ) + { + location = "inventory"; + items = sd->status.inventory; + size = MAX_INVENTORY; + } + else + return 1; + + StrBuf->Init(&buf); + count = 0; // total slots occupied counter = 0; // total items found for( i = 0; i < size; ++i ) { const struct item* it = &items[i]; struct item_data* itd; - + if( it->nameid == 0 || (itd = itemdb_exists(it->nameid)) == NULL ) continue; - + counter += it->amount; count++; - + if( count == 1 ) { - StringBuf_Printf(&buf, msg_txt(1332), location, sd->status.name); // ------ %s items list of '%s' ------ - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Clear(&buf); + StrBuf->Printf(&buf, msg_txt(1332), location, sd->status.name); // ------ %s items list of '%s' ------ + clif->message(fd, StrBuf->Value(&buf)); + StrBuf->Clear(&buf); } - + if( it->refine ) - StringBuf_Printf(&buf, "%d %s %+d (%s, id: %d)", it->amount, itd->jname, it->refine, itd->name, it->nameid); + StrBuf->Printf(&buf, "%d %s %+d (%s, id: %d)", it->amount, itd->jname, it->refine, itd->name, it->nameid); else - StringBuf_Printf(&buf, "%d %s (%s, id: %d)", it->amount, itd->jname, itd->name, it->nameid); - + StrBuf->Printf(&buf, "%d %s (%s, id: %d)", it->amount, itd->jname, itd->name, it->nameid); + if( it->equip ) { char equipstr[CHAT_SIZE_MAX]; @@ -8245,74 +8185,74 @@ ACMD_FUNC(itemlist) strcat(equipstr, msg_txt(1347)); // lower/mid/top head, // remove final ', ' equipstr[strlen(equipstr) - 2] = '\0'; - StringBuf_AppendStr(&buf, equipstr); + StrBuf->AppendStr(&buf, equipstr); } - - clif_displaymessage(fd, StringBuf_Value(&buf)); - StringBuf_Clear(&buf); - + + clif->message(fd, StrBuf->Value(&buf)); + StrBuf->Clear(&buf); + if( it->card[0] == CARD0_PET ) {// pet egg if (it->card[3]) - StringBuf_Printf(&buf, msg_txt(1348), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, named) + StrBuf->Printf(&buf, msg_txt(1348), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, named) else - StringBuf_Printf(&buf, msg_txt(1349), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, unnamed) - } - else - if(it->card[0] == CARD0_FORGE) - {// forged item - StringBuf_Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d) + StrBuf->Printf(&buf, msg_txt(1349), (unsigned int)MakeDWord(it->card[1], it->card[2])); // -> (pet egg, pet id: %u, unnamed) } else - if(it->card[0] == CARD0_CREATE) - {// created item - StringBuf_Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u) - } - else - {// normal item - int counter2 = 0; - - for( j = 0; j < itd->slot; ++j ) - { - struct item_data* card; - - if( it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL ) - continue; - - counter2++; - - if( counter2 == 1 ) - StringBuf_AppendStr(&buf, msg_txt(1352)); // -> (card(s): - - if( counter2 != 1 ) - StringBuf_AppendStr(&buf, ", "); - - StringBuf_Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid); + if(it->card[0] == CARD0_FORGE) + {// forged item + StrBuf->Printf(&buf, msg_txt(1350), (unsigned int)MakeDWord(it->card[2], it->card[3]), it->card[1]>>8, it->card[1]&0x0f); // -> (crafted item, creator id: %u, star crumbs %d, element %d) } - - if( counter2 > 0 ) - StringBuf_AppendStr(&buf, ")"); - } - - if( StringBuf_Length(&buf) > 0 ) - clif_displaymessage(fd, StringBuf_Value(&buf)); - - StringBuf_Clear(&buf); + else + if(it->card[0] == CARD0_CREATE) + {// created item + StrBuf->Printf(&buf, msg_txt(1351), (unsigned int)MakeDWord(it->card[2], it->card[3])); // -> (produced item, creator id: %u) + } + else + {// normal item + int counter2 = 0; + + for( j = 0; j < itd->slot; ++j ) + { + struct item_data* card; + + if( it->card[j] == 0 || (card = itemdb_exists(it->card[j])) == NULL ) + continue; + + counter2++; + + if( counter2 == 1 ) + StrBuf->AppendStr(&buf, msg_txt(1352)); // -> (card(s): + + if( counter2 != 1 ) + StrBuf->AppendStr(&buf, ", "); + + StrBuf->Printf(&buf, "#%d %s (id: %d)", counter2, card->jname, card->nameid); + } + + if( counter2 > 0 ) + StrBuf->AppendStr(&buf, ")"); + } + + if( StrBuf->Length(&buf) > 0 ) + clif->message(fd, StrBuf->Value(&buf)); + + StrBuf->Clear(&buf); } - + if( count == 0 ) - StringBuf_Printf(&buf, msg_txt(1353), location); // No item found in this player's %s. + StrBuf->Printf(&buf, msg_txt(1353), location); // No item found in this player's %s. else - StringBuf_Printf(&buf, msg_txt(1354), counter, count, location); // %d item(s) found in %d %s slots. - - clif_displaymessage(fd, StringBuf_Value(&buf)); - - StringBuf_Destroy(&buf); - - return 0; + StrBuf->Printf(&buf, msg_txt(1354), counter, count, location); // %d item(s) found in %d %s slots. + + clif->message(fd, StrBuf->Value(&buf)); + + StrBuf->Destroy(&buf); + + return true; } -ACMD_FUNC(stats) +ACMD(stats) { char job_jobname[100]; char output[CHAT_SIZE_MAX]; @@ -8339,10 +8279,10 @@ ACMD_FUNC(stats) { "JobChangeLvl (3rd) - %d", 0 }, { NULL, 0 } }; - + memset(job_jobname, '\0', sizeof(job_jobname)); memset(output, '\0', sizeof(output)); - + //direct array initialization with variables is not standard C compliant. output_table[0].value = sd->status.base_level; output_table[1].format = job_jobname; @@ -8361,118 +8301,118 @@ ACMD_FUNC(stats) output_table[13].value = sd->status.skill_point; output_table[14].value = sd->change_level_2nd; output_table[15].value = sd->change_level_3rd; - + sprintf(job_jobname, "Job - %s %s", job_name(sd->status.class_), "(level %d)"); sprintf(output, msg_txt(53), sd->status.name); // '%s' stats: - - clif_displaymessage(fd, output); - + + clif->message(fd, output); + for (i = 0; output_table[i].format != NULL; i++) { sprintf(output, output_table[i].format, output_table[i].value); - clif_displaymessage(fd, output); + clif->message(fd, output); } - - return 0; + + return true; } -ACMD_FUNC(delitem) +ACMD(delitem) { char item_name[100]; int nameid, amount = 0, total, idx; struct item_data* id; - + nullpo_retr(-1, sd); - + if( !message || !*message || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &amount) < 2 && sscanf(message, "%99s %d", item_name, &amount) < 2 ) || amount < 1 ) { - clif_displaymessage(fd, msg_txt(1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>). - return -1; + clif->message(fd, msg_txt(1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>). + return false; } - + if( ( id = itemdb_searchname(item_name) ) != NULL || ( id = itemdb_exists(atoi(item_name)) ) != NULL ) { nameid = id->nameid; } else { - clif_displaymessage(fd, msg_txt(19)); // Invalid item ID or name. - return -1; + clif->message(fd, msg_txt(19)); // Invalid item ID or name. + return false; } - + total = amount; - + // delete items while( amount && ( idx = pc_search_inventory(sd, nameid) ) != -1 ) { int delamount = ( amount < sd->status.inventory[idx].amount ) ? amount : sd->status.inventory[idx].amount; - + if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) {// delete pet intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); } pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND); - + amount-= delamount; } - + // notify target sprintf(atcmd_output, msg_txt(113), total-amount); // %d item(s) removed by a GM. - clif_displaymessage(sd->fd, atcmd_output); - + clif->message(sd->fd, atcmd_output); + // notify source if( amount == total ) { - clif_displaymessage(fd, msg_txt(116)); // Character does not have the item. + clif->message(fd, msg_txt(116)); // Character does not have the item. } else if( amount ) { sprintf(atcmd_output, msg_txt(115), total-amount, total-amount, total); // %d item(s) removed. Player had only %d on %d items. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } else { sprintf(atcmd_output, msg_txt(114), total); // %d item(s) removed from the player. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - - return 0; + + return true; } /*========================================== * Custom Fonts *------------------------------------------*/ -ACMD_FUNC(font) +ACMD(font) { int font_id; nullpo_retr(-1,sd); - + font_id = atoi(message); if( font_id == 0 ) { if( sd->user_font ) { sd->user_font = 0; - clif_displaymessage(fd, msg_txt(1356)); // Returning to normal font. - clif_font(sd); + clif->message(fd, msg_txt(1356)); // Returning to normal font. + clif->font(sd); } else { - clif_displaymessage(fd, msg_txt(1357)); // Use @font <1-9> to change your message font. - clif_displaymessage(fd, msg_txt(1358)); // Use 0 or no parameter to return to normal font. + clif->message(fd, msg_txt(1357)); // Use @font <1-9> to change your message font. + clif->message(fd, msg_txt(1358)); // Use 0 or no parameter to return to normal font. } } else if( font_id < 0 || font_id > 9 ) - clif_displaymessage(fd, msg_txt(1359)); // Invalid font. Use a value from 0 to 9. + clif->message(fd, msg_txt(1359)); // Invalid font. Use a value from 0 to 9. else if( font_id != sd->user_font ) { sd->user_font = font_id; - clif_font(sd); - clif_displaymessage(fd, msg_txt(1360)); // Font changed. + clif->font(sd); + clif->message(fd, msg_txt(1360)); // Font changed. } else - clif_displaymessage(fd, msg_txt(1361)); // Already using this font. - - return 0; + clif->message(fd, msg_txt(1361)); // Already using this font. + + return true; } /*========================================== @@ -8483,17 +8423,17 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At char line_buff[CHATBOX_SIZE]; char* cur = line_buff; AtCommandInfo* cmd; - DBIterator *iter = db_iterator(atcommand_db); + DBIterator *iter = db_iterator(atcommand->db); int count = 0; - + memset(line_buff,' ',CHATBOX_SIZE); line_buff[CHATBOX_SIZE-1] = 0; - - clif_displaymessage(fd, msg_txt(273)); // "Commands available:" - + + clif->message(fd, msg_txt(273)); // "Commands available:" + for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { unsigned int slen = 0; - + switch( type ) { case COMMAND_CHARCOMMAND: if( cmd->char_groups[sd->group_pos] == 0 ) @@ -8506,127 +8446,127 @@ static void atcommand_commands_sub(struct map_session_data* sd, const int fd, At default: continue; } - - + + slen = strlen(cmd->command); - + // flush the text buffer if this command won't fit into it if ( slen + cur - line_buff >= CHATBOX_SIZE ) { - clif_displaymessage(fd,line_buff); + clif->message(fd,line_buff); cur = line_buff; memset(line_buff,' ',CHATBOX_SIZE); line_buff[CHATBOX_SIZE-1] = 0; } - + memcpy(cur,cmd->command,slen); cur += slen+(10-slen%10); - + count++; } dbi_destroy(iter); - clif_displaymessage(fd,line_buff); - + clif->message(fd,line_buff); + sprintf(atcmd_output, msg_txt(274), count); // "%d commands found." - clif_displaymessage(fd, atcmd_output); - + clif->message(fd, atcmd_output); + return; } /*========================================== * @commands Lists available @ commands to you *------------------------------------------*/ -ACMD_FUNC(commands) +ACMD(commands) { atcommand_commands_sub(sd, fd, COMMAND_ATCOMMAND); - return 0; + return true; } /*========================================== * @charcommands Lists available # commands to you *------------------------------------------*/ -ACMD_FUNC(charcommands) +ACMD(charcommands) { atcommand_commands_sub(sd, fd, COMMAND_CHARCOMMAND); - return 0; + return true; } /* for new mounts */ -ACMD_FUNC(mount2) { - - clif_displaymessage(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated. - if( !(sd->sc.option&OPTION_MOUNTING) ) { - clif_displaymessage(sd->fd,msg_txt(1363)); // You have mounted. - pc_setoption(sd, sd->sc.option|OPTION_MOUNTING); +ACMD(mount2) { + + clif->message(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated. + if( !(sd->sc.data[SC_ALL_RIDING]) ) { + clif->message(sd->fd,msg_txt(1363)); // You have mounted. + sc_start(&sd->bl,SC_ALL_RIDING,100,0,-1); } else { - clif_displaymessage(sd->fd,msg_txt(1364)); // You have released your mount. - pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING); + clif->message(sd->fd,msg_txt(1364)); // You have released your mount. + status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER); } - return 0; + return true; } -ACMD_FUNC(accinfo) { +ACMD(accinfo) { char query[NAME_LENGTH]; - + if (!message || !*message || strlen(message) > NAME_LENGTH ) { - clif_displaymessage(fd, msg_txt(1365)); // Usage: @accinfo/@accountinfo <account_id/char name> - clif_displaymessage(fd, msg_txt(1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario". - return -1; + clif->message(fd, msg_txt(1365)); // Usage: @accinfo/@accountinfo <account_id/char name> + clif->message(fd, msg_txt(1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario". + return false; } - + //remove const type safestrncpy(query, message, NAME_LENGTH); - - intif_request_accinfo( sd->fd, sd->bl.id, sd->group_id, query ); - - return 0; + + intif_request_accinfo( sd->fd, sd->bl.id, pc_get_group_level(sd), query ); + + return true; } /* [Ind] */ -ACMD_FUNC(set) { +ACMD(set) { char reg[32], val[128]; struct script_data* data; int toset = 0, len; bool is_str = false; - - if( !message || !*message || (toset = sscanf(message, "%32s %128[^\n]s", reg, val)) < 1 ) { - clif_displaymessage(fd, msg_txt(1367)); // Usage: @set <variable name> <value> - clif_displaymessage(fd, msg_txt(1368)); // Usage: ex. "@set PoringCharVar 50" - clif_displaymessage(fd, msg_txt(1369)); // Usage: ex. "@set PoringCharVarSTR$ Super Duper String" - clif_displaymessage(fd, msg_txt(1370)); // Usage: ex. "@set PoringCharVarSTR$" outputs its value, Super Duper String. - return -1; + + if( !message || !*message || (toset = sscanf(message, "%31s %128[^\n]s", reg, val)) < 1 ) { + clif->message(fd, msg_txt(1367)); // Usage: @set <variable name> <value> + clif->message(fd, msg_txt(1368)); // Usage: ex. "@set PoringCharVar 50" + clif->message(fd, msg_txt(1369)); // Usage: ex. "@set PoringCharVarSTR$ Super Duper String" + clif->message(fd, msg_txt(1370)); // Usage: ex. "@set PoringCharVarSTR$" outputs its value, Super Duper String. + return false; } - + /* disabled variable types (they require a proper script state to function, so allowing them would crash the server) */ if( reg[0] == '.' ) { - clif_displaymessage(fd, msg_txt(1371)); // NPC variables may not be used with @set. - return -1; + clif->message(fd, msg_txt(1371)); // NPC variables may not be used with @set. + return false; } else if( reg[0] == '\'' ) { - clif_displaymessage(fd, msg_txt(1372)); // Instance variables may not be used with @set. - return -1; + clif->message(fd, msg_txt(1372)); // Instance variables may not be used with @set. + return false; } - + is_str = ( reg[strlen(reg) - 1] == '$' ) ? true : false; - + if( ( len = strlen(val) ) > 1 ) { if( val[0] == '"' && val[len-1] == '"') { val[len-1] = '\0'; //Strip quotes. memmove(val, val+1, len-1); } } - + if( toset >= 2 ) {/* we only set the var if there is an val, otherwise we only output the value */ if( is_str ) set_var(sd, reg, (void*) val); else - set_var(sd, reg, (void*)__64BPRTSIZE((atoi(val)))); - + set_var(sd, reg, (void*)__64BPTRSIZE((atoi(val)))); + } - + CREATE(data, struct script_data,1); - - + + if( is_str ) {// string variable - + switch( reg[0] ) { case '@': data->u.str = pc_readregstr(sd, add_str(reg)); @@ -8644,7 +8584,7 @@ ACMD_FUNC(set) { data->u.str = pc_readglobalreg_str(sd, reg); break; } - + if( data->u.str == NULL || data->u.str[0] == '\0' ) {// empty string data->type = C_CONSTSTR; data->u.str = ""; @@ -8652,9 +8592,9 @@ ACMD_FUNC(set) { data->type = C_STR; data->u.str = aStrdup(data->u.str); } - + } else {// integer variable - + data->type = C_INT; switch( reg[0] ) { case '@': @@ -8673,10 +8613,10 @@ ACMD_FUNC(set) { data->u.num = pc_readglobalreg(sd, reg); break; } - + } - - + + switch( data->type ) { case C_INT: sprintf(atcmd_output,msg_txt(1373),reg,data->u.num); // %s value is now :%d @@ -8691,138 +8631,826 @@ ACMD_FUNC(set) { sprintf(atcmd_output,msg_txt(1376),reg,data->type); // %s data type is not supported :%u break; } - - clif_displaymessage(fd, atcmd_output); - + + clif->message(fd, atcmd_output); + aFree(data); - - return 0; + + return true; } -ACMD_FUNC(reloadquestdb) { +ACMD(reloadquestdb) { do_reload_quest(); - clif_displaymessage(fd, msg_txt(1377)); // Quest database has been reloaded. - return 0; + clif->message(fd, msg_txt(1377)); // Quest database has been reloaded. + return true; } -ACMD_FUNC(addperm) { +ACMD(addperm) { int perm_size = ARRAYLENGTH(pc_g_permission_name); bool add = (strcmpi(command+1, "addperm") == 0) ? true : false; int i; - + if( !message || !*message ) { sprintf(atcmd_output, msg_txt(1378),command); // Usage: %s <permission_name> - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1379)); // -- Permission List + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1379)); // -- Permission List for( i = 0; i < perm_size; i++ ) { sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - return -1; + return false; } - + ARR_FIND(0, perm_size, i, strcmpi(pc_g_permission_name[i].name, message) == 0); - + if( i == perm_size ) { sprintf(atcmd_output,msg_txt(1380),message); // '%s' is not a known permission. - clif_displaymessage(fd, atcmd_output); - clif_displaymessage(fd, msg_txt(1379)); // -- Permission List + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1379)); // -- Permission List for( i = 0; i < perm_size; i++ ) { sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } - return -1; + return false; } - + if( add && (sd->permissions&pc_g_permission_name[i].permission) ) { sprintf(atcmd_output, msg_txt(1381),sd->status.name,pc_g_permission_name[i].name); // User '%s' already possesses the '%s' permission. - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } else if ( !add && !(sd->permissions&pc_g_permission_name[i].permission) ) { sprintf(atcmd_output, msg_txt(1382),sd->status.name,pc_g_permission_name[i].name); // User '%s' doesn't possess the '%s' permission. - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); sprintf(atcmd_output,msg_txt(1383),sd->status.name); // -- User '%s' Permissions - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); for( i = 0; i < perm_size; i++ ) { if( sd->permissions&pc_g_permission_name[i].permission ) { sprintf(atcmd_output,"- %s",pc_g_permission_name[i].name); - clif_displaymessage(fd, atcmd_output); + clif->message(fd, atcmd_output); } } - - return -1; + + return false; } - + if( add ) sd->permissions |= pc_g_permission_name[i].permission; else sd->permissions &=~ pc_g_permission_name[i].permission; - - + + sprintf(atcmd_output, msg_txt(1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary. - clif_displaymessage(fd, atcmd_output); - - return 0; + clif->message(fd, atcmd_output); + + return true; } -ACMD_FUNC(unloadnpcfile) { - +ACMD(unloadnpcfile) { + if( !message || !*message ) { - clif_displaymessage(fd, msg_txt(1385)); // Usage: @unloadnpcfile <file name> - return -1; + clif->message(fd, msg_txt(1385)); // Usage: @unloadnpcfile <file name> + return false; } - + if( npc_unloadfile(message) ) - clif_displaymessage(fd, msg_txt(1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. + clif->message(fd, msg_txt(1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed. else { - clif_displaymessage(fd, msg_txt(1387)); // File not found. - return -1; + clif->message(fd, msg_txt(1387)); // File not found. + return false; } - return 0; + return true; } -ACMD_FUNC(cart) { -#define MC_CART_MDFY(x) \ - sd->status.skill[MC_PUSHCART].id = x?MC_PUSHCART:0; \ - sd->status.skill[MC_PUSHCART].lv = x?1:0; \ - sd->status.skill[MC_PUSHCART].flag = x?1:0; - +ACMD(cart) { +#define MC_CART_MDFY(x,idx) \ +sd->status.skill[idx].id = x?MC_PUSHCART:0; \ +sd->status.skill[idx].lv = x?1:0; \ +sd->status.skill[idx].flag = x?1:0; + int val = atoi(message); bool need_skill = pc_checkskill(sd, MC_PUSHCART) ? false : true; - + unsigned int index = skill->get_index(MC_PUSHCART); + if( !message || !*message || val < 0 || val > MAX_CARTS ) { sprintf(atcmd_output, msg_txt(1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>). - clif_displaymessage(fd, atcmd_output); - return -1; + clif->message(fd, atcmd_output); + return false; } - + if( val == 0 && !pc_iscarton(sd) ) { - clif_displaymessage(fd, msg_txt(1391)); // You do not possess a cart to be removed - return -1; + clif->message(fd, msg_txt(1391)); // You do not possess a cart to be removed + return false; } - + if( need_skill ) { - MC_CART_MDFY(1); + MC_CART_MDFY(1,index); } - + if( pc_setcart(sd, val) ) { if( need_skill ) { - MC_CART_MDFY(0); + MC_CART_MDFY(0,index); } - return -1;/* @cart failed */ + return false;/* @cart failed */ } - + if( need_skill ) { - MC_CART_MDFY(0); + MC_CART_MDFY(0,index); } + + clif->message(fd, msg_txt(1392)); // Cart Added + + return true; +#undef MC_CART_MDFY +} +/* [Ind/Hercules] */ +ACMD(join) { + struct hChSysCh *channel; + char name[HCHSYS_NAME_LENGTH], pass[HCHSYS_NAME_LENGTH]; + + if( !message || !*message || sscanf(message, "%s %s", name, pass) < 1 ) { + sprintf(atcmd_output, msg_txt(1399),command); // Unknown Channel (usage: %s <#channel_name>) + clif->message(fd, atcmd_output); + return false; + } + if( hChSys.local && strcmpi(name + 1, hChSys.local_name) == 0 ) { + if( !map[sd->bl.m].channel ) { + clif->chsys_mjoin(sd); + return true; + } else + channel = map[sd->bl.m].channel; + } else if( hChSys.ally && sd->status.guild_id && strcmpi(name + 1, hChSys.ally_name) == 0 ) { + struct guild *g = sd->guild; + if( !g ) return false;/* unlikely, but we wont let it crash anyway. */ + channel = (struct hChSysCh *)g->channel; + } else if( !( channel = strdb_get(clif->channel_db, name + 1) ) ) { + sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>) + clif->message(fd, atcmd_output); + return false; + } + + if( idb_exists(channel->users, sd->status.char_id) ) { + sprintf(atcmd_output, msg_txt(1475),name); // You're already in the '%s' channel + clif->message(fd, atcmd_output); + return false; + } + if( channel->pass[0] != '\0' && strcmp(channel->pass,pass) != 0 ) { + if( pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + sd->stealth = true; + } else { + sprintf(atcmd_output, msg_txt(1401),name,command); // '%s' Channel is password protected (usage: %s <#channel_name> <password>) + clif->message(fd, atcmd_output); + return false; + } + } + + if( channel->banned && idb_exists(channel->banned, sd->status.account_id) ) { + sprintf(atcmd_output, msg_txt(1438),name); // You cannot join the '%s' channel because you've been banned from it + clif->message(fd, atcmd_output); + return false; + } + + if( !( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) { + sprintf(atcmd_output, msg_txt(1403),name); // You're now in the '%s' channel + clif->message(fd, atcmd_output); + } + if( channel->type == hChSys_ALLY ) { + struct guild *g = sd->guild, *sg = NULL; + int i; + for (i = 0; i < MAX_GUILDALLIANCE; i++) { + if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) { + if( !(((struct hChSysCh*)sg->channel)->banned && idb_exists(((struct hChSysCh*)sg->channel)->banned, sd->status.account_id))) { + clif->chsys_join((struct hChSysCh *)sg->channel,sd); + } + } + } + } + clif->chsys_join(channel,sd); + + return true; +} +/* [Ind/Hercules] */ +static inline void atcmd_channel_help(int fd, const char *command, bool can_create) { + sprintf(atcmd_output, msg_txt(1404),command); // %s failed. + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1414));// --- Available options: + if( can_create ) { + sprintf(atcmd_output, msg_txt(1415),command);// -- %s create <channel name> <channel password> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1416));// - creates a new channel + } + sprintf(atcmd_output, msg_txt(1417),command);// -- %s list + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1418));// - lists public channels + if( can_create ) { + sprintf(atcmd_output, msg_txt(1419),command);// -- %s list colors + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1420));// - lists colors available to select for custom channels + sprintf(atcmd_output, msg_txt(1421),command);// -- %s setcolor <channel name> <color name> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1422));// - changes <channel name> color to <color name> + } + sprintf(atcmd_output, msg_txt(1423),command);// -- %s leave <channel name> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1424));// - leaves <channel name> + sprintf(atcmd_output, msg_txt(1427),command);// -- %s bindto <channel name> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1428));// - binds global chat to <channel name>, making anything you type in global be sent to the channel + sprintf(atcmd_output, msg_txt(1429),command);// -- %s unbind + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1430));// - unbinds your global chat from its attached channel (if binded) + sprintf(atcmd_output, msg_txt(1429),command);// -- %s unbind + clif->message(fd, atcmd_output); + if( can_create ) { + sprintf(atcmd_output, msg_txt(1456),command);// -- %s ban <channel name> <character name> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1457));// - bans <character name> from <channel name> channel + sprintf(atcmd_output, msg_txt(1458),command);// -- %s banlist <channel name> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1459));// - lists all banned characters from <channel name> channel + sprintf(atcmd_output, msg_txt(1460),command);// -- %s unban <channel name> <character name> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1461));// - unbans <character name> from <channel name> channel + sprintf(atcmd_output, msg_txt(1467),command);// -- %s unbanall <channel name> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1468));// - unbans everyone from <channel name> + sprintf(atcmd_output, msg_txt(1462),command);// -- %s setopt <channel name> <option name> <option value> + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1463));// - adds or removes <option name> with <option value> to <channel name> channel + } + +} +/* [Ind/Hercules] */ +ACMD(channel) { + struct hChSysCh *channel; + char key[HCHSYS_NAME_LENGTH], sub1[HCHSYS_NAME_LENGTH], sub2[HCHSYS_NAME_LENGTH], sub3[HCHSYS_NAME_LENGTH]; + unsigned char k = 0; + sub1[0] = sub2[0] = sub3[0] = '\0'; + + if( !message || !*message || sscanf(message, "%s %s %s %s", key, sub1, sub2, sub3) < 1 ) { + atcmd_channel_help(fd,command,( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) )); + return true; + } + + if( strcmpi(key,"create") == 0 && ( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) ) { + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } else if ( strlen(sub1) < 3 || strlen(sub1) > HCHSYS_NAME_LENGTH ) { + sprintf(atcmd_output, msg_txt(1406), HCHSYS_NAME_LENGTH);// Channel length must be between 3 and %d + clif->message(fd, atcmd_output); + return false; + } else if ( sub3[0] != '\0' ) { + clif->message(fd, msg_txt(1408)); // Channel password may not contain spaces + return false; + } + if( strcmpi(sub1 + 1,hChSys.local_name) == 0 || strcmpi(sub1 + 1,hChSys.ally_name) == 0 || strdb_exists(clif->channel_db, sub1 + 1) ) { + sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available + clif->message(fd, atcmd_output); + return false; + } + + CREATE( channel, struct hChSysCh, 1 ); + + clif->chsys_create(channel,sub1 + 1,sub2,0); + + channel->owner = sd->status.char_id; + channel->type = hChSys_PRIVATE; + + if( !( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) { + sprintf(atcmd_output, msg_txt(1403),sub1); // You're now in the '%s' channel + clif->message(fd, atcmd_output); + } + + clif->chsys_join(channel,sd); + + } else if ( strcmpi(key,"list") == 0 ) { + if( sub1[0] != '\0' && strcmpi(sub1,"colors") == 0 ) { + char mout[40]; + for( k = 0; k < hChSys.colors_count; k++ ) { + unsigned short msg_len = 1; + msg_len += sprintf(mout, "[ %s list colors ] : %s",command,hChSys.colors_name[k]); + + WFIFOHEAD(fd,msg_len + 12); + WFIFOW(fd,0) = 0x2C1; + WFIFOW(fd,2) = msg_len + 12; + WFIFOL(fd,4) = 0; + WFIFOL(fd,8) = hChSys.colors[k]; + safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); + WFIFOSET(fd, msg_len + 12); + } + } else { + DBIterator *iter = db_iterator(clif->channel_db); + bool show_all = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ? true : false; + clif->message(fd, msg_txt(1410)); // -- Public Channels + if( hChSys.local ) { + sprintf(atcmd_output, msg_txt(1409), hChSys.local_name, map[sd->bl.m].channel ? db_size(map[sd->bl.m].channel->users) : 0);// - #%s ( %d users ) + clif->message(fd, atcmd_output); + } + if( hChSys.ally && sd->status.guild_id ) { + struct guild *g = sd->guild; + if( !g ) { dbi_destroy(iter); return false; } + sprintf(atcmd_output, msg_txt(1409), hChSys.ally_name, db_size(((struct hChSysCh *)g->channel)->users));// - #%s ( %d users ) + clif->message(fd, atcmd_output); + } + for(channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) { + if( show_all || channel->type == hChSys_PUBLIC || channel->type == hChSys_IRC ) { + sprintf(atcmd_output, msg_txt(1409), channel->name, db_size(channel->users));// - #%s ( %d users ) + clif->message(fd, atcmd_output); + } + } + dbi_destroy(iter); + } + } else if ( strcmpi(key,"setcolor") == 0 ) { + + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + + if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) { + sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available + clif->message(fd, atcmd_output); + return false; + } + + if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' + clif->message(fd, atcmd_output); + return false; + } + + for( k = 0; k < hChSys.colors_count; k++ ) { + if( strcmpi(sub2,hChSys.colors_name[k]) == 0 ) + break; + } + if( k == hChSys.colors_count ) { + sprintf(atcmd_output, msg_txt(1411), sub2);// Unknown color '%s' + clif->message(fd, atcmd_output); + return false; + } + channel->color = k; + sprintf(atcmd_output, msg_txt(1413),sub1,hChSys.colors_name[k]);// '%s' channel color updated to '%s' + clif->message(fd, atcmd_output); + } else if ( strcmpi(key,"leave") == 0 ) { + + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + for(k = 0; k < sd->channel_count; k++) { + if( strcmpi(sub1+1,sd->channels[k]->name) == 0 ) + break; + } + if( k == sd->channel_count ) { + sprintf(atcmd_output, msg_txt(1425),sub1);// You're not part of the '%s' channel + clif->message(fd, atcmd_output); + return false; + } + if( sd->channels[k]->type == hChSys_ALLY ) { + do { + for(k = 0; k < sd->channel_count; k++) { + if( sd->channels[k]->type == hChSys_ALLY ) { + clif->chsys_left(sd->channels[k],sd); + break; + } + } + } while( k != sd->channel_count ); + } else + clif->chsys_left(sd->channels[k],sd); + sprintf(atcmd_output, msg_txt(1426),sub1); // You've left the '%s' channel + clif->message(fd, atcmd_output); + } else if ( strcmpi(key,"bindto") == 0 ) { + + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + + for(k = 0; k < sd->channel_count; k++) { + if( strcmpi(sub1+1,sd->channels[k]->name) == 0 ) + break; + } + if( k == sd->channel_count ) { + sprintf(atcmd_output, msg_txt(1425),sub1);// You're not part of the '%s' channel + clif->message(fd, atcmd_output); + return false; + } + + sd->gcbind = sd->channels[k]; + sprintf(atcmd_output, msg_txt(1431),sub1); // Your global chat is now binded to the '%s' channel + clif->message(fd, atcmd_output); + } else if ( strcmpi(key,"unbind") == 0 ) { + + if( sd->gcbind == NULL ) { + clif->message(fd, msg_txt(1432));// Your global chat is not binded to any channel + return false; + } + + sprintf(atcmd_output, msg_txt(1433),sd->gcbind->name); // Your global chat is now unbinded from the '#%s' channel + clif->message(fd, atcmd_output); + + sd->gcbind = NULL; + } else if ( strcmpi(key,"ban") == 0 ) { + struct map_session_data *pl_sd = NULL; + struct hChSysBanEntry *entry = NULL; + + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + + if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) { + sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available + clif->message(fd, atcmd_output); + return false; + } + + if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' + clif->message(fd, atcmd_output); + return false; + } + + if( sub2[0] == '\0' || ( pl_sd = map_nick2sd(sub2) ) == NULL ) { + sprintf(atcmd_output, msg_txt(1434), sub2);// Player '%s' was not found + clif->message(fd, atcmd_output); + return false; + } + + if( pc_has_permission(pl_sd, PC_PERM_HCHSYS_ADMIN) ) { + clif->message(fd, msg_txt(1464)); // Ban failed, not possible to ban this user. + return false; + } + + if( channel->banned && idb_exists(channel->banned,pl_sd->status.account_id) ) { + sprintf(atcmd_output, msg_txt(1465), pl_sd->status.name);// Player '%s' is already banned from this channel + clif->message(fd, atcmd_output); + return false; + } + + if( !channel->banned ) + channel->banned = idb_alloc(DB_OPT_BASE|DB_OPT_ALLOW_NULL_DATA|DB_OPT_RELEASE_DATA); + + CREATE(entry, struct hChSysBanEntry, 1); + + safestrncpy(entry->name, pl_sd->status.name, NAME_LENGTH); + + idb_put(channel->banned, pl_sd->status.account_id, entry); + + clif->chsys_left(channel,pl_sd); + + sprintf(atcmd_output, msg_txt(1437),pl_sd->status.name,sub1); // Player '%s' has now been banned from '%s' channel + clif->message(fd, atcmd_output); + } else if ( strcmpi(key,"unban") == 0 ) { + struct map_session_data *pl_sd = NULL; + + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + + if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) { + sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available + clif->message(fd, atcmd_output); + return false; + } + + if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' + clif->message(fd, atcmd_output); + return false; + } + + if( !channel->banned ) { + sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players + clif->message(fd, atcmd_output); + return false; + } + + if( sub2[0] == '\0' || ( pl_sd = map_nick2sd(sub2) ) == NULL ) { + sprintf(atcmd_output, msg_txt(1434), sub2);// Player '%s' was not found + clif->message(fd, atcmd_output); + return false; + } + + if( !idb_exists(channel->banned,pl_sd->status.account_id) ) { + sprintf(atcmd_output, msg_txt(1440), pl_sd->status.name);// Player '%s' is not banned from this channel + clif->message(fd, atcmd_output); + return false; + } + + idb_remove(channel->banned, pl_sd->status.account_id); + + if( !db_size(channel->banned) ) { + db_destroy(channel->banned); + channel->banned = NULL; + } + + sprintf(atcmd_output, msg_txt(1441),pl_sd->status.name,sub1); // Player '%s' has now been unbanned from the '%s' channel + clif->message(fd, atcmd_output); + } else if ( strcmpi(key,"unbanall") == 0 ) { + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + + if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) { + sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available + clif->message(fd, atcmd_output); + return false; + } + + if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' + clif->message(fd, atcmd_output); + return false; + } + + if( !channel->banned ) { + sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players + clif->message(fd, atcmd_output); + return false; + } + + db_destroy(channel->banned); + channel->banned = NULL; + + sprintf(atcmd_output, msg_txt(1442),sub1); // Removed all bans from '%s' channel + clif->message(fd, atcmd_output); + } else if ( strcmpi(key,"banlist") == 0 ) { + DBIterator *iter = NULL; + DBKey key; + DBData *data; + bool isA = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)?true:false; + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + + if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) { + sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available + clif->message(fd, atcmd_output); + return false; + } + + if( channel->owner != sd->status.char_id && !isA ) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' + clif->message(fd, atcmd_output); + return false; + } + + if( !channel->banned ) { + sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players + clif->message(fd, atcmd_output); + return false; + } + sprintf(atcmd_output, msg_txt(1443), channel->name);// -- '%s' ban list + clif->message(fd, atcmd_output); + + iter = db_iterator(channel->banned); + + for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) { + struct hChSysBanEntry * entry = DB->data2ptr(data); + + if( !isA ) + sprintf(atcmd_output, msg_txt(1444), entry->name);// - %s %s + else + sprintf(atcmd_output, msg_txt(1445), entry->name, key.i);// - %s (%d) + + clif->message(fd, atcmd_output); + } + + dbi_destroy(iter); + + } else if ( strcmpi(key,"setopt") == 0 ) { + const char* opt_str[3] = { + "None", + "JoinAnnounce", + "MessageDelay", + }; + + if( sub1[0] != '#' ) { + clif->message(fd, msg_txt(1405));// Channel name must start with a '#' + return false; + } + + if( !(channel = strdb_get(clif->channel_db, sub1 + 1)) ) { + sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available + clif->message(fd, atcmd_output); + return false; + } + + if( channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s' + clif->message(fd, atcmd_output); + return false; + } + + if( sub2[0] == '\0' ) { + clif->message(fd, msg_txt(1446));// You need to input a option + return false; + } + + for( k = 1; k < 3; k++ ) { + if( strcmpi(sub2,opt_str[k]) == 0 ) + break; + } + + if( k == 3 ) { + sprintf(atcmd_output, msg_txt(1447), sub2);// '%s' is not a known channel option + clif->message(fd, atcmd_output); + clif->message(fd, msg_txt(1448)); // -- Available options + for( k = 1; k < 3; k++ ) { + sprintf(atcmd_output, msg_txt(1444), opt_str[k]);// - '%s' + clif->message(fd, atcmd_output); + } + return false; + } + + if( sub3[0] == '\0' ) { + if ( k == hChSys_OPT_MSG_DELAY ) { + sprintf(atcmd_output, msg_txt(1466), opt_str[k]);// For '%s' you need the amount of seconds (from 0 to 10) + clif->message(fd, atcmd_output); + return false; + } else if( channel->opt & k ) { + sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel setopt %s 0' + clif->message(fd, atcmd_output); + return false; + } else { + channel->opt |= k; + sprintf(atcmd_output, msg_txt(1450), opt_str[k],channel->name);//option '%s' is now enabled for channel '%s' + clif->message(fd, atcmd_output); + return true; + } + } else { + int v = atoi(sub3); + if( k == hChSys_OPT_MSG_DELAY ) { + if( v < 0 || v > 10 ) { + sprintf(atcmd_output, msg_txt(1451), v, opt_str[k]);// value '%d' for option '%s' is out of range (limit is 0-10) + clif->message(fd, atcmd_output); + return false; + } + if( v == 0 ) { + channel->opt &=~ k; + channel->msg_delay = 0; + sprintf(atcmd_output, msg_txt(1453), opt_str[k],channel->name,v);// option '%s' is now disabled for channel '%s' + clif->message(fd, atcmd_output); + return true; + } else { + channel->opt |= k; + channel->msg_delay = v; + sprintf(atcmd_output, msg_txt(1452), opt_str[k],channel->name,v);// option '%s' is now enabled for channel '%s' with %d seconds + clif->message(fd, atcmd_output); + return true; + } + } else { + if( v ) { + if( channel->opt & k ) { + sprintf(atcmd_output, msg_txt(1449), opt_str[k],opt_str[k]); // option '%s' is already enabled, if you'd like to disable it type '@channel opt %s 0' + clif->message(fd, atcmd_output); + return false; + } else { + channel->opt |= k; + sprintf(atcmd_output, msg_txt(1454), opt_str[k],channel->name);//option '%s' is now enabled for channel '%s' + clif->message(fd, atcmd_output); + } + } else { + if( !(channel->opt & k) ) { + sprintf(atcmd_output, msg_txt(1454), opt_str[k],channel->name); // option '%s' is not enabled on channel '%s' + clif->message(fd, atcmd_output); + return false; + } else { + channel->opt &=~ k; + sprintf(atcmd_output, msg_txt(1453), opt_str[k],channel->name);// option '%s' is now disabled for channel '%s' + clif->message(fd, atcmd_output); + return true; + } + } + } + + } + + } else { + atcmd_channel_help(fd,command,( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) )); + } + + return true; +} +/* debug only, delete after */ +ACMD(fontcolor) { + unsigned char k; + unsigned short msg_len = 1; + char mout[40]; - clif_displaymessage(fd, msg_txt(1392)); // Cart Added - - return 0; - #undef MC_CART_MDFY + if( !message || !*message ) { + for( k = 0; k < hChSys.colors_count; k++ ) { + msg_len += sprintf(mout, "[ %s ] : %s",command,hChSys.colors_name[k]); + + WFIFOHEAD(fd,msg_len + 12); + WFIFOW(fd,0) = 0x2C1; + WFIFOW(fd,2) = msg_len + 12; + WFIFOL(fd,4) = 0; + WFIFOL(fd,8) = hChSys.colors[k]; + safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); + WFIFOSET(fd, msg_len + 12); + } + return false; + } + + if( message[0] == '0' ) { + sd->fontcolor = 0; + return true; + } + + for( k = 0; k < hChSys.colors_count; k++ ) { + if( strcmpi(message,hChSys.colors_name[k]) == 0 ) + break; + } + if( k == hChSys.colors_count ) { + sprintf(atcmd_output, msg_txt(1411), message);// Unknown color '%s' + clif->message(fd, atcmd_output); + return false; + } + + sd->fontcolor = k + 1; + msg_len += sprintf(mout, "Color changed to '%s'",hChSys.colors_name[k]); + + WFIFOHEAD(fd,msg_len + 12); + WFIFOW(fd,0) = 0x2C1; + WFIFOW(fd,2) = msg_len + 12; + WFIFOL(fd,4) = 0; + WFIFOL(fd,8) = hChSys.colors[k]; + safestrncpy((char*)WFIFOP(fd,12), mout, msg_len); + WFIFOSET(fd, msg_len + 12); + return true; } +ACMD(searchstore){ + int val = atoi(message); + + switch( val ) { + case 0://EFFECTTYPE_NORMAL + case 1://EFFECTTYPE_CASH + break; + default: + val = 0; + break; + } + searchstore->open(sd, 99, val); + + return true; +} +ACMD(costume){ + const char* names[4] = { + "Wedding", + "Xmas", + "Summer", + "Hanbok", + }; + const int name2id[4] = { SC_WEDDING, SC_XMAS, SC_SUMMER, SC_HANBOK }; + unsigned short k = 0; + + if( !message || !*message ) { + for( k = 0; k < 4; k++ ) { + if( sd->sc.data[name2id[k]] ) { + sprintf(atcmd_output,msg_txt(1473),names[k]);//Costume '%s' removed. + clif->message(sd->fd,atcmd_output); + status_change_end(&sd->bl,name2id[k],INVALID_TIMER); + return true; + } + } + + clif->message(sd->fd,msg_txt(1472)); + for( k = 0; k < 4; k++ ) { + sprintf(atcmd_output,msg_txt(1471),names[k]);//-- %s + clif->message(sd->fd,atcmd_output); + } + return false; + } + + for( k = 0; k < 4; k++ ) { + if( sd->sc.data[name2id[k]] ) { + sprintf(atcmd_output,msg_txt(1470),names[k]);// You're already with a '%s' costume, type '@costume' to remove it. + clif->message(sd->fd,atcmd_output); + return false; + } + } + + for( k = 0; k < 4; k++ ) { + if( strcmpi(message,names[k]) == 0 ) + break; + } + if( k == 4 ) { + sprintf(atcmd_output,msg_txt(1469),message);// '%s' is not a known costume + clif->message(sd->fd,atcmd_output); + return false; + } + + sc_start(&sd->bl, name2id[k], 100, 0, -1); + + return true; +} /** * Fills the reference of available commands in atcommand DBMap **/ -#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL } -#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL } +#define ACMD_DEF(x) { #x, atcommand_ ## x, NULL, NULL, NULL, true } +#define ACMD_DEF2(x2, x) { x2, atcommand_ ## x, NULL, NULL, NULL, true } void atcommand_basecommands(void) { /** * Command reference list, place the base of your commands here @@ -9030,7 +9658,6 @@ void atcommand_basecommands(void) { ACMD_DEF(leave), ACMD_DEF(accept), ACMD_DEF(reject), - ACMD_DEF(main), ACMD_DEF(clone), ACMD_DEF2("slaveclone", clone), ACMD_DEF2("evilclone", clone), @@ -9078,20 +9705,26 @@ void atcommand_basecommands(void) { ACMD_DEF2("rmvperm", addperm), ACMD_DEF(unloadnpcfile), ACMD_DEF(cart), - ACMD_DEF(mount2) + ACMD_DEF(mount2), + ACMD_DEF(join), + ACMD_DEF(channel), + ACMD_DEF(fontcolor), + ACMD_DEF(searchstore), + ACMD_DEF(costume), }; - AtCommandInfo* atcommand; + AtCommandInfo* cmd; int i; - + for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) { - if(atcommand_exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK + if(atcommand->exists(atcommand_base[i].command)) { // Should not happen if atcommand_base[] array is OK ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command); continue; } - CREATE(atcommand, AtCommandInfo, 1); - safestrncpy(atcommand->command, atcommand_base[i].command, sizeof(atcommand->command)); - atcommand->func = atcommand_base[i].func; - strdb_put(atcommand_db, atcommand->command, atcommand); + CREATE(cmd, AtCommandInfo, 1); + safestrncpy(cmd->command, atcommand_base[i].command, sizeof(cmd->command)); + cmd->func = atcommand_base[i].func; + cmd->help = NULL;/* start as null dear */ + strdb_put(atcommand->db, cmd->command, cmd); } return; } @@ -9099,33 +9732,32 @@ void atcommand_basecommands(void) { /*========================================== * Command lookup functions *------------------------------------------*/ -bool atcommand_exists(const char* name) -{ - return strdb_exists(atcommand_db, name); +AtCommandInfo* atcommand_exists(const char* name) { + return strdb_get(atcommand->db, name); } -static AtCommandInfo* get_atcommandinfo_byname(const char *name) -{ - if (strdb_exists(atcommand_db, name)) - return (AtCommandInfo*)strdb_get(atcommand_db, name); +static AtCommandInfo* get_atcommandinfo_byname(const char *name) { + AtCommandInfo *cmd; + if ((cmd = strdb_get(atcommand->db, name))) + return cmd; return NULL; } static const char* atcommand_checkalias(const char *aliasname) { AliasInfo *alias_info = NULL; - if ((alias_info = (AliasInfo*)strdb_get(atcommand_alias_db, aliasname)) != NULL) + if ((alias_info = (AliasInfo*)strdb_get(atcommand->alias_db, aliasname)) != NULL) return alias_info->command->command; return aliasname; } /// AtCommand suggestion -static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool atcommand) { +static void atcommand_get_suggestions(struct map_session_data* sd, const char *name, bool is_atcmd_cmd) { DBIterator* atcommand_iter; DBIterator* alias_iter; AtCommandInfo* command_info = NULL; AliasInfo* alias_info = NULL; - AtCommandType type = atcommand ? COMMAND_ATCOMMAND : COMMAND_CHARCOMMAND; + AtCommandType type = is_atcmd_cmd ? COMMAND_ATCOMMAND : COMMAND_CHARCOMMAND; char* full_match[MAX_SUGGESTIONS]; char* suggestions[MAX_SUGGESTIONS]; char* match; @@ -9135,13 +9767,13 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n if (!battle_config.atcommand_suggestions_enabled) return; - atcommand_iter = db_iterator(atcommand_db); - alias_iter = db_iterator(atcommand_alias_db); + atcommand_iter = db_iterator(atcommand->db); + alias_iter = db_iterator(atcommand->alias_db); // Build the matches for (command_info = dbi_first(atcommand_iter); dbi_exists(atcommand_iter); command_info = dbi_next(atcommand_iter)) { match = strstr(command_info->command, name); - can_use = pc_can_use_command(sd, command_info->command, type); + can_use = atcommand->can_use2(sd, command_info->command, type); if ( prefix_count < MAX_SUGGESTIONS && match == command_info->command && can_use ) { suggestions[prefix_count] = command_info->command; ++prefix_count; @@ -9154,7 +9786,7 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n for (alias_info = dbi_first(alias_iter); dbi_exists(alias_iter); alias_info = dbi_next(alias_iter)) { match = strstr(alias_info->alias, name); - can_use = pc_can_use_command(sd, alias_info->command->command, type); + can_use = atcommand->can_use2(sd, alias_info->command->command,type); if ( prefix_count < MAX_SUGGESTIONS && match == alias_info->alias && can_use) { suggestions[prefix_count] = alias_info->alias; ++prefix_count; @@ -9184,7 +9816,7 @@ static void atcommand_get_suggestions(struct map_session_data* sd, const char *n strcat(buffer," "); } - clif_displaymessage(sd->fd, buffer); + clif->message(sd->fd, buffer); } dbi_destroy(atcommand_iter); @@ -9216,11 +9848,11 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message return true; // skip 10/11-langtype's codepage indicator, if detected - if ( message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand_symbol || message[3] == charcommand_symbol) ) + if ( message[0] == '|' && strlen(message) >= 4 && (message[3] == atcommand->at_symbol || message[3] == atcommand->char_symbol) ) message += 3; //Should display as a normal message - if ( *message != atcommand_symbol && *message != charcommand_symbol ) + if ( *message != atcommand->at_symbol && *message != atcommand->char_symbol ) return false; // type value 0 = server invoked: bypass restrictions @@ -9228,12 +9860,12 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message if ( type == 1) { //Commands are disabled on maps flagged as 'nocommand' if ( map[sd->bl.m].nocommand && pc_get_group_level(sd) < map[sd->bl.m].nocommand ) { - clif_displaymessage(fd, msg_txt(143)); + clif->message(fd, msg_txt(143)); return false; } } - if (*message == charcommand_symbol) { + if (*message == atcommand->char_symbol) { do { int x, y, z; @@ -9271,12 +9903,12 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message return false;/* display as normal message */ } - sprintf(output, msg_txt(1388), charcommand_symbol); // Charcommand failed (usage: %c<command> <char name> <parameters>). - clif_displaymessage(fd, output); + sprintf(output, msg_txt(1388), atcommand->char_symbol); // Charcommand failed (usage: %c<command> <char name> <parameters>). + clif->message(fd, output); return true; } while(0); } - else if (*message == atcommand_symbol) { + else if (*message == atcommand->at_symbol) { //atcmd_msg is constructed above differently for charcommands //it's copied from message if not a charcommand so it can //pass through the rest of the code compatible with both symbols @@ -9292,27 +9924,31 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message params[0] = '\0'; // @commands (script based) - if(type == 1 && atcmd_binding_count > 0) { + if(type == 1 && atcommand->binding_count > 0) { struct atcmd_binding_data * binding; - // Check if the command initiated is a character command - if (*message == charcommand_symbol && - (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { - sprintf(output, msg_txt(1389), command); // %s failed. Player not found. - clif_displaymessage(fd, output); - return true; - } - // Get atcommand binding - binding = get_atcommandbind_byname(command); + binding = atcommand->get_bind_byname(command); // Check if the binding isn't NULL and there is a NPC event, level of usage met, et cetera if( binding != NULL && binding->npc_event[0] && - ((*atcmd_msg == atcommand_symbol && pc_get_group_level(sd) >= binding->level) || - (*atcmd_msg == charcommand_symbol && pc_get_group_level(sd) >= binding->level2))) + ((*atcmd_msg == atcommand->at_symbol && pc_get_group_level(sd) >= binding->group_lv) || + (*atcmd_msg == atcommand->char_symbol && pc_get_group_level(sd) >= binding->group_lv_char))) { // Check if self or character invoking; if self == character invoked, then self invoke. - bool invokeFlag = ((*atcmd_msg == atcommand_symbol) ? 1 : 0); + bool invokeFlag = ((*atcmd_msg == atcommand->at_symbol) ? 1 : 0); + + // Check if the command initiated is a character command + if (*message == atcommand->char_symbol && + (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { + sprintf(output, msg_txt(1389), command); // %s failed. Player not found. + clif->message(fd, output); + return true; + } + + if( binding->log ) /* log only if this command should be logged [Ind/Hercules] */ + logs->atcommand(sd, atcmd_msg); + npc_do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event); return true; } @@ -9323,8 +9959,8 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message if (info == NULL) { if( pc_get_group_level(sd) ) { // TODO: remove or replace with proper permission sprintf(output, msg_txt(153), command); // "%s is Unknown Command." - clif_displaymessage(fd, output); - atcommand_get_suggestions(sd, command + 1, *message == atcommand_symbol); + clif->message(fd, output); + atcommand_get_suggestions(sd, command + 1, *message == atcommand->at_symbol); return true; } else return false; @@ -9332,37 +9968,43 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message // type == 1 : player invoked if (type == 1) { - if ((*command == atcommand_symbol && info->at_groups[sd->group_pos] == 0) || - (*command == charcommand_symbol && info->char_groups[sd->group_pos] == 0) ) { + int i; + if ((*command == atcommand->at_symbol && info->at_groups[sd->group_pos] == 0) || + (*command == atcommand->char_symbol && info->char_groups[sd->group_pos] == 0) ) { return false; } if( pc_isdead(sd) && pc_has_permission(sd,PC_PERM_DISABLE_CMD_DEAD) ) { - clif_displaymessage(fd, msg_txt(1393)); // You can't use commands while dead + clif->message(fd, msg_txt(1393)); // You can't use commands while dead return true; } + for(i = 0; i < map[sd->bl.m].zone->disabled_commands_count; i++) { + if( info->func == map[sd->bl.m].zone->disabled_commands[i]->cmd ) { + if( sd->group_level < map[sd->bl.m].zone->disabled_commands[i]->group_lv ) { + clif->colormes(sd->fd,COLOR_RED,"This command is disabled in this area"); + return true; + } else + break;/* already found the matching command, no need to keep checking -- just go on */ + } + } } - + // Check if target is valid only if confirmed that player can use command. - if (*message == charcommand_symbol && + if (*message == atcommand->char_symbol && (ssd = map_nick2sd(charname)) == NULL && (ssd = map_nick2sd(charname2)) == NULL ) { sprintf(output, msg_txt(1389), command); // %s failed. Player not found. - clif_displaymessage(fd, output); + clif->message(fd, output); return true; } //Attempt to use the command - if ( (info->func(fd, (*atcmd_msg == atcommand_symbol) ? sd : ssd, command, params) != 0) ) - { + if ( (info->func(fd, (*atcmd_msg == atcommand->at_symbol) ? sd : ssd, command, params,info) != true) ) { sprintf(output,msg_txt(154), command); // %s failed. - clif_displaymessage(fd, output); + clif->message(fd, output); return true; } - //Log only if successful. - if ( *atcmd_msg == atcommand_symbol ) - log_atcommand(sd, atcmd_msg); - else if ( *atcmd_msg == charcommand_symbol ) - log_atcommand(sd, message); + if( info->log ) /* log only if this command should be logged [Ind/Hercules] */ + logs->atcommand(sd, *atcmd_msg == atcommand->at_symbol ? atcmd_msg : message); return true; } @@ -9370,9 +10012,9 @@ bool is_atcommand(const int fd, struct map_session_data* sd, const char* message /*========================================== * *------------------------------------------*/ -static void atcommand_config_read(const char* config_filename) -{ - config_setting_t *aliases = NULL, *help = NULL; +static void atcommand_config_read(const char* config_filename) { + config_t atcommand_config; + config_setting_t *aliases = NULL, *help = NULL, *nolog = NULL; const char *symbol = NULL; int num_aliases = 0; @@ -9385,8 +10027,8 @@ static void atcommand_config_read(const char* config_filename) *symbol != '/' && // symbol of client commands *symbol != '%' && // symbol of party chat *symbol != '$' && // symbol of guild chat - *symbol != charcommand_symbol) - atcommand_symbol = *symbol; + *symbol != atcommand->char_symbol) + atcommand->at_symbol = *symbol; } if (config_lookup_string(&atcommand_config, "charcommand_symbol", &symbol)) { @@ -9394,8 +10036,8 @@ static void atcommand_config_read(const char* config_filename) *symbol != '/' && // symbol of client commands *symbol != '%' && // symbol of party chat *symbol != '$' && // symbol of guild chat - *symbol != atcommand_symbol) - charcommand_symbol = *symbol; + *symbol != atcommand->at_symbol) + atcommand->char_symbol = *symbol; } // Command aliases @@ -9405,7 +10047,7 @@ static void atcommand_config_read(const char* config_filename) int count = config_setting_length(aliases); for (i = 0; i < count; ++i) { - config_setting_t *command = NULL; + config_setting_t *command; const char *commandname = NULL; int j = 0, alias_count = 0; AtCommandInfo *commandinfo = NULL; @@ -9414,30 +10056,49 @@ static void atcommand_config_read(const char* config_filename) if (config_setting_type(command) != CONFIG_TYPE_ARRAY) continue; commandname = config_setting_name(command); - if (!atcommand_exists(commandname)) { + if ( !( commandinfo = atcommand_exists(commandname) ) ) { ShowConfigWarning(command, "atcommand_config_read: can not set alias for non-existent command %s", commandname); continue; } - commandinfo = get_atcommandinfo_byname(commandname); alias_count = config_setting_length(command); for (j = 0; j < alias_count; ++j) { const char *alias = config_setting_get_string_elem(command, j); if (alias != NULL) { AliasInfo *alias_info; - if (strdb_exists(atcommand_alias_db, alias)) { + if (strdb_exists(atcommand->alias_db, alias)) { ShowConfigWarning(command, "atcommand_config_read: alias %s already exists", alias); continue; } CREATE(alias_info, AliasInfo, 1); alias_info->command = commandinfo; safestrncpy(alias_info->alias, alias, sizeof(alias_info->alias)); - strdb_put(atcommand_alias_db, alias, alias_info); + strdb_put(atcommand->alias_db, alias, alias_info); ++num_aliases; } } } } + nolog = config_lookup(&atcommand_config, "nolog"); + if (nolog != NULL) { + int i = 0; + int count = config_setting_length(nolog); + + for (i = 0; i < count; ++i) { + config_setting_t *command; + const char *commandname = NULL; + AtCommandInfo *commandinfo = NULL; + + command = config_setting_get_elem(nolog, i); + commandname = config_setting_name(command); + if ( !( commandinfo = atcommand_exists(commandname) ) ) { + ShowConfigWarning(command, "atcommand_config_read: can not disable logging for non-existent command %s", commandname); + continue; + } + commandinfo->log = false; + } + } + // Commands help // We only check if all commands exist help = config_lookup(&atcommand_config, "help"); @@ -9446,21 +10107,32 @@ static void atcommand_config_read(const char* config_filename) int i; for (i = 0; i < count; ++i) { - config_setting_t *command = NULL; - const char *commandname = NULL; + config_setting_t *command; + const char *commandname; + AtCommandInfo *commandinfo = NULL; command = config_setting_get_elem(help, i); commandname = config_setting_name(command); - if (!atcommand_exists(commandname)) + if ( !( commandinfo = atcommand_exists(commandname) ) ) ShowConfigWarning(command, "atcommand_config_read: command %s does not exist", commandname); + else { + if( commandinfo->help == NULL ) { + const char *str = config_setting_get_string(command); + int len = strlen(str); + commandinfo->help = aMalloc( len * sizeof(char) ); + safestrncpy(commandinfo->help, str, len); + } + } } } ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename); + + config_destroy(&atcommand_config); return; } -void atcommand_db_load_groups(int* group_ids) { - DBIterator *iter = db_iterator(atcommand_db); +void atcommand_db_load_groups(void) { + DBIterator *iter = db_iterator(atcommand->db); AtCommandInfo* cmd; int i; @@ -9468,11 +10140,11 @@ void atcommand_db_load_groups(int* group_ids) { cmd->at_groups = aMalloc( pc_group_max * sizeof(char) ); cmd->char_groups = aMalloc( pc_group_max * sizeof(char) ); for(i = 0; i < pc_group_max; i++) { - if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_ATCOMMAND ) ) + if( pc_group_can_use_command(atcommand->group_ids[i], cmd->command, COMMAND_ATCOMMAND ) ) cmd->at_groups[i] = 1; else cmd->at_groups[i] = 0; - if( pc_group_can_use_command(group_ids[i], cmd->command, COMMAND_CHARCOMMAND ) ) + if( pc_group_can_use_command(atcommand->group_ids[i], cmd->command, COMMAND_CHARCOMMAND ) ) cmd->char_groups[i] = 1; else cmd->char_groups[i] = 0; @@ -9483,39 +10155,118 @@ void atcommand_db_load_groups(int* group_ids) { return; } -void atcommand_db_clear(void) { +bool atcommand_can_use(struct map_session_data *sd, const char *command) { + AtCommandInfo *info = get_atcommandinfo_byname(atcommand_checkalias(command + 1)); + + if (info == NULL) + return false; + + if ((*command == atcommand->at_symbol && info->at_groups[sd->group_pos] != 0) || + (*command == atcommand->char_symbol && info->char_groups[sd->group_pos] != 0) ) { + return true; + } + + return false; +} +bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtCommandType type) { + AtCommandInfo *info = get_atcommandinfo_byname(atcommand_checkalias(command)); + + if (info == NULL) + return false; + + if ((type == COMMAND_ATCOMMAND && info->at_groups[sd->group_pos] != 0) || + (type == COMMAND_CHARCOMMAND && info->char_groups[sd->group_pos] != 0) ) { + return true; + } + + return false; +} +bool atcommand_hp_add(char *name, AtCommandFunc func) { + AtCommandInfo* cmd; + + if( runflag == MAPSERVER_ST_RUNNING ) { + ShowDebug("atcommand_hp_add: Commands can't be added after server is ready, skipping '%s'...\n",name); + return false; + } + + if( !atcommand->db ) + atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + + if( atcommand->exists(name) ) { + ShowDebug("atcommand_hp_add: duplicate command '%s', skipping...\n", name); + return false; + } + + CREATE(cmd, AtCommandInfo, 1); + + safestrncpy(cmd->command, name, sizeof(cmd->command)); + cmd->func = func; + cmd->help = NULL;/* start as null dear */ - if (atcommand_db != NULL) { - DBIterator *iter = db_iterator(atcommand_db); + strdb_put(atcommand->db, cmd->command, cmd); + return true; +} +void atcommand_db_clear(void) { + if (atcommand->db != NULL) { + DBIterator *iter = db_iterator(atcommand->db); AtCommandInfo* cmd; for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) { aFree(cmd->at_groups); aFree(cmd->char_groups); + if( cmd->help != NULL ) + aFree(cmd->help); } dbi_destroy(iter); - db_destroy(atcommand_db); + db_destroy(atcommand->db); + atcommand->db = NULL; } - if (atcommand_alias_db != NULL) - db_destroy(atcommand_alias_db); - - config_destroy(&atcommand_config); + if (atcommand->alias_db != NULL) + db_destroy(atcommand->alias_db); } void atcommand_doload(void) { - atcommand_db_clear(); - atcommand_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); - atcommand_alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + if( runflag >= MAPSERVER_ST_RUNNING ) + atcommand_db_clear(); + if( !atcommand->db ) + atcommand->db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); + atcommand->alias_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, ATCOMMAND_LENGTH); atcommand_basecommands(); //fills initial atcommand_db with known commands atcommand_config_read(ATCOMMAND_CONF_FILENAME); } void do_init_atcommand(void) { + atcommand->at_symbol = '@'; + atcommand->char_symbol = '#'; + atcommand->binding_count = 0; + atcommand_doload(); } void do_final_atcommand(void) { atcommand_db_clear(); + if( atcommand->group_ids ) + aFree(atcommand->group_ids); +} + +void atcommand_defaults(void) { + atcommand = &atcommand_s; + + atcommand->db = NULL; + atcommand->alias_db = NULL; + + atcommand->init = do_init_atcommand; + atcommand->final = do_final_atcommand; + + atcommand->parse = is_atcommand; + atcommand->can_use = atcommand_can_use; + atcommand->can_use2 = atcommand_can_use2; + atcommand->create = atcommand_hp_add; + atcommand->load_groups = atcommand_db_load_groups; + atcommand->exists = atcommand_exists; + atcommand->msg_read = msg_config_read; + atcommand->final_msg = do_final_msg; + atcommand->get_bind_byname = get_atcommandbind_byname; } diff --git a/src/map/atcommand.h b/src/map/atcommand.h index 8affa4c26..f09b1f2b8 100644 --- a/src/map/atcommand.h +++ b/src/map/atcommand.h @@ -1,51 +1,99 @@ -// 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 _ATCOMMAND_H_ #define _ATCOMMAND_H_ -struct map_session_data; +#include "../common/db.h" -//This is the distance at which @autoloot works, -//if the item drops farther from the player than this, -//it will not be autolooted. [Skotlex] -//Note: The range is unlimited unless this define is set. -//#define AUTOLOOT_DISTANCE AREA_SIZE +/** + * Declarations + **/ +struct map_session_data; +struct AtCommandInfo; -extern char atcommand_symbol; -extern char charcommand_symbol; +/** + * Defines + **/ +#define ATCOMMAND_LENGTH 50 +#define MAX_MSG 1500 +/** + * Enumerations + **/ typedef enum { COMMAND_ATCOMMAND = 1, COMMAND_CHARCOMMAND = 2, } AtCommandType; -typedef int (*AtCommandFunc)(const int fd, struct map_session_data* sd, const char* command, const char* message); - -bool is_atcommand(const int fd, struct map_session_data* sd, const char* message, int type); - -void do_init_atcommand(void); -void do_final_atcommand(void); -void atcommand_db_load_groups(int* group_ids); - -bool atcommand_exists(const char* name); +/** + * Typedef + **/ +typedef bool (*AtCommandFunc)(const int fd, struct map_session_data* sd, const char* command, const char* message,struct AtCommandInfo *info); +typedef struct AtCommandInfo AtCommandInfo; +typedef struct AliasInfo AliasInfo; -const char* msg_txt(int msg_number); -int msg_config_read(const char* cfgName); -void do_final_msg(void); +/** + * Structures + **/ +struct AliasInfo { + AtCommandInfo *command; + char alias[ATCOMMAND_LENGTH]; +}; -extern int atcmd_binding_count; +struct AtCommandInfo { + char command[ATCOMMAND_LENGTH]; + AtCommandFunc func; + char *at_groups;/* quick @commands "can-use" lookup */ + char *char_groups;/* quick @charcommands "can-use" lookup */ + char *help;/* quick access to this @command's help string */ + bool log;/* whether to log this command or not, regardless of group settings */ +}; -// @commands (script based) struct atcmd_binding_data { - char command[50]; - char npc_event[50]; - int level; - int level2; + char command[ATCOMMAND_LENGTH]; + char npc_event[ATCOMMAND_LENGTH]; + int group_lv; + int group_lv_char; + bool log; }; -struct atcmd_binding_data** atcmd_binding; +/** + * Interface + **/ +struct atcommand_interface { + unsigned char at_symbol; + unsigned char char_symbol; + /* atcommand binding */ + struct atcmd_binding_data** binding; + int binding_count; + unsigned int *group_ids; + /* other vars */ + DBMap* db; //name -> AtCommandInfo + DBMap* alias_db; //alias -> AtCommandInfo + /* */ + void (*init) (void); + void (*final) (void); + /* */ + bool (*parse) (const int fd, struct map_session_data* sd, const char* message, int type); + bool (*create) (char *name, AtCommandFunc func); + bool (*can_use) (struct map_session_data *sd, const char *command); + bool (*can_use2) (struct map_session_data *sd, const char *command, AtCommandType type); + void (*load_groups) (void); + AtCommandInfo* (*exists) (const char* name); + int (*msg_read) (const char* cfgName); + void (*final_msg) (void); + /* atcommand binding */ + struct atcmd_binding_data* (*get_bind_byname) (const char* name); +} atcommand_s; -struct atcmd_binding_data* get_atcommandbind_byname(const char* name); +struct atcommand_interface *atcommand; + +const char* msg_txt(int msg_number); +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) +#define ACMD_A(x) atcommand_ ## x #endif /* _ATCOMMAND_H_ */ diff --git a/src/map/battle.c b/src/map/battle.c index 0959ea858..f6fba5ca5 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -40,9 +41,6 @@ int attr_fix_table[4][ELE_MAX][ELE_MAX]; struct Battle_Config battle_config; static struct eri *delay_damage_ers; //For battle delay damage structures. -#define DAMAGE_RATE(a){damage = (int64)damage * (a)/100;} -#define DAMAGE_SUBRATE(a){damage -= (int64)damage * (a)/100;} -#define DAMAGE_ADDRATE(a){damage += (int64)damage * (a)/100;} int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last skill in use by this bl. struct unit_data *ud; @@ -59,7 +57,7 @@ int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last s /*========================================== * Get random targetting enemy *------------------------------------------*/ -static int battle_gettargeted_sub(struct block_list *bl, va_list ap) { +int battle_gettargeted_sub(struct block_list *bl, va_list ap) { struct block_list **bl_list; struct unit_data *ud; int target_id; @@ -92,7 +90,7 @@ struct block_list* battle_gettargeted(struct block_list *target) { nullpo_retr(NULL, target); memset(bl_list, 0, sizeof(bl_list)); - map_foreachinrange(battle_gettargeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id); + map_foreachinrange(battle->get_targeted_sub, target, AREA_SIZE, BL_CHAR, bl_list, &c, target->id); if ( c == 0 ) return NULL; if( c > 24 ) @@ -116,7 +114,7 @@ int battle_gettarget(struct block_list* bl) { return 0; } -static int battle_getenemy_sub(struct block_list *bl, va_list ap) { +int battle_getenemy_sub(struct block_list *bl, va_list ap) { struct block_list **bl_list; struct block_list *target; int *c; @@ -134,7 +132,7 @@ static int battle_getenemy_sub(struct block_list *bl, va_list ap) { if (status_isdead(bl)) return 0; - if (battle_check_target(target, bl, BCT_ENEMY) > 0) { + if (battle->check_target(target, bl, BCT_ENEMY) > 0) { bl_list[(*c)++] = bl; return 1; } @@ -148,7 +146,7 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang int c = 0; memset(bl_list, 0, sizeof(bl_list)); - map_foreachinrange(battle_getenemy_sub, target, range, type, bl_list, &c, target); + map_foreachinrange(battle->get_enemy_sub, target, range, type, bl_list, &c, target); if ( c == 0 ) return NULL; @@ -158,7 +156,7 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang return bl_list[rnd()%c]; } -static int battle_getenemyarea_sub(struct block_list *bl, va_list ap) { +int battle_getenemyarea_sub(struct block_list *bl, va_list ap) { struct block_list **bl_list, *src; int *c, ignore_id; @@ -176,7 +174,7 @@ static int battle_getenemyarea_sub(struct block_list *bl, va_list ap) { if( status_isdead(bl) ) return 0; - if( battle_check_target(src, bl, BCT_ENEMY) > 0 ) {// Is Enemy!... + if( battle->check_target(src, bl, BCT_ENEMY) > 0 ) {// Is Enemy!... bl_list[(*c)++] = bl; return 1; } @@ -190,7 +188,7 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int int c = 0; memset(bl_list, 0, sizeof(bl_list)); - map_foreachinarea(battle_getenemyarea_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id); + map_foreachinarea(battle->get_enemy_area_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id); if( c == 0 ) return NULL; @@ -211,6 +209,7 @@ struct delay_damage { uint16 skill_id; enum damage_lv dmg_lv; unsigned short attack_type; + bool additional_effects; }; int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { @@ -233,10 +232,10 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { { map_freeblock_lock(); status_fix_damage(src, target, dat->damage, dat->delay); - if( dat->attack_type && !status_isdead(target) ) - skill_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick); + if( dat->attack_type && !status_isdead(target) && dat->additional_effects ) + skill->additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,dat->dmg_lv,tick); if( dat->dmg_lv > ATK_BLOCK && dat->attack_type ) - skill_counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); + skill->counter_additional_effect(src,target,dat->skill_id,dat->skill_lv,dat->attack_type,tick); map_freeblock_unlock(); } else if( !src && dat->skill_id == CR_REFLECTSHIELD ) { /** @@ -251,7 +250,7 @@ int battle_delay_damage_sub(int tid, unsigned int tick, int id, intptr_t data) { return 0; } -int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int damage, enum damage_lv dmg_lv, int ddelay) +int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) { struct delay_damage *dat; struct status_change *sc; @@ -266,10 +265,10 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, if ( !battle_config.delay_battle_damage || amotion <= 1 ) { map_freeblock_lock(); status_fix_damage(src, target, damage, ddelay); // We have to seperate here between reflect damage and others [icescope] - if( attack_type && !status_isdead(target) ) - skill_additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, gettick()); + if( attack_type && !status_isdead(target) && additional_effects ) + skill->additional_effect(src, target, skill_id, skill_lv, attack_type, dmg_lv, gettick()); if( dmg_lv > ATK_BLOCK && attack_type ) - skill_counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); + skill->counter_additional_effect(src, target, skill_id, skill_lv, attack_type, gettick()); map_freeblock_unlock(); return 0; } @@ -283,10 +282,11 @@ int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, dat->dmg_lv = dmg_lv; dat->delay = ddelay; dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported. + dat->additional_effects = additional_effects; if (src->type != BL_PC && amotion > 1000) amotion = 1000; //Aegis places a damage-delay cap of 1 sec to non player attacks. [Skotlex] - add_timer(tick+amotion, battle_delay_damage_sub, 0, (intptr_t)dat); + add_timer(tick+amotion, battle->delay_damage_sub, 0, (intptr_t)dat); return 0; } @@ -334,20 +334,20 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag ratio += enchant_eff[sc->data[SC_DELUGE]->val1-1]; } if( target && target->type == BL_SKILL ) { - if( atk_elem == ELE_FIRE && battle_getcurrentskill(target) == GN_WALLOFTHORN ) { + if( atk_elem == ELE_FIRE && battle->get_current_skill(target) == GN_WALLOFTHORN ) { struct skill_unit *su = (struct skill_unit*)target; struct skill_unit_group *sg; struct block_list *src; - int x,y; if( !su || !su->alive || (sg = su->group) == NULL || !sg || sg->val3 == -1 || (src = map_id2bl(sg->src_id)) == NULL || status_isdead(src) ) return 0; if( sg->unit_id != UNT_FIREWALL ) { + int x,y; x = sg->val3 >> 16; y = sg->val3 & 0xffff; - skill_unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1); + skill->unitsetting(src,su->group->skill_id,su->group->skill_lv,x,y,1); sg->val3 = -1; sg->limit = DIFF_TICK(gettick(),sg->tick)+300; } @@ -366,7 +366,7 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag if( tsc->data[SC_THORNSTRAP]) status_change_end(target, SC_THORNSTRAP, INVALID_TIMER); if( tsc->data[SC_FIRE_CLOAK_OPTION]) - DAMAGE_SUBRATE(tsc->data[SC_FIRE_CLOAK_OPTION]->val2) + damage -= damage * tsc->data[SC_FIRE_CLOAK_OPTION]->val2 / 100; if( tsc->data[SC_CRYSTALIZE] && target->type != BL_MOB) status_change_end(target, SC_CRYSTALIZE, INVALID_TIMER); if( tsc->data[SC_EARTH_INSIGNIA]) damage += damage/2; @@ -406,9 +406,9 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag ARR_FIND(1, 6, t, tsd->talisman[t] > 0); if( t < 5 && atk_elem == t ) - DAMAGE_SUBRATE(tsd->talisman[t] * 3) // -3% custom value + damage -= damage * ( tsd->talisman[t] * 3 ) / 100;// -3% custom value } - return (int64)damage*ratio/100; + return damage*ratio/100; } /*========================================== @@ -431,7 +431,6 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li tstatus = status_get_status_data(target); s_race2 = status_get_race2(src); -#define bccDAMAGE_RATE(a){ damage = (int64)damage * (a)/1000;} switch(attack_type){ case BF_MAGIC: if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) { @@ -448,7 +447,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li } } if (cardfix != 1000) - bccDAMAGE_RATE(cardfix) + damage = damage * cardfix / 1000; } if( tsd && !(nk&NK_NO_CARDFIX_DEF) ) @@ -492,7 +491,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li cardfix = cardfix * ( 100 - tsd->sc.data[SC_MDEF_RATE]->val1 ) / 100; if (cardfix != 1000) - bccDAMAGE_RATE(cardfix) + damage = damage * cardfix / 1000; } break; case BF_WEAPON: @@ -626,9 +625,9 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li } #endif if( (left&1) && cardfix_ != 1000 ) - bccDAMAGE_RATE(cardfix_) + damage = damage * cardfix_ / 1000; else if( cardfix != 1000 ) - bccDAMAGE_RATE(cardfix) + damage = damage * cardfix / 1000; }else if( tsd && !(nk&NK_NO_CARDFIX_DEF) ){ if( !(nk&NK_NO_ELEFIX) ) @@ -682,7 +681,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li cardfix = cardfix * ( 100 - tsd->sc.data[SC_DEF_RATE]->val1 ) / 100; if( cardfix != 1000 ) - bccDAMAGE_RATE(cardfix) + damage = damage * cardfix / 1000; } break; case BF_MISC: @@ -716,7 +715,7 @@ int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_li cardfix = cardfix * ( 100 - tsd->bonus.long_attack_def_rate ) / 100; if (cardfix != 10000) - bccDAMAGE_RATE(cardfix) + damage = damage * cardfix / 1000; } break; } @@ -747,13 +746,13 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag sd=(struct map_session_data *)bl; //Special no damage states if(flag&BF_WEAPON && sd->special_state.no_weapon_damage) - DAMAGE_SUBRATE(sd->special_state.no_weapon_damage) + damage -= damage * sd->special_state.no_weapon_damage / 100; if(flag&BF_MAGIC && sd->special_state.no_magic_damage) - DAMAGE_SUBRATE(sd->special_state.no_magic_damage) + damage -= damage * sd->special_state.no_magic_damage / 100; if(flag&BF_MISC && sd->special_state.no_misc_damage) - DAMAGE_SUBRATE(sd->special_state.no_misc_damage) + damage -= damage * sd->special_state.no_misc_damage / 100; if(!damage) return 0; } @@ -778,7 +777,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if( skill_id == MG_NAPALMBEAT || skill_id == MG_SOULSTRIKE || skill_id == WL_SOULEXPANSION || - (skill_id && skill_get_ele(skill_id, skill_lv) == ELE_GHOST) || + (skill_id && skill->get_ele(skill_id, skill_lv) == ELE_GHOST) || (!skill_id && (status_get_status_data(src))->rhw.ele == ELE_GHOST) ){ if( skill_id == WL_SOULEXPANSION ) @@ -798,12 +797,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if( sc->data[SC_SAFETYWALL] && (flag&(BF_SHORT|BF_MAGIC))==BF_SHORT ) { - struct skill_unit_group* group = skill_id2group(sc->data[SC_SAFETYWALL]->val3); + struct skill_unit_group* group = skill->id2group(sc->data[SC_SAFETYWALL]->val3); uint16 skill_id = sc->data[SC_SAFETYWALL]->val2; if (group) { if(skill_id == MH_STEINWAND){ if (--group->val2<=0) - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); d->dmg_lv = ATK_BLOCK; return 0; } @@ -811,16 +810,15 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag * in RE, SW possesses a lifetime equal to 3 times the caster's health **/ #ifdef RENEWAL + d->dmg_lv = ATK_BLOCK; if ( ( group->val2 - damage) > 0 ) { group->val2 -= damage; - d->dmg_lv = ATK_BLOCK; - return 0; } else - damage -= group->val2; - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); + return 0; #else if (--group->val2<=0) - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); d->dmg_lv = ATK_BLOCK; return 0; #endif @@ -834,15 +832,15 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag } if( sc->data[SC_WEAPONBLOCKING] && flag&(BF_SHORT|BF_WEAPON) && rnd()%100 < sc->data[SC_WEAPONBLOCKING]->val2 ) { - clif_skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1); + clif->skill_nodamage(bl,src,GC_WEAPONBLOCKING,1,1); d->dmg_lv = ATK_BLOCK; sc_start2(bl,SC_COMBO,100,GC_WEAPONBLOCKING,src->id,2000); return 0; } - if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill_get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 ) + if( (sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2 ) { int delay; - clif_skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); + clif->skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1); // different delay depending on skill level [celest] if (sce->val1 <= 5) delay = 300; @@ -853,20 +851,20 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag unit_set_walkdelay(bl, gettick(), delay, 1); if(sc->data[SC_SHRINK] && rnd()%100<5*sce->val1) - skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1),-1,0); + skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0); return 0; } if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) { - clif_skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); + clif->skill_nodamage(bl, bl, RK_MILLENNIUMSHIELD, 1, 1); sce->val3 -= damage; // absorb damage d->dmg_lv = ATK_BLOCK; - sc_start(bl,SC_STUN,15,0,skill_get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. + sc_start(bl,SC_STUN,15,0,skill->get_time2(RK_MILLENNIUMSHIELD,sce->val1)); // There is a chance to be stuned when one shield is broken. if( sce->val3 <= 0 ) { // Shield Down sce->val2--; if( sce->val2 > 0 ) { if( sd ) - clif_millenniumshield(sd,sce->val2); + clif->millenniumshield(sd,sce->val2); sce->val3 = 1000; // Next Shield } else status_change_end(bl,SC_MILLENNIUMSHIELD,INVALID_TIMER); // All shields down @@ -877,7 +875,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_id != WS_CARTTERMINATION && rnd()%100 < sce->val2 ) { // attack blocked by Parrying - clif_skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); + clif->skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); return 0; } @@ -885,7 +883,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag (flag&BF_LONG || sc->data[SC_SPURT]) && rnd()%100 < 20) { if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge. - clif_skill_nodamage(bl,bl,TK_DODGE,1,1); + clif->skill_nodamage(bl,bl,TK_DODGE,1,1); if (!sc->data[SC_COMBO]) sc_start4(bl, SC_COMBO, 100, TK_JUMPKICK, src->id, 1, 0, 2000); return 0; @@ -904,7 +902,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2) { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries. - clif_specialeffect(bl, 462, AREA); + clif->specialeffect(bl, 462, AREA); //Shouldn't end until Breaker's non-weapon part connects. if (skill_id != ASC_BREAKER || !(flag&BF_WEAPON)) if (--(sce->val3) <= 0) //We make it work like Safety Wall, even though it only blocks 1 time. @@ -913,19 +911,19 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag } if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rnd()%100 < sce->val2) { - clif_specialeffect(bl, 462, AREA); // Still need confirm it. + clif->specialeffect(bl, 462, AREA); // Still need confirm it. return 0; } if (((sce=sc->data[SC_UTSUSEMI]) || sc->data[SC_BUNSINJYUTSU]) - && flag&BF_WEAPON && !(skill_get_nk(skill_id)&NK_NO_CARDFIX_ATK)) { + && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK)) { - skill_additional_effect (src, bl, skill_id, skill_lv, flag, ATK_BLOCK, gettick() ); + skill->additional_effect (src, bl, skill_id, skill_lv, flag, ATK_BLOCK, gettick() ); if( !status_isdead(src) ) - skill_counter_additional_effect( src, bl, skill_id, skill_lv, flag, gettick() ); + skill->counter_additional_effect( src, bl, skill_id, skill_lv, flag, gettick() ); if (sce) { - clif_specialeffect(bl, 462, AREA); - skill_blown(src,bl,sce->val3,-1,0); + clif->specialeffect(bl, 462, AREA); + skill->blown(src,bl,sce->val3,-1,0); } //Both need to be consumed if they are active. if (sce && --(sce->val2) <= 0) @@ -947,9 +945,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag } #ifdef RENEWAL - if( sc->data[SC_RAID] ) - { - DAMAGE_ADDRATE(20) + if( sc->data[SC_RAID] ) { + damage += damage * 20 / 100; if (--sc->data[SC_RAID]->val1 == 0) status_change_end(bl, SC_RAID, INVALID_TIMER); @@ -968,7 +965,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag case W_2HMACE: case W_1HAXE: case W_2HAXE: - DAMAGE_RATE(150) + damage = damage * 150/100; break; case W_MUSICAL: case W_WHIP: @@ -983,7 +980,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag case W_DAGGER: case W_1HSWORD: case W_2HSWORD: - DAMAGE_RATE(50) + damage = damage * 50/100; break; } } @@ -991,13 +988,12 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag status_change_end(bl,SC_VOICEOFSIREN,INVALID_TIMER); } - //Finally damage reductions.... // Assumptio doubles the def & mdef on RE mode, otherwise gives a reduction on the final damage. [Igniz] #ifndef RENEWAL if( sc->data[SC_ASSUMPTIO] ) { if( map_flag_vs(bl->m) ) - damage = (int64)damage*2/3; //Receive 66% damage + damage = damage*2/3; //Receive 66% damage else damage >>= 1; //Receive 50% damage } @@ -1005,15 +1001,15 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if(sc->data[SC_DEFENDER] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - DAMAGE_RATE(100-sc->data[SC_DEFENDER]->val2) + damage = damage * ( 100 - sc->data[SC_DEFENDER]->val2 ) / 100; if(sc->data[SC_ADJUSTMENT] && (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) - DAMAGE_SUBRATE(20) + damage -= damage * 20 / 100; if(sc->data[SC_FOGWALL] && skill_id != RK_DRAGONBREATH) { if(flag&BF_SKILL) //25% reduction - DAMAGE_SUBRATE(25) + damage -= damage * 25 / 100; else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) damage >>= 2; //75% reduction } @@ -1024,25 +1020,25 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if (sc->data[SC_MANU_DEF]) for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) if (mob_manuk[i]==((TBL_MOB*)src)->class_) { - DAMAGE_SUBRATE(sc->data[SC_MANU_DEF]->val1) + damage -= damage * sc->data[SC_MANU_DEF]->val1 / 100; break; } if (sc->data[SC_SPL_DEF]) for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) if (mob_splendide[i]==((TBL_MOB*)src)->class_) { - DAMAGE_SUBRATE(sc->data[SC_SPL_DEF]->val1) + damage -= damage * sc->data[SC_SPL_DEF]->val1 / 100; break; } } if((sce=sc->data[SC_ARMOR]) && //NPC_DEFENDER sce->val3&flag && sce->val4&flag) - DAMAGE_SUBRATE(sc->data[SC_ARMOR]->val2) + damage -= damage * sc->data[SC_ARMOR]->val2 / 100; #ifdef RENEWAL if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON || flag&BF_MAGIC) && skill_id != WS_CARTTERMINATION) #else - if(sc->data[SC_ENERGYCOAT] && flag&BF_WEAPON && skill_id != WS_CARTTERMINATION) + if(sc->data[SC_ENERGYCOAT] && (flag&BF_WEAPON && skill_id != WS_CARTTERMINATION)) #endif { struct status_data *status = status_get_status_data(bl); @@ -1052,16 +1048,31 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); //Reduction: 6% + 6% every 20% - DAMAGE_SUBRATE(6 * (1+per)) + damage -= damage * (6 * (1+per)) / 100; } if(sc->data[SC_GRANITIC_ARMOR]){ - DAMAGE_SUBRATE(sc->data[SC_GRANITIC_ARMOR]->val2) + damage -= damage * sc->data[SC_GRANITIC_ARMOR]->val2 / 100; } if(sc->data[SC_PAIN_KILLER]){ - DAMAGE_SUBRATE(sc->data[SC_PAIN_KILLER]->val3) + damage -= damage * sc->data[SC_PAIN_KILLER]->val3 / 100; } if((sce=sc->data[SC_MAGMA_FLOW]) && (rnd()%100 <= sce->val2) ){ - skill_castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0); + skill->castend_damage_id(bl,src,MH_MAGMA_FLOW,sce->val1,gettick(),0); + } + + if( (sce = sc->data[SC_STONEHARDSKIN]) && flag&BF_WEAPON && damage > 0 ) { + sce->val2 -= damage; + if( src->type == BL_PC ) { + TBL_PC *ssd = BL_CAST(BL_PC, src); + if (ssd && ssd->status.weapon != W_BOW) + skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); + } else + skill->break_equip(src, EQP_WEAPON, 3000, BCT_SELF); + // 30% chance to reduce monster's ATK by 25% for 10 seconds. + if( src->type == BL_MOB ) + sc_start(src, SC_STRIPWEAPON, 30, 0, skill->get_time2(RK_STONEHARDSKIN, sce->val1)); + if( sce->val2 <= 0 ) + status_change_end(bl, SC_STONEHARDSKIN, INVALID_TIMER); } /** @@ -1105,7 +1116,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag int dy[8]={1,1,0,-1,-1,-1,0,1}; uint8 dir = map_calc_dir(bl, src->x, src->y); if( unit_movepos(bl, src->x-dx[dir], src->y-dy[dir], 1, 1) ) { - clif_slide(bl,src->x-dx[dir],src->y-dy[dir]); + clif->slide(bl,src->x-dx[dir],src->y-dy[dir]); unit_setdir(bl, dir); } d->dmg_lv = ATK_DEF; @@ -1117,13 +1128,13 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag //(since battle_drain is strictly for players currently) if ((sce=sc->data[SC_BLOODLUST]) && flag&BF_WEAPON && damage > 0 && rnd()%100 < sce->val3) - status_heal(src, (int64)damage*sce->val4/100, 0, 3); + status_heal(src, damage*sce->val4/100, 0, 3); if( sd && (sce = sc->data[SC_FORCEOFVANGUARD]) && flag&BF_WEAPON && rnd()%100 < sce->val2 ) - pc_addspiritball(sd,skill_get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); + pc_addspiritball(sd,skill->get_time(LG_FORCEOFVANGUARD,sce->val1),sce->val3); if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); - if (hd) hom_addspiritball(hd, 10); //add a sphere + if (hd) homun->addspiritball(hd, 10); //add a sphere } if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) @@ -1131,9 +1142,9 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if( sc && sc->data[SC__SHADOWFORM] ) { struct block_list *s_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2); - if( !s_bl ) { // If the shadow form target is not present remove the sc. + if( !s_bl || s_bl->m != bl->m ) { // If the shadow form target is not present remove the sc. status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - } else if( status_isdead(s_bl) || !battle_check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both. + } else if( status_isdead(s_bl) || !battle->check_target(src,s_bl,BCT_ENEMY)) { // If the shadow form target is dead or not your enemy remove the sc in both. status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); if( s_bl->type == BL_PC ) ((TBL_PC*)s_bl)->shadowform_id = 0; @@ -1143,7 +1154,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag if( s_bl->type == BL_PC ) ((TBL_PC*)s_bl)->shadowform_id = 0; } else { - status_damage(bl, s_bl, damage, 0, clif_damage(s_bl, s_bl, gettick(), 500, 500, damage, -1, 0, 0), 0); + status_damage(bl, s_bl, damage, 0, clif->damage(s_bl, s_bl, gettick(), 500, 500, damage, -1, 0, 0), 0); return ATK_NONE; } } @@ -1154,13 +1165,11 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag //SC effects from caster side. sc = status_get_sc(src); - if (sc && sc->count) - { + if (sc && sc->count) { if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) - DAMAGE_ADDRATE(75) + damage += damage * 75 / 100; // [Epoque] - if (bl->type == BL_MOB) - { + if (bl->type == BL_MOB) { int i; if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || @@ -1168,7 +1177,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag ) for (i=0;ARRAYLENGTH(mob_manuk)>i;i++) if (((TBL_MOB*)bl)->class_==mob_manuk[i]) { - DAMAGE_ADDRATE(sce->val1) + damage += damage * sce->val1 / 100; break; } if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || @@ -1176,36 +1185,44 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag ) for (i=0;ARRAYLENGTH(mob_splendide)>i;i++) if (((TBL_MOB*)bl)->class_==mob_splendide[i]) { - DAMAGE_ADDRATE(sce->val1) + damage += damage * sce->val1 / 100; break; } } if( sc->data[SC_POISONINGWEAPON] && skill_id != GC_VENOMPRESSURE && (flag&BF_WEAPON) && damage > 0 && rnd()%100 < sc->data[SC_POISONINGWEAPON]->val3 ) - sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); + sc_start(bl,sc->data[SC_POISONINGWEAPON]->val2,100,sc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1)); if( sc->data[SC__DEADLYINFECT] && damage > 0 && rnd()%100 < 65 + 5 * sc->data[SC__DEADLYINFECT]->val1 ) status_change_spread(src, bl); if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); - if (hd) hom_addspiritball(hd, 10); + if (hd) homun->addspiritball(hd, 10); } } - - if (battle_config.pk_mode && sd && bl->type == BL_PC && damage && map[bl->m].flag.pvp) - { - if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] - if (flag&BF_WEAPON) - DAMAGE_RATE(battle_config.pk_weapon_damage_rate) - if (flag&BF_MAGIC) - DAMAGE_RATE(battle_config.pk_magic_damage_rate) - if (flag&BF_MISC) - DAMAGE_RATE(battle_config.pk_misc_damage_rate) - } else { //Normal attacks get reductions based on range. - if (flag & BF_SHORT) - DAMAGE_RATE(battle_config.pk_short_damage_rate) - if (flag & BF_LONG) - DAMAGE_RATE(battle_config.pk_long_damage_rate) - } - if(!damage) damage = 1; + /* no data claims these settings affect anything other than players */ + if( damage && sd && bl->type == BL_PC ) { + switch( skill_id ) { + //case PA_PRESSURE: /* pressure also belongs to this list but it doesn't reach this area -- so dont worry about it */ + case HW_GRAVITATION: + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + break; + default: + if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] + if (flag&BF_WEAPON) + damage = damage * map[bl->m].weapon_damage_rate / 100; + if (flag&BF_MAGIC) + damage = damage * map[bl->m].magic_damage_rate / 100; + if (flag&BF_MISC) + damage = damage * map[bl->m].misc_damage_rate / 100; + } else { //Normal attacks get reductions based on range. + if (flag & BF_SHORT) + damage = damage * map[bl->m].short_damage_rate / 100; + if (flag & BF_LONG) + damage = damage * map[bl->m].long_damage_rate / 100; + } + if(!damage) damage = 1; + break; + } } if(battle_config.skill_min_damage && damage > 0 && damage < div_) @@ -1225,7 +1242,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damag } if( sd ) { if( pc_ismadogear(sd) && rnd()%100 < 50 ) { - short element = skill_get_ele(skill_id, skill_lv); + short element = skill->get_ele(skill_id, skill_lv); if( !skill_id || element == -1 ) { //Take weapon's element struct status_data *sstatus = NULL; if( src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele ) @@ -1254,41 +1271,13 @@ int battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int dam if( !damage ) return 0; - if( bl->type == BL_MOB ) - { + if( bl->type == BL_MOB ) { struct mob_data* md = BL_CAST(BL_MOB, bl); - if( map[bl->m].flag.battleground && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) && flag&BF_SKILL ) + + if( flag&BF_SKILL && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) ) return 0; // Crystal cannot receive skill damage on battlegrounds } - switch( skill_id ) - { - case PA_PRESSURE: - case HW_GRAVITATION: - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - break; - default: - if( flag&BF_SKILL ) - { //Skills get a different reduction than non-skills. [Skotlex] - if( flag&BF_WEAPON ) - DAMAGE_RATE(battle_config.bg_weapon_damage_rate) - if( flag&BF_MAGIC ) - DAMAGE_RATE(battle_config.bg_magic_damage_rate) - if( flag&BF_MISC ) - DAMAGE_RATE(battle_config.bg_misc_damage_rate) - } - else - { //Normal attacks get reductions based on range. - if( flag&BF_SHORT ) - DAMAGE_RATE(battle_config.bg_short_damage_rate) - if( flag&BF_LONG ) - DAMAGE_RATE(battle_config.bg_long_damage_rate) - } - - if( !damage ) damage = 1; - } - return damage; } @@ -1317,56 +1306,42 @@ int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int dama } } if(src->type != BL_MOB) { - struct guild *g = guild_search(status_get_guild_id(src)); + struct guild *g = src->type == BL_PC ? ((TBL_PC *)src)->guild : guild->search(status_get_guild_id(src)); - if (class_ == MOBID_EMPERIUM && (!g || guild_checkskill(g,GD_APPROVAL) <= 0 )) + if (class_ == MOBID_EMPERIUM && (!g || guild->checkskill(g,GD_APPROVAL) <= 0 )) return 0; - if (g && battle_config.guild_max_castles && guild_checkcastles(g)>=battle_config.guild_max_castles) + if (g && battle_config.guild_max_castles && guild->checkcastles(g)>=battle_config.guild_max_castles) return 0; // [MouseJstr] } } switch (skill_id) { - //Skills with no damage reduction. - case PA_PRESSURE: - case HW_GRAVITATION: - case NJ_ZENYNAGE: - case KO_MUCHANAGE: - break; - default: - /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka] - if (md && md->guardian_data) { - damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; - } - */ - if (flag & BF_SKILL) { //Skills get a different reduction than non-skills. [Skotlex] - if (flag&BF_WEAPON) - DAMAGE_RATE(battle_config.gvg_weapon_damage_rate) - if (flag&BF_MAGIC) - DAMAGE_RATE(battle_config.gvg_magic_damage_rate) - if (flag&BF_MISC) - DAMAGE_RATE(battle_config.gvg_misc_damage_rate) - } else { //Normal attacks get reductions based on range. - if (flag & BF_SHORT) - DAMAGE_RATE(battle_config.gvg_short_damage_rate) - if (flag & BF_LONG) - DAMAGE_RATE(battle_config.gvg_long_damage_rate) - } - if(!damage) damage = 1; + case PA_PRESSURE: + case HW_GRAVITATION: + case NJ_ZENYNAGE: + case KO_MUCHANAGE: + break; + default: + /* Uncomment if you want god-mode Emperiums at 100 defense. [Kisuka] + if (md && md->guardian_data) { + damage -= damage * (md->guardian_data->castle->defense/100) * battle_config.castle_defense_rate/100; + } + */ + break; } + return damage; } /*========================================== * HP/SP drain calculation *------------------------------------------*/ -static int battle_calc_drain(int damage, int rate, int per) -{ +int battle_calc_drain(int damage, int rate, int per) { int diff = 0; if (per && rnd()%1000 < rate) { - diff = ((int64)damage * per) / 100; + diff = (damage * per) / 100; if (diff == 0) { if (per > 0) diff = 1; @@ -1380,8 +1355,7 @@ static int battle_calc_drain(int damage, int rate, int per) /*========================================== * Passif skill dammages increases *------------------------------------------*/ -int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type) -{ +int battle_addmastery(struct map_session_data *sd,struct block_list *target,int dmg,int type) { int damage,skill; struct status_data *status = status_get_status_data(target); int weapon; @@ -1391,7 +1365,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int if((skill = pc_checkskill(sd,AL_DEMONBANE)) > 0 && target->type == BL_MOB && //This bonus doesnt work against players. - (battle_check_undead(status->race,status->def_ele) || status->race==RC_DEMON) ) + (battle->check_undead(status->race,status->def_ele) || status->race==RC_DEMON) ) damage += (skill*(int)(3+(sd->status.base_level+1)*0.05)); // submitted by orn //damage += (skill * 3); if( (skill = pc_checkskill(sd, RA_RANGERMAIN)) > 0 && (status->race == RC_BRUTE || status->race == RC_PLANT || status->race == RC_FISH) ) @@ -1495,8 +1469,7 @@ int battle_addmastery(struct map_session_data *sd,struct block_list *target,int * &8: Skip target size adjustment (Extremity Fist?) *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) */ -static int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) -{ +int battle_calc_base_damage(struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) { unsigned int atkmin=0, atkmax=0; short type = 0; int damage = 0; @@ -1553,9 +1526,7 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk //SizeFix only for players if (!(sd->special_state.no_sizefix || (flag&8))) - DAMAGE_RATE(type==EQI_HAND_L? - sd->left_weapon.atkmods[t_size]: - sd->right_weapon.atkmods[t_size]) + damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[t_size] : sd->right_weapon.atkmods[t_size] ) / 100; } //Finally, add baseatk @@ -1571,12 +1542,12 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk if(sd->left_weapon.overrefine) damage += rnd()%sd->left_weapon.overrefine+1; if (sd->weapon_atk_rate[sd->weapontype2]) - DAMAGE_ADDRATE(sd->weapon_atk_rate[sd->weapontype2]) + damage += damage * sd->weapon_atk_rate[sd->weapontype2] / 100; } else { //Right hand if(sd->right_weapon.overrefine) damage += rnd()%sd->right_weapon.overrefine+1; if (sd->weapon_atk_rate[sd->weapontype1]) - DAMAGE_ADDRATE(sd->weapon_atk_rate[sd->weapontype1]) + damage += damage * sd->weapon_atk_rate[sd->weapontype1] / 100; } } return damage; @@ -1585,14 +1556,13 @@ static int battle_calc_base_damage(struct status_data *status, struct weapon_atk /*========================================== * Consumes ammo for the given skill. *------------------------------------------*/ -void battle_consume_ammo(TBL_PC*sd, int skill, int lv) -{ +void battle_consume_ammo(TBL_PC*sd, int skill_id, int lv) { int qty=1; if (!battle_config.arrow_decrement) return; if (skill) { - qty = skill_get_ammo_qty(skill, lv); + qty = skill->get_ammo_qty(skill_id, lv); if (!qty) qty = 1; } @@ -1601,11 +1571,8 @@ void battle_consume_ammo(TBL_PC*sd, int skill, int lv) sd->state.arrow_atk = 0; } - -static int battle_range_type( - struct block_list *src, struct block_list *target, - uint16 skill_id, uint16 skill_lv) -{ //Skill Range Criteria +//Skill Range Criteria +int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv) { if (battle_config.skillrange_by_distance && (src->type&battle_config.skillrange_by_distance) ) { //based on distance between src/target [Skotlex] @@ -1614,13 +1581,25 @@ static int battle_range_type( return BF_LONG; } //based on used skill's range - if (skill_get_range2(src, skill_id, skill_lv) < 5) + if (skill->get_range2(src, skill_id, skill_lv) < 5) return BF_SHORT; return BF_LONG; } +int battle_adjust_skill_damage(int m, unsigned short skill_id) { -static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) -{ + if( map[m].skill_count ) { + int i; + ARR_FIND(0, map[m].skill_count, i, map[m].skills[i]->skill_id == skill_id ); + + if( i < map[m].skill_count ) { + return map[m].skills[i]->modifier; + } + + } + + return 0; +} +int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { int i; if (!sd->skillblown[0].id) return 0; @@ -1632,18 +1611,15 @@ static int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) return 0; } -struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); -struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); - //For quick div adjustment. #define damage_div_fix(dmg, div) { if (div > 1) (dmg)*=div; else if (div < 0) (div)*=-1; } /*========================================== * battle_calc_weapon_attack (by Skotlex) *------------------------------------------*/ -static struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag) +struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag) { unsigned int skillratio = 100; //Skill dmg modifiers. - short skill=0; + short temp=0; short s_ele, s_ele_, t_class; int i, nk; bool n_ele = false; // non-elemental @@ -1692,16 +1668,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo //Initial Values wd.type=0; //Normal attack - wd.div_=skill_id?skill_get_num(skill_id,skill_lv):1; - wd.amotion=(skill_id && skill_get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. + wd.div_=skill_id?skill->get_num(skill_id,skill_lv):1; + wd.amotion=(skill_id && skill->get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. if(skill_id == KN_AUTOCOUNTER) wd.amotion >>= 1; wd.dmotion=tstatus->dmotion; - wd.blewcount=skill_get_blewcount(skill_id,skill_lv); + wd.blewcount=skill->get_blewcount(skill_id,skill_lv); wd.flag = BF_WEAPON; //Initial Flag wd.flag |= (skill_id||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish] wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later - nk = skill_get_nk(skill_id); + nk = skill->get_nk(skill_id); if( !skill_id && wflag ) //If flag, this is splash damage from Baphomet Card and it always hits. nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE; flag.hit = nk&NK_IGNORE_FLEE?1:0; @@ -1716,19 +1692,18 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo tsd = BL_CAST(BL_PC, target); if(sd) - wd.blewcount += battle_blewcount_bonus(sd, skill_id); + wd.blewcount += battle->blewcount_bonus(sd, skill_id); //Set miscellaneous data that needs be filled regardless of hit/miss if( (sd && sd->state.arrow_atk) || - (!sd && ((skill_id && skill_get_ammotype(skill_id)) || sstatus->rhw.range>3)) + (!sd && ((skill_id && skill->get_ammotype(skill_id)) || sstatus->rhw.range>3)) ) flag.arrow = 1; - if(skill_id){ - wd.flag |= battle_range_type(src, target, skill_id, skill_lv); - switch(skill_id) - { + if(skill_id) { + wd.flag |= battle->range_type(src, target, skill_id, skill_lv); + switch(skill_id) { case MO_FINGEROFFENSIVE: if(sd) { if (battle_config.finger_offensive_type) @@ -1794,7 +1769,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } t_class = status_get_class(target); - s_ele = s_ele_ = skill_get_ele(skill_id, skill_lv); + s_ele = s_ele_ = skill->get_ele(skill_id, skill_lv); if( !skill_id || s_ele == -1 ) { //Take weapon's element s_ele = sstatus->rhw.ele; @@ -1848,16 +1823,16 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo { //Success chance is not added, the higher one is used [Skotlex] if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) { - wd.div_ = skill_get_num(TF_DOUBLE,skill_lv?skill_lv:1); + wd.div_ = skill->get_num(TF_DOUBLE,skill_lv?skill_lv:1); wd.type = 0x08; } } else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc_checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv ) { - wd.div_ = skill_get_num(GS_CHAINACTION,skill_lv); + wd.div_ = skill->get_num(GS_CHAINACTION,skill_lv); wd.type = 0x08; } - else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW + else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){ int chance = rand()%100; wd.type = 0x08; @@ -1933,10 +1908,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if (rnd()%1000 < cri) flag.cri = 1; } - if (flag.cri) - { + if (flag.cri) { wd.type = 0x0a; +#ifdef RENEWAL + flag.hit = 1; +#else flag.idef = flag.idef2 = flag.hit = 1; +#endif } else { //Check for Perfect Hit if(sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit) flag.hit = 1; @@ -2041,12 +2019,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if( sd ) { // Weaponry Research hidden bonus - if ((skill = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) - hitrate += hitrate * ( 2 * skill ) / 100; + if ((temp = pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) + hitrate += hitrate * ( 2 * temp ) / 100; if( (sd->status.weapon == W_1HSWORD || sd->status.weapon == W_DAGGER) && - (skill = pc_checkskill(sd, GN_TRAINING_SWORD))>0 ) - hitrate += 3 * skill; + (temp = pc_checkskill(sd, GN_TRAINING_SWORD))>0 ) + hitrate += 3 * temp; } hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate); @@ -2064,8 +2042,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo //ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc #define ATK_RATE( a ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(a)/100; } #define ATK_RATE2( a , b ) { wd.damage= wd.damage*(a)/100 ; if(flag.lh) wd.damage2= wd.damage2*(b)/100; } -#define ATK_RATER(a){ wd.damage = (int64)wd.damage*(a)/100;} -#define ATK_RATEL(a){ wd.damage2 = (int64)wd.damage2*(a)/100;} +#define ATK_RATER(a){ wd.damage = wd.damage*(a)/100;} +#define ATK_RATEL(a){ wd.damage2 = wd.damage2*(a)/100;} //Adds dmg%. 100 = +100% (double) damage. 10 = +10% damage #define ATK_ADDRATE( a ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(a)/100; } #define ATK_ADDRATE2( a , b ) { wd.damage+= wd.damage*(a)/100 ; if(flag.lh) wd.damage2+= wd.damage2*(b)/100; } @@ -2076,7 +2054,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo switch (skill_id) { //Calc base damage according to skill case PA_SACRIFICE: - wd.damage = (int64)sstatus->max_hp* 9/100; + wd.damage = sstatus->max_hp* 9/100; wd.damage2 = 0; break; #ifndef RENEWAL @@ -2150,15 +2128,15 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo default: i |= 16; // for ex. shuriken must not be influenced by DEX } - wd.damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); + wd.damage = battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, i); if (flag.lh) - wd.damage2 = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i); + wd.damage2 = battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, i); if (nk&NK_SPLASHSPLIT){ // Divide ATK among targets if(wflag>0) wd.damage/= wflag; else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id)); + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); } //Add any bonuses that modify the base baseatk+watk (pre-skills) @@ -2169,9 +2147,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if(flag.cri && sd->bonus.crit_atk_rate) ATK_ADDRATE(sd->bonus.crit_atk_rate); - if(sd->status.party_id && (skill=pc_checkskill(sd,TK_POWER)) > 0){ + if(sd->status.party_id && (temp=pc_checkskill(sd,TK_POWER)) > 0){ if( (i = party_foreachsamemap(party_sub_count, sd, 0)) > 1 ) // exclude the player himself [Inkfish] - ATK_ADDRATE(2*skill*i); + ATK_ADDRATE(2*temp*i); } } break; @@ -2787,11 +2765,11 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo break; case SR_TIGERCANNON:// ATK [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] % { - int hp = (int64)sstatus->max_hp * (10 + 2 * skill_lv) / 100, - sp = (int64)sstatus->max_sp * (6 + skill_lv) / 100; - skillratio = ((int64)hp+sp) / 4; + int hp = sstatus->max_hp * (10 + 2 * skill_lv) / 100, + sp = sstatus->max_sp * (6 + skill_lv) / 100; + skillratio = (hp+sp) / 4; if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE ) // ATK [((Caster consumed HP + SP) / 2) x Caster Base Level / 100] % - skillratio = (int64)hp+sp / 2; + skillratio = hp+sp / 2; RE_LVL_DMOD(100); } break; @@ -2853,7 +2831,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo skillratio += 800 + 100 * skill_lv; if( sd ) { // Still need official value [pakpil] short lv = (short)skill_lv; - skillratio += 100 * skill_check_pc_partner(sd,skill_id,&lv,skill_get_splash(skill_id,skill_lv),0); + skillratio += 100 * skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0); } break; case WM_SOUND_OF_DESTRUCTION: @@ -2955,7 +2933,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo skillratio += -100 + 100 * skill_lv; break; } - +#ifdef RENEWAL + if( sc && sc->data[SC_TRUESIGHT] ) + skillratio += 2*sc->data[SC_TRUESIGHT]->val1; +#endif ATK_RATE(skillratio); //Constant/misc additions from skills @@ -3008,9 +2989,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo case SR_GATEOFHELL: ATK_ADD (sstatus->max_hp - status_get_hp(src)); if(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == SR_FALLENEMPIRE){ - ATK_ADD ( ((int64)sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) ); + ATK_ADD ( (sstatus->max_sp * (1 + skill_lv * 2 / 10)) + 40 * status_get_lv(src) ); }else{ - ATK_ADD ( ((int64)sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) ); + ATK_ADD ( (sstatus->sp * (1 + skill_lv * 2 / 10)) + 10 * status_get_lv(src) ); } break; case SR_TIGERCANNON: // (Tiger Cannon skill level x 240) + (Target Base Level x 40) @@ -3050,8 +3031,10 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo //The following are applied on top of current damage and are stackable. if ( sc ) { +#ifndef RENEWAL if( sc->data[SC_TRUESIGHT] ) ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1); +#endif if( sc->data[SC_GLOOMYDAY_SK] && ( skill_id == LK_SPIRALPIERCE || skill_id == KN_BRANDISHSPEAR || skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN || @@ -3060,7 +3043,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if( sc->data[SC_EDP] ){ switch(skill_id){ case AS_SPLASHER: case AS_VENOMKNIFE: +#ifndef RENEWAL_EDP case AS_GRIMTOOTH: +#endif break; #ifndef RENEWAL_EDP case ASC_BREAKER: case ASC_METEORASSAULT: break; @@ -3101,11 +3086,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo break; } - if( sd ) - { + if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) + ATK_RATE(i); + + if( sd ) { if (skill_id && (i = pc_skillatk_bonus(sd, skill_id))) ATK_ADDRATE(i); - + if( skill_id != PA_SACRIFICE && skill_id != MO_INVESTIGATE && skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS && skill_id != PA_SHIELDCHAIN && !flag.cri ) { //Elemental/Racial adjustments if( sd->right_weapon.def_ratio_atk_ele & (1<<tstatus->def_ele) || @@ -3211,14 +3198,14 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo #else vit_def = def2; #endif - if((battle_check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players - src->type == BL_MOB && (skill=pc_checkskill(tsd,AL_DP)) > 0) - vit_def += skill*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn - if( src->type == BL_MOB && (skill=pc_checkskill(tsd,RA_RANGERMAIN))>0 && + if((battle->check_undead(sstatus->race,sstatus->def_ele) || sstatus->race==RC_DEMON) && //This bonus already doesnt work vs players + src->type == BL_MOB && (temp=pc_checkskill(tsd,AL_DP)) > 0) + vit_def += temp*(int)(3 +(tsd->status.base_level+1)*0.04); // submitted by orn + if( src->type == BL_MOB && (temp=pc_checkskill(tsd,RA_RANGERMAIN))>0 && (sstatus->race == RC_BRUTE || sstatus->race == RC_FISH || sstatus->race == RC_PLANT) ) - vit_def += skill*5; + vit_def += temp*5; #ifdef RENEWAL - if( skill == NJ_ISSEN ){//TODO: do better implementation if other skills(same func) are found [malufett] + if( temp == NJ_ISSEN ){//TODO: do better implementation if other skills(same func) are found [malufett] vit_def += def1; def1 = 0; } @@ -3246,6 +3233,9 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo * Pierce defence gains 1 atk per def/2 **/ + if( def1 == -400 ) /* being hit by a gazillion units, you hit the jackpot and got -400 which creates a division by 0 and subsequently crashes */ + def1 = -399; + ATK_ADD2( flag.pdef ?(def1/2):0, flag.pdef2?(def1/2):0 @@ -3258,8 +3248,8 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo #else if (def1 > 100) def1 = 100; ATK_RATE2( - flag.idef ?100:(flag.pdef ? (int64)flag.pdef*(def1+vit_def) : (100-def1)), - flag.idef2?100:(flag.pdef2? (int64)flag.pdef2*(def1+vit_def) : (100-def1)) + flag.idef ?100:(flag.pdef ? flag.pdef*(def1+vit_def) : (100-def1)), + flag.idef2?100:(flag.pdef2? flag.pdef2*(def1+vit_def) : (100-def1)) ); ATK_ADD2( flag.idef ||flag.pdef ?0:-vit_def, @@ -3317,38 +3307,37 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo skill_id != CR_GRANDCROSS) { //Add mastery damage if(skill_id != ASC_BREAKER && sd->status.weapon == W_KATAR && - (skill=pc_checkskill(sd,ASC_KATAR)) > 0) + (temp=pc_checkskill(sd,ASC_KATAR)) > 0) { //Adv Katar Mastery is does not applies to ASC_BREAKER, // but other masteries DO apply >_> - ATK_ADDRATE(10+ 2*skill); + ATK_ADDRATE(10+ 2*temp); } - wd.damage = battle_addmastery(sd,target,wd.damage,0); + wd.damage = battle->add_mastery(sd,target,wd.damage,0); if (flag.lh) - wd.damage2 = battle_addmastery(sd,target,wd.damage2,1); + wd.damage2 = battle->add_mastery(sd,target,wd.damage2,1); if (sc && sc->data[SC_MIRACLE]) i = 2; //Star anger else ARR_FIND(0, MAX_PC_FEELHATE, i, t_class == sd->hate_mob[i]); - if (i < MAX_PC_FEELHATE && (skill=pc_checkskill(sd,sg_info[i].anger_id))) - { + if (i < MAX_PC_FEELHATE && (temp=pc_checkskill(sd,sg_info[i].anger_id))) { skillratio = sd->status.base_level + sstatus->dex + sstatus->luk; if (i == 2) skillratio += sstatus->str; //Star Anger - if (skill<4) - skillratio /= 12-3*skill; + if (temp<4) + skillratio /= 12-3*temp; ATK_ADDRATE(skillratio); } - if (skill_id == NJ_SYURIKEN && (skill = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) - ATK_ADD(3*skill); - if (skill_id == NJ_KUNAI) + if (skill_id == NJ_SYURIKEN && (temp = pc_checkskill(sd,NJ_TOBIDOUGU)) > 0) { + ATK_ADD(3*temp); + } else if (skill_id == NJ_KUNAI) ATK_ADD(60); } } //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks else if(wd.div_ < 0) //Since the attack missed... wd.div_ *= -1; - if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) - ATK_ADD(skill*2); + if(sd && (temp=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) + ATK_ADD(temp*2); if(skill_id==TF_POISON) ATK_ADD(15*skill_lv); @@ -3357,23 +3346,22 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo { //Elemental attribute fix if( wd.damage > 0 ) { - wd.damage=battle_attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv); + wd.damage=battle->attr_fix(src,target,wd.damage,s_ele,tstatus->def_ele, tstatus->ele_lv); if( skill_id == MC_CARTREVOLUTION ) //Cart Revolution applies the element fix once more with neutral element - wd.damage = battle_attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); + wd.damage = battle->attr_fix(src,target,wd.damage,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); if( skill_id== GS_GROUNDDRIFT ) //Additional 50*lv Neutral damage. - wd.damage += battle_attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); + wd.damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv); } if( flag.lh && wd.damage2 > 0 ) - wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); + wd.damage2 = battle->attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); if( sc && sc->data[SC_WATK_ELEMENT] ) { // Descriptions indicate this means adding a percent of a normal attack in another element. [Skotlex] - int damage = battle_calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; - wd.damage += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); + int damage = battle->calc_base_damage(sstatus, &sstatus->rhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; + wd.damage += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); - if( flag.lh ) - { - damage = battle_calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; - wd.damage2 += battle_attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); + if( flag.lh ) { + damage = battle->calc_base_damage(sstatus, &sstatus->lhw, sc, tstatus->size, sd, (flag.arrow?2:0)) * sc->data[SC_WATK_ELEMENT]->val2 / 100; + wd.damage2 += battle->attr_fix(src, target, damage, sc->data[SC_WATK_ELEMENT]->val1, tstatus->def_ele, tstatus->ele_lv); } } #ifdef RENEWAL @@ -3388,9 +3376,26 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) return wd; //Enough, rest is not needed. - - if (sd) - { +#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE + if( target && skill_id ) { + for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { + if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) { + if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { + if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) ) + continue; + if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) + continue; + } + if( wd.damage > map[target->m].zone->capped_skills[i]->cap ) + wd.damage = map[target->m].zone->capped_skills[i]->cap; + if( wd.damage2 > map[target->m].zone->capped_skills[i]->cap ) + wd.damage2 = map[target->m].zone->capped_skills[i]->cap; + break; + } + } + } +#endif + if (sd) { if (skill_id != CR_SHIELDBOOMERANG) //Only Shield boomerang doesn't takes the Star Crumbs bonus. ATK_ADD2(wd.div_*sd->right_weapon.star, wd.div_*sd->left_weapon.star); if (skill_id==MO_FINGEROFFENSIVE) { //The finger offensive spheres on moment of attack do count. [Skotlex] @@ -3400,24 +3405,26 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo } //Card Fix, sd side - wd.damage = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag); + wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag); if( flag.lh ) - wd.damage2 = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag); - + wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag); +#ifdef RENEWAL + if( flag.cri ) + ATK_ADDRATE(sd->bonus.crit_atk_rate>=100?sd->bonus.crit_atk_rate-60:40); +#endif if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN ) { //Refine bonus applies after cards and elements. short index= sd->equip_index[EQI_HAND_L]; if( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) ATK_ADD(10*sd->status.inventory[index].refine); } - } //if (sd) + } //Card Fix, tsd side - if(tsd) - wd.damage = battle_calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, flag.lh, wd.flag); + if(tsd) //if player on player then it was already measured above + wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, flag.lh, wd.flag); - if( flag.infdef ) - { //Plants receive 1 damage when hit + if( flag.infdef ) { //Plants receive 1 damage when hit short class_ = status_get_class(target); if( flag.hit || wd.damage > 0 ) wd.damage = wd.div_; // In some cases, right hand no need to have a weapon to increase damage @@ -3425,12 +3432,12 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo wd.damage2 = wd.div_; if( flag.hit && class_ == MOBID_EMPERIUM ) { if(wd.damage2 > 0) { - wd.damage2 = battle_attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); - wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage2 = battle->attr_fix(src,target,wd.damage2,s_ele_,tstatus->def_ele, tstatus->ele_lv); + wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); } else if(wd.damage > 0) { - wd.damage = battle_attr_fix(src,target,wd.damage,s_ele_,tstatus->def_ele, tstatus->ele_lv); - wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage = battle->attr_fix(src,target,wd.damage,s_ele_,tstatus->def_ele, tstatus->ele_lv); + wd.damage = battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); } return wd; } @@ -3447,22 +3454,22 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo flag.lh=0; } else if(flag.rh && flag.lh) { //Dual-wield if (wd.damage) { - if( (skill = pc_checkskill(sd,AS_RIGHT)) ) - ATK_RATER(50 + (skill * 10)) - else if( (skill = pc_checkskill(sd,KO_RIGHT)) ) - ATK_RATER(70 + (skill * 10)) + if( (temp = pc_checkskill(sd,AS_RIGHT)) ) + ATK_RATER(50 + (temp * 10)) + else if( (temp = pc_checkskill(sd,KO_RIGHT)) ) + ATK_RATER(70 + (temp * 10)) if(wd.damage < 1) wd.damage = 1; } if (wd.damage2) { - if( (skill = pc_checkskill(sd,AS_LEFT)) ) - ATK_RATEL(30 + (skill * 10)) - else if( (skill = pc_checkskill(sd,KO_LEFT)) ) - ATK_RATEL(50 + (skill * 10)) + if( (temp = pc_checkskill(sd,AS_LEFT)) ) + ATK_RATEL(30 + (temp * 10)) + else if( (temp = pc_checkskill(sd,KO_LEFT)) ) + ATK_RATEL(50 + (temp * 10)) if(wd.damage2 < 1) wd.damage2 = 1; } } else if(sd->status.weapon == W_KATAR && !skill_id) { //Katars (offhand damage only applies to normal attacks, tested on Aegis 10.2) - skill = pc_checkskill(sd,TF_DOUBLE); - wd.damage2 = (int64)wd.damage * (1 + (skill * 2))/100; + temp = pc_checkskill(sd,TF_DOUBLE); + wd.damage2 = wd.damage * (1 + (temp * 2))/100; if(wd.damage && !wd.damage2) wd.damage2 = 1; flag.lh = 1; @@ -3479,29 +3486,29 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo { //There is a total damage value if(!wd.damage2) { - wd.damage = battle_calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); + wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); if( map_flag_gvg2(target->m) ) - wd.damage=battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage=battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); else if( map[target->m].flag.battleground ) - wd.damage=battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage=battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); } else if(!wd.damage) { - wd.damage2 = battle_calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); + wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); if( map_flag_gvg2(target->m) ) - wd.damage2 = battle_calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); else if( map[target->m].flag.battleground ) - wd.damage = battle_calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage = battle->calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); } else { int d1 = wd.damage + wd.damage2,d2 = wd.damage2; - wd.damage = battle_calc_damage(src,target,&wd,d1,skill_id,skill_lv); + wd.damage = battle->calc_damage(src,target,&wd,d1,skill_id,skill_lv); if( map_flag_gvg2(target->m) ) - wd.damage = battle_calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage = battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); else if( map[target->m].flag.battleground ) - wd.damage = battle_calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - wd.damage2 = (int64)d2*100/d1 * wd.damage/100; + wd.damage = battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); + wd.damage2 = d2*100/d1 * wd.damage/100; if(wd.damage > 1 && wd.damage2 < 1) wd.damage2 = 1; wd.damage-=wd.damage2; } @@ -3516,13 +3523,13 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo rnd()%100 < tsc->data[SC_REJECTSWORD]->val2 ) { ATK_RATER(50) - status_fix_damage(target,src,wd.damage,clif_damage(target,src,gettick(),0,0,wd.damage,0,0,0)); - clif_skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1); + status_fix_damage(target,src,wd.damage,clif->damage(target,src,gettick(),0,0,wd.damage,0,0,0)); + clif->skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_REJECTSWORD]->val1,1); if( --(tsc->data[SC_REJECTSWORD]->val3) <= 0 ) status_change_end(target, SC_REJECTSWORD, INVALID_TIMER); } if(skill_id == ASC_BREAKER) { //Breaker's int-based damage (a misc attack?) - struct Damage md = battle_calc_misc_attack(src, target, skill_id, skill_lv, wflag); + struct Damage md = battle->calc_misc_attack(src, target, skill_id, skill_lv, wflag); wd.damage += md.damage; } if( sc ) { @@ -3531,7 +3538,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo int hp= sstatus->max_hp; if (sd && tsd) { hp = 8*hp/100; - if (((int64)sstatus->hp * 100) <= ((int64)sstatus->max_hp * 20)) + if ((sstatus->hp * 100) <= (sstatus->max_hp * 20)) hp = sstatus->hp; } else hp = 2*hp/100; //2% hp loss per hit @@ -3552,7 +3559,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); } if( skill_id == LG_RAYOFGENESIS ) { - struct Damage md = battle_calc_magic_attack(src, target, skill_id, skill_lv, wflag); + struct Damage md = battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag); wd.damage += md.damage; } @@ -3562,8 +3569,7 @@ static struct Damage battle_calc_weapon_attack(struct block_list *src,struct blo /*========================================== * battle_calc_magic_attack [DracoRPG] *------------------------------------------*/ -struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) -{ +struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int i, nk; short s_ele = 0; unsigned int skillratio = 100; //Skill dmg modifiers. @@ -3589,13 +3595,13 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } //Initial Values ad.damage = 1; - ad.div_=skill_get_num(skill_id,skill_lv); - ad.amotion=skill_get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. + ad.div_=skill->get_num(skill_id,skill_lv); + ad.amotion=skill->get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; //Amotion should be 0 for ground skills. ad.dmotion=tstatus->dmotion; - ad.blewcount = skill_get_blewcount(skill_id,skill_lv); + ad.blewcount = skill->get_blewcount(skill_id,skill_lv); ad.flag=BF_MAGIC|BF_SKILL; ad.dmg_lv=ATK_DEF; - nk = skill_get_nk(skill_id); + nk = skill->get_nk(skill_id); flag.imdef = nk&NK_IGNORE_DEF?1:0; sd = BL_CAST(BL_PC, src); @@ -3604,7 +3610,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list tsc = status_get_sc(target); //Initialize variables that will be used afterwards - s_ele = skill_get_ele(skill_id, skill_lv); + s_ele = skill->get_ele(skill_id, skill_lv); if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element s_ele = sstatus->rhw.ele; @@ -3629,11 +3635,11 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list //Set miscellaneous data that needs be filled if(sd) { sd->state.arrow_atk = 0; - ad.blewcount += battle_blewcount_bonus(sd, skill_id); + ad.blewcount += battle->blewcount_bonus(sd, skill_id); } //Skill Range Criteria - ad.flag |= battle_range_type(src, target, skill_id, skill_lv); + ad.flag |= battle->range_type(src, target, skill_id, skill_lv); flag.infdef=(tstatus->mode&MD_PLANT?1:0); if( target->type == BL_SKILL){ TBL_SKILL *su = (TBL_SKILL*)target; @@ -3646,7 +3652,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case MG_FIREWALL: case NJ_KAENSIN: ad.dmotion = 0; //No flinch animation. - if ( tstatus->def_ele == ELE_FIRE || battle_check_undead(tstatus->race, tstatus->def_ele) ) + if ( tstatus->def_ele == ELE_FIRE || battle->check_undead(tstatus->race, tstatus->def_ele) ) ad.blewcount = 0; //No knockback break; case PR_SANCTUARY: @@ -3675,7 +3681,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list * Arch Bishop **/ case AB_HIGHNESSHEAL: - ad.damage = skill_calc_heal(src, target, skill_id, skill_lv, false); + ad.damage = skill->calc_heal(src, target, skill_id, skill_lv, false); break; case PR_ASPERSIO: ad.damage = 40; @@ -3727,7 +3733,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if(mflag>0) ad.damage/= mflag; else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id)); + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); } switch(skill_id){ @@ -3742,7 +3748,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list #endif break; case MG_SOULSTRIKE: - if (battle_check_undead(tstatus->race,tstatus->def_ele)) + if (battle->check_undead(tstatus->race,tstatus->def_ele)) skillratio += 5*skill_lv; break; case MG_FIREWALL: @@ -3946,7 +3952,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list int16 lv = skill_lv; int bandingBonus = 0; if( sc && sc->data[SC_BANDING] ) - bandingBonus = 200 * (sd ? skill_check_pc_partner(sd,skill_id,&lv,skill_get_splash(skill_id,skill_lv),0) : 1); + bandingBonus = 200 * (sd ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),0) : 1); skillratio = ((300 * skill_lv) + bandingBonus) * (sd ? sd->status.job_level : 1) / 25; } break; @@ -4080,13 +4086,35 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list MATK_ADD(50); } } +#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE + if( target && skill_id ) { + for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { + if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) { + if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { + if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) ) + continue; + if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) + continue; + } + if( ad.damage > map[target->m].zone->capped_skills[i]->cap ) + ad.damage = map[target->m].zone->capped_skills[i]->cap; + if( ad.damage2 > map[target->m].zone->capped_skills[i]->cap ) + ad.damage2 = map[target->m].zone->capped_skills[i]->cap; + break; + } + } + } +#endif #ifdef RENEWAL - ad.damage = battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); + ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); #endif if(sd) { //Damage bonuses if ((i = pc_skillatk_bonus(sd, skill_id))) - ad.damage += (int64)ad.damage*i/100; + ad.damage += ad.damage*i/100; + + if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) + MATK_RATE(i); //Ignore Defense? if (!flag.imdef && ( @@ -4134,7 +4162,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if(mflag>0) ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag; else - ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id)); + ShowError("Zero range by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); } if(ad.damage<1) @@ -4158,12 +4186,12 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } if (!(nk&NK_NO_ELEFIX)) - ad.damage=battle_attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + ad.damage=battle->attr_fix(src, target, ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); if( skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS ) { //Apply the physical part of the skill's damage. [Skotlex] - struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag); - ad.damage = battle_attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100; + struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + ad.damage = battle->attr_fix(src, target, wd.damage + ad.damage, s_ele, tstatus->def_ele, tstatus->ele_lv) * (100 + 40*skill_lv)/100; if( src == target ) { if( src->type == BL_PC ) @@ -4174,7 +4202,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } #ifndef RENEWAL - ad.damage = battle_calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); + ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag); #endif } @@ -4183,15 +4211,15 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if (flag.infdef && ad.damage) ad.damage = ad.damage>0?1:-1; - ad.damage=battle_calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv); + ad.damage=battle->calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv); if( map_flag_gvg2(target->m) ) - ad.damage=battle_calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); + ad.damage=battle->calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); else if( map[target->m].flag.battleground ) - ad.damage=battle_calc_bg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); + ad.damage=battle->calc_bg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); switch( skill_id ) { /* post-calc modifiers */ case SO_VARETYR_SPEAR: { // Physical damage. - struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); if(!flag.infdef && ad.damage > 1) ad.damage += wd.damage; break; @@ -4205,9 +4233,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list /*========================================== * Calculate Misc dammage for skill_id *------------------------------------------*/ -struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) -{ - int skill; +struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { + int temp; short i, nk; short s_ele; @@ -4224,31 +4251,31 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } //Some initial values - md.amotion=skill_get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; + md.amotion=skill->get_inf(skill_id)&INF_GROUND_SKILL?0:sstatus->amotion; md.dmotion=tstatus->dmotion; - md.div_=skill_get_num( skill_id,skill_lv ); - md.blewcount=skill_get_blewcount(skill_id,skill_lv); + md.div_=skill->get_num( skill_id,skill_lv ); + md.blewcount=skill->get_blewcount(skill_id,skill_lv); md.dmg_lv=ATK_DEF; md.flag=BF_MISC|BF_SKILL; - nk = skill_get_nk(skill_id); + nk = skill->get_nk(skill_id); sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, target); if(sd) { sd->state.arrow_atk = 0; - md.blewcount += battle_blewcount_bonus(sd, skill_id); + md.blewcount += battle->blewcount_bonus(sd, skill_id); } - s_ele = skill_get_ele(skill_id, skill_lv); + s_ele = skill->get_ele(skill_id, skill_lv); if (s_ele < 0 && s_ele != -3) //Attack that takes weapon's element for misc attacks? Make it neutral [Skotlex] s_ele = ELE_NEUTRAL; else if (s_ele == -3) //Use random element s_ele = rnd()%ELE_MAX; //Skill Range Criteria - md.flag |= battle_range_type(src, target, skill_id, skill_lv); + md.flag |= battle->range_type(src, target, skill_id, skill_lv); switch( skill_id ) { @@ -4276,20 +4303,19 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * case HT_BLITZBEAT: case SN_FALCONASSAULT: //Blitz-beat Damage. - if(!sd || (skill = pc_checkskill(sd,HT_STEELCROW)) <= 0) - skill=0; - md.damage=(sstatus->dex/10+sstatus->int_/2+skill*3+40)*2; + if(!sd || (temp = pc_checkskill(sd,HT_STEELCROW)) <= 0) + temp=0; + md.damage=(sstatus->dex/10+sstatus->int_/2+temp*3+40)*2; if(mflag > 1) //Autocasted Blitz. nk|=NK_SPLASHSPLIT; - if (skill_id == SN_FALCONASSAULT) - { + if (skill_id == SN_FALCONASSAULT) { //Div fix of Blitzbeat - skill = skill_get_num(HT_BLITZBEAT, 5); - damage_div_fix(md.damage, skill); + temp = skill->get_num(HT_BLITZBEAT, 5); + damage_div_fix(md.damage, temp); //Falcon Assault Modifier - md.damage=(int64)md.damage*(150+70*skill_lv)/100; + md.damage=md.damage*(150+70*skill_lv)/100; } break; case TF_THROWSTONE: @@ -4318,7 +4344,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * break; case CR_ACIDDEMONSTRATION: // updated the formula based on a Japanese formula found to be exact [Reddozen] if(tstatus->vit+sstatus->int_) //crash fix - md.damage = (int)((int64)7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_))); + md.damage = (int)(7*tstatus->vit*sstatus->int_*sstatus->int_ / (10*(tstatus->vit+sstatus->int_))); else md.damage = 0; if (tsd) md.damage>>=1; @@ -4329,7 +4355,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * break; case NJ_ZENYNAGE: case KO_MUCHANAGE: - md.damage = skill_get_zeny(skill_id ,skill_lv); + md.damage = skill->get_zeny(skill_id ,skill_lv); if (!md.damage) md.damage = 2; md.damage = rand()%md.damage + md.damage / (skill_id==NJ_ZENYNAGE?1:2) ; if (is_boss(target)) @@ -4341,7 +4367,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.damage = sd?sd->status.job_level:status_get_lv(src); break; case HVAN_EXPLOSION: //[orn] - md.damage = (int64)sstatus->max_hp * (50 + 50 * skill_lv) / 100; + md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100; break ; case ASC_BREAKER: md.damage = 500+rnd()%500 + 5*skill_lv * sstatus->int_; @@ -4352,12 +4378,12 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.dmotion = 0; //No flinch animation. break; case NPC_EVILLAND: - md.damage = skill_calc_heal(src,target,skill_id,skill_lv,false); + md.damage = skill->calc_heal(src,target,skill_id,skill_lv,false); break; case RK_DRAGONBREATH: md.damage = ((status_get_hp(src) / 50) + (status_get_max_sp(src) / 4)) * skill_lv; RE_LVL_MDMOD(150); - if (sd) md.damage = (int64)md.damage * (100 + 5 * (pc_checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100; + if (sd) md.damage = md.damage * (100 + 5 * (pc_checkskill(sd,RK_DRAGONTRAINING) - 1)) / 100; md.flag |= BF_LONG|BF_WEAPON; break; /** @@ -4372,11 +4398,11 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * { int researchskill_lv = pc_checkskill(sd,RA_RESEARCHTRAP); if(researchskill_lv) - md.damage = (int64)md.damage * 20 * researchskill_lv / (skill_id == RA_CLUSTERBOMB?50:100); + md.damage = md.damage * 20 * researchskill_lv / (skill_id == RA_CLUSTERBOMB?50:100); else md.damage = 0; }else - md.damage = (int64)md.damage * 200 / (skill_id == RA_CLUSTERBOMB?50:100); + md.damage = md.damage * 200 / (skill_id == RA_CLUSTERBOMB?50:100); break; /** @@ -4399,9 +4425,9 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * break; case KO_HAPPOKUNAI: { - struct Damage wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); short totaldef = tstatus->def2 + (short)status_get_def(target); - md.damage = (int64)wd.damage * 60 * (5 + skill_lv) / 100; + md.damage = wd.damage * 60 * (5 + skill_lv) / 100; md.damage -= totaldef; } break; @@ -4414,7 +4440,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * if(mflag>0) md.damage/= mflag; else - ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill_get_name(skill_id)); + ShowError("0 enemies targeted by %d:%s, divide per 0 avoided!\n", skill_id, skill->get_name(skill_id)); } damage_div_fix(md.damage, md.div_); @@ -4462,11 +4488,32 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * md.dmg_lv=ATK_FLEE; } } - - md.damage = battle_calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag); +#ifndef HMAP_ZONE_DAMAGE_CAP_TYPE + if( target && skill_id ) { + for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { + if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) { + if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { + if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) ) + continue; + if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) + continue; + } + if( md.damage > map[target->m].zone->capped_skills[i]->cap ) + md.damage = map[target->m].zone->capped_skills[i]->cap; + if( md.damage2 > map[target->m].zone->capped_skills[i]->cap ) + md.damage2 = map[target->m].zone->capped_skills[i]->cap; + break; + } + } + } +#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 += (int64)md.damage*i/100; + md.damage += md.damage*i/100; + + if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) + md.damage = md.damage * i / 100; if(md.damage < 0) md.damage = 0; @@ -4490,13 +4537,13 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } if(!(nk&NK_NO_ELEFIX)) - md.damage=battle_attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); + md.damage=battle->attr_fix(src, target, md.damage, s_ele, tstatus->def_ele, tstatus->ele_lv); - md.damage=battle_calc_damage(src,target,&md,md.damage,skill_id,skill_lv); + md.damage=battle->calc_damage(src,target,&md,md.damage,skill_id,skill_lv); if( map_flag_gvg2(target->m) ) - md.damage=battle_calc_gvg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); + md.damage=battle->calc_gvg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); else if( map[target->m].flag.battleground ) - md.damage=battle_calc_bg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); + md.damage=battle->calc_bg_damage(src,target,md.damage,md.div_,skill_id,skill_lv,md.flag); switch( skill_id ) { case RA_FIRINGTRAP: @@ -4505,7 +4552,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * case RA_CLUSTERBOMB: { struct Damage wd; - wd = battle_calc_weapon_attack(src,target,skill_id,skill_lv,mflag); + wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag); md.damage += wd.damage; } break; @@ -4521,35 +4568,55 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * return md; } /*========================================== - * Battle main entry, from skill_attack + * Battle main entry, from skill->attack *------------------------------------------*/ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int count) { struct Damage d; switch(attack_type) { - case BF_WEAPON: d = battle_calc_weapon_attack(bl,target,skill_id,skill_lv,count); break; - case BF_MAGIC: d = battle_calc_magic_attack(bl,target,skill_id,skill_lv,count); break; - case BF_MISC: d = battle_calc_misc_attack(bl,target,skill_id,skill_lv,count); break; + case BF_WEAPON: d = battle->calc_weapon_attack(bl,target,skill_id,skill_lv,count); break; + case BF_MAGIC: d = battle->calc_magic_attack(bl,target,skill_id,skill_lv,count); break; + case BF_MISC: d = battle->calc_misc_attack(bl,target,skill_id,skill_lv,count); break; default: ShowError("battle_calc_attack: unknown attack type! %d\n",attack_type); memset(&d,0,sizeof(d)); break; } - if( d.damage + d.damage2 < 1 ) - { //Miss/Absorbed + +#ifdef HMAP_ZONE_DAMAGE_CAP_TYPE + if( target && skill_id ) { + int i; + for(i = 0; i < map[target->m].zone->capped_skills_count; i++) { + if( skill_id == map[target->m].zone->capped_skills[i]->nameid && (map[target->m].zone->capped_skills[i]->type & target->type) ) { + if( target->type == BL_MOB && map[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { + if( (((TBL_MOB*)target)->status.mode&MD_BOSS) && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_BOSS) ) + continue; + if( ((TBL_MOB*)target)->special_state.clone && !(map[target->m].zone->disabled_skills[i]->subtype&MZS_CLONE) ) + continue; + } + if( d.damage > map[target->m].zone->capped_skills[i]->cap ) + d.damage = map[target->m].zone->capped_skills[i]->cap; + if( d.damage2 > map[target->m].zone->capped_skills[i]->cap ) + d.damage2 = map[target->m].zone->capped_skills[i]->cap; + break; + } + } + } +#endif + + if( d.damage + d.damage2 < 1 ) { //Miss/Absorbed //Weapon attacks should go through to cause additional effects. if (d.dmg_lv == ATK_DEF /*&& attack_type&(BF_MAGIC|BF_MISC)*/) // Isn't it that additional effects don't apply if miss? d.dmg_lv = ATK_MISS; d.dmotion = 0; - } - else // Some skills like Weaponry Research will cause damage even if attack is dodged + } else // Some skills like Weaponry Research will cause damage even if attack is dodged d.dmg_lv = ATK_DEF; return d; } //Calculates BF_WEAPON returned damage. int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int *dmg, int flag, uint16 skill_id){ - struct map_session_data* sd = NULL; + struct map_session_data* sd; int rdamage = 0, damage = *dmg; struct status_change* sc; @@ -4557,40 +4624,40 @@ int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int sc = status_get_sc(bl); if( sc && sc->data[SC_REFLECTDAMAGE] ) { - int max_damage = (int64)status_get_max_hp(bl) * status_get_lv(bl) / 100; - rdamage = (int64)(*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100; + int max_damage = status_get_max_hp(bl) * status_get_lv(bl) / 100; + rdamage = (*dmg) * sc->data[SC_REFLECTDAMAGE]->val2 / 100; if( rdamage > max_damage ) rdamage = max_damage; }else if( sc && sc->data[SC_CRESCENTELBOW] && !is_boss(src) && rnd()%100 < sc->data[SC_CRESCENTELBOW]->val2 ){ //ATK [{(Target HP / 100) x Skill Level} x Caster Base Level / 125] % + [Received damage x {1 + (Skill Level x 0.2)}] - int ratio = (int64)(status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status_get_lv(bl) / 125; + int ratio = (status_get_hp(src) / 100) * sc->data[SC_CRESCENTELBOW]->val1 * status_get_lv(bl) / 125; if (ratio > 5000) ratio = 5000; // Maximum of 5000% ATK - rdamage = (int64)rdamage * ratio / 100 + (*dmg) * (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10; - skill_blown(bl, src, skill_get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0); - clif_skill_damage(bl, src, gettick(), status_get_amotion(src), 0, rdamage, + rdamage = rdamage * ratio / 100 + (*dmg) * (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10; + skill->blown(bl, src, skill->get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit_getdir(src), 0); + clif->skill_damage(bl, src, gettick(), status_get_amotion(src), 0, rdamage, 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does - clif_damage(src, bl, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, 0, 0); + clif->damage(src, bl, gettick(), status_get_amotion(src)+1000, 0, rdamage/10, 1, 0, 0); status_damage(src, bl, status_damage(bl, src, rdamage, 0, 0, 1)/10, 0, 0, 1); status_change_end(bl, SC_CRESCENTELBOW, INVALID_TIMER); return 0; // Just put here to minimize redundancy }else if (flag & BF_SHORT) {//Bounces back part of the damage. if ( sd && sd->bonus.short_weapon_damage_return ) { - rdamage += (int64)damage * sd->bonus.short_weapon_damage_return / 100; + rdamage += damage * sd->bonus.short_weapon_damage_return / 100; if(rdamage < 1) rdamage = 1; } if( sc && sc->count ) { if ( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) { - rdamage += (int64)damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; + rdamage += damage * sc->data[SC_REFLECTSHIELD]->val2 / 100; if (rdamage < 1) rdamage = 1; } if(sc->data[SC_DEATHBOUND] && skill_id != WS_CARTTERMINATION && !(src->type == BL_MOB && is_boss(src)) ) { uint8 dir = map_calc_dir(bl,src->x,src->y), t_dir = unit_getdir(bl); - int rd1 = 0; if( distance_bl(src,bl) <= 0 || !map_check_dir(dir,t_dir) ) { - rd1 = (int64)min(damage,status_get_max_hp(bl)) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. - *dmg = (int64)rd1 * 30 / 100; // Received damage = 30% of amplifly damage. - clif_skill_damage(src,bl,gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1,6); + int rd1 = 0; + rd1 = min(damage,status_get_max_hp(bl)) * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. + *dmg = rd1 * 30 / 100; // Received damage = 30% of amplifly damage. + clif->skill_damage(src,bl,gettick(), status_get_amotion(src), 0, -30000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1,6); status_change_end(bl,SC_DEATHBOUND,INVALID_TIMER); rdamage += rd1; if (rdamage < 1) rdamage = 1; @@ -4599,7 +4666,7 @@ int battle_calc_return_damage(struct block_list* bl, struct block_list *src, int } } else { if (sd && sd->bonus.long_weapon_damage_return) { - rdamage += (int64)damage * sd->bonus.long_weapon_damage_return / 100; + rdamage += damage * sd->bonus.long_weapon_damage_return / 100; if (rdamage < 1) rdamage = 1; } } @@ -4627,11 +4694,11 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int rdamage, int ldamage, hp = wd->hp_drain[type].value; if (wd->hp_drain[type].rate) - hp += battle_calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per); + hp += battle->calc_drain(*damage, wd->hp_drain[type].rate, wd->hp_drain[type].per); sp = wd->sp_drain[type].value; if (wd->sp_drain[type].rate) - sp += battle_calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per); + sp += battle->calc_drain(*damage, wd->sp_drain[type].rate, wd->sp_drain[type].per); if (hp) { if (wd->hp_drain[type].type) @@ -4675,16 +4742,17 @@ int battle_damage_area( struct block_list *bl, va_list ap) { damage=va_arg(ap,int); if( bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM ) return 0; - if( bl != src && battle_check_target(src,bl,BCT_ENEMY) > 0 ) { + if( bl != src && battle->check_target(src,bl,BCT_ENEMY) > 0 ) { map_freeblock_lock(); if( src->type == BL_PC ) - battle_drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), is_boss(bl)); + battle->drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), is_boss(bl)); if( amotion ) - battle_delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0); + battle->delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true); else status_fix_damage(src,bl,damage,0); - clif_damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0); - skill_additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); + clif->damage(bl,bl,tick,amotion,dmotion,damage,1,ATK_BLOCK,0); + if( !(src && src->type == BL_PC && ((TBL_PC*)src)->state.autocast) ) + skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); map_freeblock_unlock(); } @@ -4728,7 +4796,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t { int index = sd->equip_index[EQI_AMMO]; if (index<0) { - clif_arrow_fail(sd,0); + clif->arrow_fail(sd,0); return ATK_NONE; } //Ammo check by Ishizu-chan @@ -4736,7 +4804,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t switch (sd->status.weapon) { case W_BOW: if (sd->inventory_data[index]->look != A_ARROW) { - clif_arrow_fail(sd,0); + clif->arrow_fail(sd,0); return ATK_NONE; } break; @@ -4745,13 +4813,13 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t case W_GATLING: case W_SHOTGUN: if (sd->inventory_data[index]->look != A_BULLET) { - clif_arrow_fail(sd,0); + clif->arrow_fail(sd,0); return ATK_NONE; } break; case W_GRENADE: if (sd->inventory_data[index]->look != A_GRENADE) { - clif_arrow_fail(sd,0); + clif->arrow_fail(sd,0); return ATK_NONE; } break; @@ -4772,10 +4840,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if(dist <= 0 || (!map_check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1; - clif_skillcastcancel(target); //Remove the casting bar. [Skotlex] - clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->skillcastcancel(target); //Remove the casting bar. [Skotlex] + clif->damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); - skill_attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0); + skill->attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0); return ATK_BLOCK; } } @@ -4783,12 +4851,12 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if( tsc && tsc->data[SC_BLADESTOP_WAIT] && !is_boss(src) && (src->type == BL_PC || tsd == NULL || distance_bl(src, target) <= (tsd->status.weapon == W_FIST ? 1 : 2)) ) { uint16 skill_lv = tsc->data[SC_BLADESTOP_WAIT]->val1; - int duration = skill_get_time2(MO_BLADESTOP,skill_lv); + int duration = skill->get_time2(MO_BLADESTOP,skill_lv); status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); if(sc_start4(src, SC_BLADESTOP, 100, sd?pc_checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { //Target locked. - clif_damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. - clif_bladestop(target, src->id, 1); + clif->damage(src, target, tick, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->bladestop(target, src->id, 1); sc_start4(target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); return ATK_BLOCK; } @@ -4801,7 +4869,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); } if (rnd()%100 < triple_rate) { - if( skill_attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0) ) + if( skill->attack(BF_WEAPON,src,src,target,MO_TRIPLEATTACK,skillv,tick,0) ) return ATK_DEF; return ATK_MISS; } @@ -4819,7 +4887,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t * We need to calculate the DMG before the hp reduction, because it can kill the source. * For futher information: bugreport:4950 **/ - ret_val = (damage_lv)skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skill_lv,tick,0); + ret_val = (damage_lv)skill->attack(BF_WEAPON,src,src,target,PA_SACRIFICE,skill_lv,tick,0); status_zap(src, sstatus->max_hp*9/100, 0);//Damage to self is always 9% if( ret_val == ATK_NONE ) @@ -4827,35 +4895,35 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return ret_val; } if (sc->data[SC_MAGICALATTACK]) { - if( skill_attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0) ) + if( skill->attack(BF_MAGIC,src,src,target,NPC_MAGICALATTACK,sc->data[SC_MAGICALATTACK]->val1,tick,0) ) return ATK_DEF; return ATK_MISS; } if( sc->data[SC_GT_ENERGYGAIN] ) { if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GT_ENERGYGAIN]->val1) pc_addspiritball(sd, - skill_get_time(MO_CALLSPIRITS, sc->data[SC_GT_ENERGYGAIN]->val1), + skill->get_time(MO_CALLSPIRITS, sc->data[SC_GT_ENERGYGAIN]->val1), sc->data[SC_GT_ENERGYGAIN]->val1); } if( tsc && tsc->data[SC_GT_ENERGYGAIN] ) { if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GT_ENERGYGAIN]->val1) pc_addspiritball(tsd, - skill_get_time(MO_CALLSPIRITS, tsc->data[SC_GT_ENERGYGAIN]->val1), + skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GT_ENERGYGAIN]->val1), tsc->data[SC_GT_ENERGYGAIN]->val1); } if( sc && sc->data[SC_CRUSHSTRIKE] ){ uint16 skill_lv = sc->data[SC_CRUSHSTRIKE]->val1; status_change_end(src, SC_CRUSHSTRIKE, INVALID_TIMER); - if( skill_attack(BF_WEAPON,src,src,target,RK_CRUSHSTRIKE,skill_lv,tick,0) ) + if( skill->attack(BF_WEAPON,src,src,target,RK_CRUSHSTRIKE,skill_lv,tick,0) ) return ATK_DEF; return ATK_MISS; } } if(tsc && tsc->data[SC_KAAHI] && tsc->data[SC_KAAHI]->val4 == INVALID_TIMER && tstatus->hp < tstatus->max_hp) - tsc->data[SC_KAAHI]->val4 = add_timer(tick + skill_get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal. + tsc->data[SC_KAAHI]->val4 = add_timer(tick + skill->get_time2(SL_KAAHI,tsc->data[SC_KAAHI]->val1), kaahi_heal_timer, target->id, SC_KAAHI); //Activate heal. - wd = battle_calc_attack(BF_WEAPON, src, target, 0, 0, flag); + wd = battle->calc_attack(BF_WEAPON, src, target, 0, 0, flag); if( sc && sc->count ) { if (sc->data[SC_EXEEDBREAK]) { @@ -4864,7 +4932,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } 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); + struct Damage ad = battle->calc_attack(BF_MAGIC,src,target,sc->data[SC_SPELLFIST]->val3,sc->data[SC_SPELLFIST]->val4,flag|BF_SHORT); wd.damage = ad.damage; }else status_change_end(src,SC_SPELLFIST,INVALID_TIMER); @@ -4878,46 +4946,46 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } } if (sd && sd->state.arrow_atk) //Consume arrow. - battle_consume_ammo(sd, 0, 0); + battle->consume_ammo(sd, 0, 0); damage = wd.damage + wd.damage2; - if( damage > 0 && src != target ) - { - if( sc && sc->data[SC_DUPLELIGHT] && (wd.flag&BF_SHORT) && rnd()%100 <= 10+2*sc->data[SC_DUPLELIGHT]->val1 ) - { // Activates it only from melee damage + if( damage > 0 && src != target ) { + if( sc && sc->data[SC_DUPLELIGHT] && (wd.flag&BF_SHORT) && rnd()%100 <= 10+2*sc->data[SC_DUPLELIGHT]->val1 ){ + // Activates it only from melee damage uint16 skill_id; if( rnd()%2 == 1 ) skill_id = AB_DUPLELIGHT_MELEE; else skill_id = AB_DUPLELIGHT_MAGIC; - skill_attack(skill_get_type(skill_id), src, src, target, skill_id, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL); + skill->attack(skill->get_type(skill_id), src, src, target, skill_id, sc->data[SC_DUPLELIGHT]->val1, tick, SD_LEVEL); } - rdamage = battle_calc_return_damage(target,src, &damage, wd.flag, 0); + rdamage = battle->calc_return_damage(target,src, &damage, wd.flag, 0); if( rdamage > 0 ) { if( tsc && tsc->data[SC_REFLECTDAMAGE] ) { - if( src != target )// Don't reflect your own damage (Grand Cross) - map_foreachinshootrange(battle_damage_area,target,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,wd.dmotion,rdamage,tstatus->race,0); + if( src != target ) {// Don't reflect your own damage (Grand Cross) + map_foreachinshootrange(battle->damage_area,target,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,target,wd.amotion,wd.dmotion,rdamage,tstatus->race); + } } else { - rdelay = clif_damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0); + rdelay = clif->damage(src, src, tick, wd.amotion, sstatus->dmotion, rdamage, 1, 4, 0); //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] - skill_additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); + skill->additional_effect(target,src,CR_REFLECTSHIELD,1,BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); } } } - wd.dmotion = clif_damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2); + wd.dmotion = clif->damage(src, target, tick, wd.amotion, wd.dmotion, wd.damage, wd.div_ , wd.type, wd.damage2); if (sd && sd->bonus.splash_range > 0 && damage > 0) - skill_castend_damage_id(src, target, 0, 1, tick, 0); + skill->castend_damage_id(src, target, 0, 1, tick, 0); if ( target->type == BL_SKILL && damage > 0 ){ TBL_SKILL *su = (TBL_SKILL*)target; if( su->group && su->group->skill_id == HT_BLASTMINE) - skill_blown(src, target, 3, -1, 0); + skill->blown(src, target, 3, -1, 0); } map_freeblock_lock(); - battle_delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion); + battle->delay_damage(tick, wd.amotion, src, target, wd.flag, 0, 0, damage, wd.dmg_lv, wd.dmotion, true); if( tsc ) { if( tsc->data[SC_DEVOTION] ) { struct status_change_entry *sce = tsc->data[SC_DEVOTION]; @@ -4928,7 +4996,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) ) && check_distance_bl(target, d_bl, sce->val3) ) { - clif_damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0); + clif->damage(d_bl, d_bl, gettick(), 0, 0, damage, 0, 0, 0); status_fix_damage(NULL, d_bl, damage, 0); } else @@ -4936,16 +5004,16 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } else if( tsc->data[SC_CIRCLE_OF_FIRE_OPTION] && (wd.flag&BF_SHORT) && target->type == BL_PC ) { struct elemental_data *ed = ((TBL_PC*)target)->ed; if( ed ) { - clif_skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6); - skill_attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag); + clif->skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6); + skill->attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag); } } else if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) { struct block_list *e_bl = map_id2bl(tsc->data[SC_WATER_SCREEN_OPTION]->val1); if( e_bl && !status_isdead(e_bl) ) { - clif_damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2); + clif->damage(e_bl,e_bl,tick,wd.amotion,wd.dmotion,damage,wd.div_,wd.type,wd.damage2); status_damage(target,e_bl,damage,0,0,0); // Just show damage in target. - clif_damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 ); + clif->damage(src, target, tick, wd.amotion, wd.dmotion, damage, wd.div_, wd.type, wd.damage2 ); map_freeblock_unlock(); return ATK_NONE; } @@ -4961,43 +5029,44 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if (i >= 50) skill_lv -= 2; else if (i >= 15) skill_lv--; if (skill_lv < 1) skill_lv = 1; - sp = skill_get_sp(skill_id,skill_lv) * 2 / 3; + sp = skill->get_sp(skill_id,skill_lv) * 2 / 3; if (status_charge(src, 0, sp)) { - switch (skill_get_casttype(skill_id)) { + switch (skill->get_casttype(skill_id)) { case CAST_GROUND: - skill_castend_pos2(src, target->x, target->y, skill_id, skill_lv, tick, flag); + skill->castend_pos2(src, target->x, target->y, skill_id, skill_lv, tick, flag); break; case CAST_NODAMAGE: - skill_castend_nodamage_id(src, target, skill_id, skill_lv, tick, flag); + skill->castend_nodamage_id(src, target, skill_id, skill_lv, tick, flag); break; case CAST_DAMAGE: - skill_castend_damage_id(src, target, skill_id, skill_lv, tick, flag); + skill->castend_damage_id(src, target, skill_id, skill_lv, tick, flag); break; } } } if (sd) { if( wd.flag&BF_SHORT && sc && sc->data[SC__AUTOSHADOWSPELL] && rnd()%100 < sc->data[SC__AUTOSHADOWSPELL]->val3 && - sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id != 0 && sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].flag == SKILL_FLAG_PLAGIARIZED ) + sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id != 0 && sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].flag == SKILL_FLAG_PLAGIARIZED ) { - int r_skill = sd->status.skill[sc->data[SC__AUTOSHADOWSPELL]->val1].id, - r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2, type; + int r_skill = sd->status.skill[skill->get_index(sc->data[SC__AUTOSHADOWSPELL]->val1)].id, + r_lv = sc->data[SC__AUTOSHADOWSPELL]->val2; if (r_skill != AL_HOLYLIGHT && r_skill != PR_MAGNUS) { - if( (type = skill_get_casttype(r_skill)) == CAST_GROUND ) { + int type; + if( (type = skill->get_casttype(r_skill)) == CAST_GROUND ) { int maxcount = 0; if( !(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(r_skill)&UF_NOREITERATION ) + skill->get_unit_flag(r_skill)&UF_NOREITERATION ) type = -1; if( BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(r_skill)&UF_NOFOOTSET ) + skill->get_unit_flag(r_skill)&UF_NOFOOTSET ) type = -1; if( BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(r_skill, r_lv)) > 0 + (maxcount = skill->get_maxcount(r_skill, r_lv)) > 0 ) { int v; for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) { @@ -5009,43 +5078,43 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } if( type != CAST_GROUND ){ - clif_skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,r_skill,USESKILL_FAIL_LEVEL,0); map_freeblock_unlock(); return wd.dmg_lv; } } sd->state.autocast = 1; - skill_consume_requirement(sd,r_skill,r_lv,3); + skill->consume_requirement(sd,r_skill,r_lv,3); switch( type ) { - case CAST_GROUND: - skill_castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(src, target, r_skill, r_lv, tick, flag); - break; - case CAST_DAMAGE: - skill_castend_damage_id(src, target, r_skill, r_lv, tick, flag); - break; + case CAST_GROUND: + skill->castend_pos2(src, target->x, target->y, r_skill, r_lv, tick, flag); + break; + case CAST_NODAMAGE: + skill->castend_nodamage_id(src, target, r_skill, r_lv, tick, flag); + break; + case CAST_DAMAGE: + skill->castend_damage_id(src, target, r_skill, r_lv, tick, flag); + break; } sd->state.autocast = 0; - sd->ud.canact_tick = tick + skill_delayfix(src, r_skill, r_lv); - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, r_skill, r_lv), 0, 0, 1); + sd->ud.canact_tick = tick + skill->delay_fix(src, r_skill, r_lv); + clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, r_skill, r_lv), 0, 0, 1); } } if (wd.flag & BF_WEAPON && src != target && damage > 0) { if (battle_config.left_cardfix_to_right) - battle_drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target)); + battle->drain(sd, target, wd.damage, wd.damage, tstatus->race, is_boss(target)); else - battle_drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target)); + battle->drain(sd, target, wd.damage, wd.damage2, tstatus->race, is_boss(target)); } } - if (rdamage > 0 && !(tsc && tsc->data[SC_REFLECTDAMAGE])) { //By sending attack type "none" skill_additional_effect won't be invoked. [Skotlex] + if (rdamage > 0 && !(tsc && tsc->data[SC_REFLECTDAMAGE])) { //By sending attack type "none" skill->additional_effect won't be invoked. [Skotlex] if(tsd && src != target) - battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); - battle_delay_damage(tick, wd.amotion, target, src, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay); + battle->drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); + battle->delay_damage(tick, wd.amotion, target, src, 0, CR_REFLECTSHIELD, 0, rdamage, ATK_DEF, rdelay, true); } if (tsc) { @@ -5058,9 +5127,9 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t struct status_change_entry *sce = tsc->data[SC_POISONREACT]; if (sstatus->def_ele == ELE_POISON) { sce->val2 = 0; - skill_attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0); + skill->attack(BF_WEAPON,target,target,src,AS_POISONREACT,sce->val1,tick,0); } else { - skill_attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0); + skill->attack(BF_WEAPON,target,target,src,TF_POISON, 5, tick, 0); --sce->val2; } if (sce->val2 <= 0) @@ -5148,10 +5217,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f //t_bl/s_bl hold the 'master' of the attack, while src/target are the actual //objects involved. - if( (t_bl = battle_get_master(target)) == NULL ) + if( (t_bl = battle->get_master(target)) == NULL ) t_bl = target; - if( (s_bl = battle_get_master(src)) == NULL ) + if( (s_bl = battle->get_master(src)) == NULL ) s_bl = src; if ( s_bl->type == BL_PC ) { @@ -5183,7 +5252,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f case BL_MOB: if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras - s_bl->type == BL_PC && src->type != BL_MOB) || ((TBL_MOB*)target)->special_state.ai == 4) //Zanzoe + s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == 4 && t_bl->id != s_bl->id)) //Zanzoe { //Targettable by players state |= BCT_ENEMY; strip_enemy = 0; @@ -5194,8 +5263,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f TBL_SKILL *su = (TBL_SKILL*)target; if( !su->group ) return 0; - if( skill_get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps... - switch( battle_getcurrentskill(src) ) { + if( skill->get_inf2(su->group->skill_id)&INF2_TRAP ) { //Only a few skills can target traps... + switch( battle->get_current_skill(src) ) { case RK_DRAGONBREATH:// it can only hit traps in pvp/gvg maps if( !map[m].flag.pvp && !map[m].flag.gvg ) break; @@ -5300,7 +5369,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f return 0; if (su->group->src_id == target->id) { - int inf2 = skill_get_inf2(su->group->skill_id); + int inf2 = skill->get_inf2(su->group->skill_id); if (inf2&INF2_NO_TARGET_SELF) return -1; if (inf2&INF2_TARGET_SELF) @@ -5408,7 +5477,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f { int s_guild = status_get_guild_id(s_bl); int t_guild = status_get_guild_id(t_bl); - if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild)) && (!map[m].flag.battleground || sbg_id == tbg_id) ) + if( !(map[m].flag.pvp && map[m].flag.pvp_noguild) && s_guild && t_guild && (s_guild == t_guild || guild->isallied(s_guild, t_guild)) && (!map[m].flag.battleground || sbg_id == tbg_id) ) state |= BCT_GUILD; else state |= BCT_ENEMY; @@ -5441,7 +5510,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f { int s_guild = status_get_guild_id(s_bl); int t_guild = status_get_guild_id(t_bl); - if(s_guild && t_guild && (s_guild == t_guild || guild_isallied(s_guild, t_guild))) + if(s_guild && t_guild && (s_guild == t_guild || guild->isallied(s_guild, t_guild))) state |= BCT_GUILD; } } //end non pvp/gvg chk rivality @@ -5613,6 +5682,7 @@ static const struct _battle_data { { "wedding_ignorepalette", &battle_config.wedding_ignorepalette, 0, 0, 1, }, { "xmas_ignorepalette", &battle_config.xmas_ignorepalette, 0, 0, 1, }, { "summer_ignorepalette", &battle_config.summer_ignorepalette, 0, 0, 1, }, + { "hanbok_ignorepalette", &battle_config.hanbok_ignorepalette, 0, 0, 1, }, { "natural_healhp_interval", &battle_config.natural_healhp_interval, 6000, NATURAL_HEAL_INTERVAL, INT_MAX, }, { "natural_healsp_interval", &battle_config.natural_healsp_interval, 8000, NATURAL_HEAL_INTERVAL, INT_MAX, }, { "natural_heal_skill_interval", &battle_config.natural_heal_skill_interval, 10000, NATURAL_HEAL_INTERVAL, INT_MAX, }, @@ -5653,17 +5723,7 @@ static const struct _battle_data { { "player_cloak_check_type", &battle_config.pc_cloak_check_type, 1, 0, 1|2|4, }, { "monster_cloak_check_type", &battle_config.monster_cloak_check_type, 4, 0, 1|2|4, }, { "sense_type", &battle_config.estimation_type, 1|2, 0, 1|2, }, - { "gvg_short_attack_damage_rate", &battle_config.gvg_short_damage_rate, 80, 0, INT_MAX, }, - { "gvg_long_attack_damage_rate", &battle_config.gvg_long_damage_rate, 80, 0, INT_MAX, }, - { "gvg_weapon_attack_damage_rate", &battle_config.gvg_weapon_damage_rate, 60, 0, INT_MAX, }, - { "gvg_magic_attack_damage_rate", &battle_config.gvg_magic_damage_rate, 60, 0, INT_MAX, }, - { "gvg_misc_attack_damage_rate", &battle_config.gvg_misc_damage_rate, 60, 0, INT_MAX, }, { "gvg_flee_penalty", &battle_config.gvg_flee_penalty, 20, 0, INT_MAX, }, - { "pk_short_attack_damage_rate", &battle_config.pk_short_damage_rate, 80, 0, INT_MAX, }, - { "pk_long_attack_damage_rate", &battle_config.pk_long_damage_rate, 70, 0, INT_MAX, }, - { "pk_weapon_attack_damage_rate", &battle_config.pk_weapon_damage_rate, 60, 0, INT_MAX, }, - { "pk_magic_attack_damage_rate", &battle_config.pk_magic_damage_rate, 60, 0, INT_MAX, }, - { "pk_misc_attack_damage_rate", &battle_config.pk_misc_damage_rate, 60, 0, INT_MAX, }, { "mob_changetarget_byskill", &battle_config.mob_changetarget_byskill, 0, 0, 1, }, { "attack_direction_change", &battle_config.attack_direction_change, BL_ALL, BL_NUL, BL_ALL, }, { "land_skill_limit", &battle_config.land_skill_limit, BL_ALL, BL_NUL, BL_ALL, }, @@ -5745,7 +5805,6 @@ static const struct _battle_data { { "night_at_start", &battle_config.night_at_start, 0, 0, 1, }, { "show_mob_info", &battle_config.show_mob_info, 0, 0, 1|2|4, }, { "ban_hack_trade", &battle_config.ban_hack_trade, 0, 0, INT_MAX, }, - { "packet_ver_flag", &battle_config.packet_ver_flag, 0xFFFFFF,0x0000,INT_MAX, }, { "min_hair_style", &battle_config.min_hair_style, 0, 0, INT_MAX, }, { "max_hair_style", &battle_config.max_hair_style, 23, 0, INT_MAX, }, { "min_hair_color", &battle_config.min_hair_color, 0, 0, INT_MAX, }, @@ -5790,7 +5849,6 @@ static const struct _battle_data { { "show_hp_sp_gain", &battle_config.show_hp_sp_gain, 1, 0, 1, }, { "mob_npc_event_type", &battle_config.mob_npc_event_type, 1, 0, 1, }, { "character_size", &battle_config.character_size, 1|2, 0, 1|2, }, - { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, MAX_SKILL_LEVEL, 1, MAX_SKILL_LEVEL, }, { "retaliate_to_master", &battle_config.retaliate_to_master, 1, 0, 1, }, { "rare_drop_announce", &battle_config.rare_drop_announce, 0, 0, 10000, }, { "duel_allow_pvp", &battle_config.duel_allow_pvp, 0, 0, 1, }, @@ -5800,14 +5858,13 @@ static const struct _battle_data { { "duel_time_interval", &battle_config.duel_time_interval, 60, 0, INT_MAX, }, { "duel_only_on_same_map", &battle_config.duel_only_on_same_map, 0, 0, 1, }, { "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu, 0, 0, 1, }, + { "mob_max_skilllvl", &battle_config.mob_max_skilllvl, 100, 1, INT_MAX, }, { "allow_skill_without_day", &battle_config.allow_skill_without_day, 0, 0, 1, }, { "allow_es_magic_player", &battle_config.allow_es_magic_pc, 0, 0, 1, }, { "skill_caster_check", &battle_config.skill_caster_check, 1, 0, 1, }, { "status_cast_cancel", &battle_config.sc_castcancel, BL_NUL, BL_NUL, BL_ALL, }, { "pc_status_def_rate", &battle_config.pc_sc_def_rate, 100, 0, INT_MAX, }, { "mob_status_def_rate", &battle_config.mob_sc_def_rate, 100, 0, INT_MAX, }, - { "pc_luk_status_def", &battle_config.pc_luk_sc_def, 300, 1, INT_MAX, }, - { "mob_luk_status_def", &battle_config.mob_luk_sc_def, 300, 1, INT_MAX, }, { "pc_max_status_def", &battle_config.pc_max_sc_def, 100, 0, INT_MAX, }, { "mob_max_status_def", &battle_config.mob_max_sc_def, 100, 0, INT_MAX, }, { "sg_miracle_skill_ratio", &battle_config.sg_miracle_skill_ratio, 1, 0, 10000, }, @@ -5855,11 +5912,6 @@ static const struct _battle_data { { "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, }, // BattleGround Settings { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, }, - { "bg_short_attack_damage_rate", &battle_config.bg_short_damage_rate, 80, 0, INT_MAX, }, - { "bg_long_attack_damage_rate", &battle_config.bg_long_damage_rate, 80, 0, INT_MAX, }, - { "bg_weapon_attack_damage_rate", &battle_config.bg_weapon_damage_rate, 60, 0, INT_MAX, }, - { "bg_magic_attack_damage_rate", &battle_config.bg_magic_damage_rate, 60, 0, INT_MAX, }, - { "bg_misc_attack_damage_rate", &battle_config.bg_misc_damage_rate, 60, 0, INT_MAX, }, { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, }, /** * rAthena @@ -5870,20 +5922,29 @@ static const struct _battle_data { { "skill_amotion_leniency", &battle_config.skill_amotion_leniency, 90, 0, 300 }, { "mvp_tomb_enabled", &battle_config.mvp_tomb_enabled, 1, 0, 1 }, { "feature.atcommand_suggestions", &battle_config.atcommand_suggestions_enabled, 0, 0, 1 }, - { "min_npc_vending_distance", &battle_config.min_npc_vending_distance, 3, 0, 100 }, + { "min_npc_vendchat_distance", &battle_config.min_npc_vendchat_distance, 3, 0, 100 }, { "atcommand_mobinfo_type", &battle_config.atcommand_mobinfo_type, 0, 0, 1 }, { "homunculus_max_level", &battle_config.hom_max_level, 99, 0, MAX_LEVEL, }, { "homunculus_S_max_level", &battle_config.hom_S_max_level, 150, 0, MAX_LEVEL, }, { "mob_size_influence", &battle_config.mob_size_influence, 0, 0, 1, }, + /** + * Hercules + **/ + { "skill_trap_type", &battle_config.skill_trap_type, 0, 0, 1, }, + { "item_restricted_consumption_type", &battle_config.item_restricted_consumption_type,1, 0, 1, }, + { "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, }, + { "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, }, + { "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, }, }; #ifndef STATS_OPT_OUT /** - * rAthena anonymous statistic usage report -- packet is built here, and sent to char server to report. + * Hercules anonymous statistic usage report -- packet is built here, and sent to char server to report. **/ -void rAthena_report(char* date, char *time_c) { - int i, rev = 0, bd_size = ARRAYLENGTH(battle_data); +void Hercules_report(char* date, char *time_c) { + int i, bd_size = ARRAYLENGTH(battle_data); unsigned int config = 0; - const char* rev_str; + const char *svn = get_svn_revision(); + const char *git = get_git_hash(); char timestring[25]; time_t curtime; char* buf; @@ -5891,7 +5952,7 @@ void rAthena_report(char* date, char *time_c) { enum config_table { C_CIRCULAR_AREA = 0x0001, C_CELLNOSTACK = 0x0002, - C_BETA_THREAD_TEST = 0x0004, + C_CONSOLE_INPUT = 0x0004, C_SCRIPT_CALLFUNC_CHECK = 0x0008, C_OFFICIAL_WALKPATH = 0x0010, C_RENEWAL = 0x0020, @@ -5904,16 +5965,16 @@ void rAthena_report(char* date, char *time_c) { C_SECURE_NPCTIMEOUT = 0x1000, C_SQL_DBS = 0x2000, C_SQL_LOGS = 0x4000, + C_MEMWATCH = 0x8000, + C_DMALLOC = 0x10000, + C_GCOLLECT = 0x20000, + C_SEND_SHORTLIST = 0x40000, }; - if( (rev_str = get_svn_revision()) != 0 ) - rev = atoi(rev_str); - /* we get the current time */ time(&curtime); strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", localtime(&curtime)); - - + #ifdef CIRCULAR_AREA config |= C_CIRCULAR_AREA; #endif @@ -5922,10 +5983,10 @@ void rAthena_report(char* date, char *time_c) { config |= C_CELLNOSTACK; #endif -#ifdef BETA_THREAD_TEST - config |= C_BETA_THREAD_TEST; +#ifdef CONSOLE_INPUT + config |= C_CONSOLE_INPUT; #endif - + #ifdef SCRIPT_CALLFUNC_CHECK config |= C_SCRIPT_CALLFUNC_CHECK; #endif @@ -5962,51 +6023,65 @@ void rAthena_report(char* date, char *time_c) { config |= C_RENEWAL_ASPD; #endif -/* not a ifdef because SECURE_NPCTIMEOUT is always defined, but either as 0 or higher */ -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT config |= C_SECURE_NPCTIMEOUT; #endif + /* non-define part */ if( db_use_sqldbs ) config |= C_SQL_DBS; - if( log_config.sql_logs ) + if( logs->config.sql_logs ) config |= C_SQL_LOGS; +#ifdef MEMWATCH + config |= C_MEMWATCH; +#endif +#ifdef DMALLOC + config |= C_DMALLOC; +#endif +#ifdef GCOLLECT + config |= C_GCOLLECT; +#endif + +#ifdef SEND_SHORTLIST + config |= C_SEND_SHORTLIST; +#endif + #define BFLAG_LENGTH 35 - CREATE(buf, char, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 ); + CREATE(buf, char, 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) + 1 ); /* build packet */ WBUFW(buf,0) = 0x3000; - WBUFW(buf,2) = 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ); - WBUFW(buf,4) = 0x9c; + WBUFW(buf,2) = 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ); + WBUFW(buf,4) = 0x9e; safestrncpy((char*)WBUFP(buf,6), date, 12); safestrncpy((char*)WBUFP(buf,6 + 12), time_c, 9); safestrncpy((char*)WBUFP(buf,6 + 12 + 9), timestring, 24); - WBUFL(buf,6 + 12 + 9 + 24) = rev; - WBUFL(buf,6 + 12 + 9 + 24 + 4) = map_getusers(); + safestrncpy((char*)WBUFP(buf,6 + 12 + 9 + 24), git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown", 41); + WBUFL(buf,6 + 12 + 9 + 24 + 41) = map_getusers(); - WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4) = config; - WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4) = bd_size; + WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4) = config; + WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4 + 4) = bd_size; for( i = 0; i < bd_size; i++ ) { - safestrncpy((char*)WBUFP(buf,6 + 12 + 9+ 24 + 4 + 4 + 4 + 4 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, 35); - WBUFL(buf,6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val; + safestrncpy((char*)WBUFP(buf,6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( i * ( BFLAG_LENGTH + 4 ) ) ), battle_data[i].str, 35); + WBUFL(buf,6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + BFLAG_LENGTH + ( i * ( BFLAG_LENGTH + 4 ) ) ) = *battle_data[i].val; } - chrif_send_report(buf, 6 + 12 + 9 + 24 + 4 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) ); + chrif_send_report(buf, 6 + 12 + 9 + 24 + 41 + 4 + 4 + 4 + ( bd_size * ( BFLAG_LENGTH + 4 ) ) ); aFree(buf); #undef BFLAG_LENGTH } -static int rAthena_report_timer(int tid, unsigned int tick, int id, intptr_t data) { +static int Hercules_report_timer(int tid, unsigned int tick, int id, intptr_t data) { if( chrif_isconnected() ) {/* char server relays it, so it must be online. */ - rAthena_report(__DATE__,__TIME__); + Hercules_report(__DATE__,__TIME__); } return 0; } @@ -6041,15 +6116,13 @@ int battle_get_value(const char* w1) return *battle_data[i].val; } -void battle_set_defaults() -{ +void battle_set_defaults(void) { int i; for (i = 0; i < ARRAYLENGTH(battle_data); i++) *battle_data[i].val = battle_data[i].defval; } -void battle_adjust_conf() -{ +void battle_adjust_conf(void) { battle_config.monster_max_aspd = 2000 - battle_config.monster_max_aspd*10; battle_config.max_aspd = 2000 - battle_config.max_aspd*10; battle_config.max_third_aspd = 2000 - battle_config.max_third_aspd*10; @@ -6092,12 +6165,11 @@ void battle_adjust_conf() int battle_config_read(const char* cfgName) { - char line[1024], w1[1024], w2[1024]; FILE* fp; static int count = 0; if (count == 0) - battle_set_defaults(); + battle->config_set_defaults(); count++; @@ -6106,6 +6178,7 @@ int battle_config_read(const char* cfgName) ShowError("File not found: %s\n", cfgName); else { + char line[1024], w1[1024], w2[1024]; while(fgets(line, sizeof(line), fp)) { if (line[0] == '/' && line[1] == '/') @@ -6113,9 +6186,9 @@ int battle_config_read(const char* cfgName) if (sscanf(line, "%1023[^:]:%1023s", w1, w2) != 2) continue; if (strcmpi(w1, "import") == 0) - battle_config_read(w2); + battle->config_read(w2); else - if (battle_set_value(w1, w2) == 0) + if (battle->config_set_value(w1, w2) == 0) ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName); } @@ -6124,25 +6197,72 @@ int battle_config_read(const char* cfgName) count--; - if (count == 0) - battle_adjust_conf(); + if (count == 0) { + battle->config_adjust(); + clif->bc_ready(); + } return 0; } -void do_init_battle(void) -{ +void do_init_battle(void) { delay_damage_ers = ers_new(sizeof(struct delay_damage),"battle.c::delay_damage_ers",ERS_OPT_CLEAR); add_timer_func_list(battle_delay_damage_sub, "battle_delay_damage_sub"); #ifndef STATS_OPT_OUT - add_timer_func_list(rAthena_report_timer, "rAthena_report_timer"); - add_timer_interval(gettick()+30000, rAthena_report_timer, 0, 0, 60000 * 30); + add_timer_func_list(Hercules_report_timer, "Hercules_report_timer"); + add_timer_interval(gettick()+30000, Hercules_report_timer, 0, 0, 60000 * 30); #endif } -void do_final_battle(void) -{ +void do_final_battle(void) { ers_destroy(delay_damage_ers); } + +/* initialize the interface */ +void battle_defaults(void) { + battle = &battle_s; + battle->init = do_init_battle; + battle->final = do_final_battle; + battle->calc_attack = battle_calc_attack; + battle->calc_damage = battle_calc_damage; + battle->calc_gvg_damage = battle_calc_gvg_damage; + battle->calc_bg_damage = battle_calc_bg_damage; + battle->calc_base_damage = battle_calc_base_damage; + battle->calc_misc_attack = battle_calc_misc_attack; + battle->calc_magic_attack = battle_calc_magic_attack; + battle->weapon_attack = battle_weapon_attack; + battle->delay_damage = battle_delay_damage; + battle->drain = battle_drain; + battle->calc_return_damage = battle_calc_return_damage; + battle->calc_weapon_attack = battle_calc_weapon_attack; + battle->attr_ratio = battle_attr_ratio; + battle->attr_fix = battle_attr_fix; + battle->calc_cardfix = battle_calc_cardfix; + battle->get_master = battle_get_master; + battle->get_targeted = battle_gettargeted; + battle->get_enemy = battle_getenemy; + battle->get_target = battle_gettarget; + battle->get_current_skill = battle_getcurrentskill; + battle->check_undead = battle_check_undead; + battle->check_target = battle_check_target; + battle->check_range = battle_check_range; + battle->consume_ammo = battle_consume_ammo; + battle->get_targeted_sub = battle_gettargeted_sub; + battle->get_enemy_sub = battle_getenemy_sub; + battle->get_enemy_area_sub = battle_getenemyarea_sub; + battle->delay_damage_sub = battle_delay_damage_sub; + battle->blewcount_bonus = battle_blewcount_bonus; + battle->range_type = battle_range_type; + battle->adjust_skill_damage = battle_adjust_skill_damage; + battle->add_mastery = battle_addmastery; + battle->calc_drain = battle_calc_drain; + battle->config_read = battle_config_read; + battle->config_set_defaults = battle_set_defaults; + battle->config_set_value = battle_set_value; + battle->config_get_value = battle_get_value; + battle->config_adjust = battle_adjust_conf; + battle->get_enemy_area = battle_getenemyarea; + battle->damage_area = battle_damage_area; +} diff --git a/src/map/battle.h b/src/map/battle.h index 1c1b1d38c..0975d978d 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -1,52 +1,35 @@ -// 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 _BATTLE_H_ #define _BATTLE_H_ -// state of a single attack attempt; used in flee/def penalty calculations when mobbed -typedef enum damage_lv { - ATK_NONE, // not an attack - ATK_LUCKY, // attack was lucky-dodged - ATK_FLEE, // attack was dodged - ATK_MISS, // attack missed because of element/race modifier. - ATK_BLOCK, // attack was blocked by some skills. - ATK_DEF // attack connected -} damage_lv; - -// dammage structure -struct Damage { - int damage,damage2; //right, left dmg - int type,div_; //chk clif_damage for type @TODO add an enum ? ; nb of hit - int amotion,dmotion; - int blewcount; //nb of knockback - int flag; //chk BF_* flag, (enum below) - enum damage_lv dmg_lv; //ATK_LUCKY,ATK_FLEE,ATK_DEF -}; - -//(Used in read pc.c,) attribute table (battle_attr_fix) -extern int attr_fix_table[4][10][10]; - +/** + * Declarations + **/ struct map_session_data; struct mob_data; struct block_list; +struct weapon_atk; +struct status_change; +struct status_data; -// Damage Calculation - -struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int count); - -int battle_calc_return_damage(struct block_list *bl, struct block_list *src, int *, int flag, uint16 skill_id); - -void battle_drain(struct map_session_data *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss); +/** + * Defines + **/ +#define MIN_HAIR_STYLE battle_config.min_hair_style +#define MAX_HAIR_STYLE battle_config.max_hair_style +#define MIN_HAIR_COLOR battle_config.min_hair_color +#define MAX_HAIR_COLOR battle_config.max_hair_color +#define MIN_CLOTH_COLOR battle_config.min_cloth_color +#define MAX_CLOTH_COLOR battle_config.max_cloth_color -int battle_attr_ratio(int atk_elem,int def_type, int def_lv); -int battle_attr_fix(struct block_list *src, struct block_list *target, int damage,int atk_elem,int def_type, int def_lv); -int battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag); +#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru] -// Final calculation Damage -int battle_calc_damage(struct block_list *src,struct block_list *bl,struct Damage *d,int damage,uint16 skill_id,uint16 skill_lv); -int battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,uint16 skill_id,uint16 skill_lv,int flag); -int battle_calc_bg_damage(struct block_list *src,struct block_list *bl,int damage,int div_,uint16 skill_id,uint16 skill_lv,int flag); +/** + * Enumerations + **/ enum { // Flag of the final calculation BF_WEAPON = 0x0001, @@ -61,20 +44,17 @@ enum { // Flag of the final calculation BF_SKILLMASK= 0x0f00, }; -int battle_delay_damage (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int damage, enum damage_lv dmg_lv, int ddelay); - -// Summary normal attack treatment (basic attack) -enum damage_lv battle_weapon_attack( struct block_list *bl,struct block_list *target,unsigned int tick,int flag); - -// Accessors -struct block_list* battle_get_master(struct block_list *src); -struct block_list* battle_gettargeted(struct block_list *target); -struct block_list* battle_getenemy(struct block_list *target, int type, int range); -int battle_gettarget(struct block_list *bl); -int battle_getcurrentskill(struct block_list *bl); +// state of a single attack attempt; used in flee/def penalty calculations when mobbed +typedef enum damage_lv { + ATK_NONE, // not an attack + ATK_LUCKY, // attack was lucky-dodged + ATK_FLEE, // attack was dodged + ATK_MISS, // attack missed because of element/race modifier. + ATK_BLOCK, // attack was blocked by some skills. + ATK_DEF // attack connected +} damage_lv; -enum e_battle_check_target -{//New definitions [Skotlex] +enum e_battle_check_target { //New definitions [Skotlex] BCT_ENEMY = 0x020000, BCT_NOENEMY = 0x1d0000, //This should be (~BCT_ENEMY&BCT_ALL) BCT_PARTY = 0x040000, @@ -87,24 +67,21 @@ enum e_battle_check_target BCT_NEUTRAL = 0x100000, }; -#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru] - -int battle_check_undead(int race,int element); -int battle_check_target(struct block_list *src, struct block_list *target,int flag); -bool battle_check_range(struct block_list *src,struct block_list *bl,int range); - -void battle_consume_ammo(struct map_session_data* sd, int skill, int lv); -// Settings +/** + * Structures + **/ -#define MIN_HAIR_STYLE battle_config.min_hair_style -#define MAX_HAIR_STYLE battle_config.max_hair_style -#define MIN_HAIR_COLOR battle_config.min_hair_color -#define MAX_HAIR_COLOR battle_config.max_hair_color -#define MIN_CLOTH_COLOR battle_config.min_cloth_color -#define MAX_CLOTH_COLOR battle_config.max_cloth_color +// dammage structure +struct Damage { + int damage,damage2; //right, left dmg + int type,div_; //chk clif_damage for type @TODO add an enum ? ; nb of hit + int amotion,dmotion; + int blewcount; //nb of knockback + int flag; //chk BF_* flag, (enum below) + enum damage_lv dmg_lv; //ATK_LUCKY,ATK_FLEE,ATK_DEF +}; -extern struct Battle_Config -{ +struct Battle_Config { int warp_point_debug; int enable_critical; int mob_critical_rate; @@ -184,7 +161,7 @@ extern struct Battle_Config int emergency_call; int guild_aura; int pc_invincible_time; - + int pet_catch_rate; int pet_rename; int pet_friendly_rate; @@ -204,7 +181,7 @@ extern struct Battle_Config int pet_max_atk2; //[Skotlex] int pet_no_gvg; //Disables pets in gvg. [Skotlex] int pet_equip_required; - + int skill_min_damage; int finger_offensive_type; int heal_exp; @@ -220,6 +197,7 @@ extern struct Battle_Config int wedding_ignorepalette; //[Skotlex] int xmas_ignorepalette; // [Valaris] int summer_ignorepalette; // [Zephyrus] + int hanbok_ignorepalette; int natural_healhp_interval; int natural_healsp_interval; int natural_heal_skill_interval; @@ -255,17 +233,7 @@ extern struct Battle_Config int pc_cloak_check_type; int monster_cloak_check_type; int estimation_type; - int gvg_short_damage_rate; - int gvg_long_damage_rate; - int gvg_weapon_damage_rate; - int gvg_magic_damage_rate; - int gvg_misc_damage_rate; int gvg_flee_penalty; - int pk_short_damage_rate; - int pk_long_damage_rate; - int pk_weapon_damage_rate; - int pk_magic_damage_rate; - int pk_misc_damage_rate; int mob_changetarget_byskill; int attack_direction_change; int land_skill_limit; @@ -285,9 +253,9 @@ extern struct Battle_Config int show_picker_item_type; int attack_attr_none; int item_rate_mvp, item_rate_common, item_rate_common_boss, item_rate_card, item_rate_card_boss, - item_rate_equip, item_rate_equip_boss, item_rate_heal, item_rate_heal_boss, item_rate_use, - item_rate_use_boss, item_rate_treasure, item_rate_adddrop; - + item_rate_equip, item_rate_equip_boss, item_rate_heal, item_rate_heal_boss, item_rate_use, + item_rate_use_boss, item_rate_treasure, item_rate_adddrop; + int logarithmic_drops; int item_drop_common_min,item_drop_common_max; // Added by TyrNemesis^ int item_drop_card_min,item_drop_card_max; @@ -297,9 +265,9 @@ extern struct Battle_Config int item_drop_use_min,item_drop_use_max; //End int item_drop_treasure_min,item_drop_treasure_max; //by [Skotlex] int item_drop_adddrop_min,item_drop_adddrop_max; //[Skotlex] - + int prevent_logout; // Added by RoVeRT - + int alchemist_summon_reward; // [Valaris] int drops_by_luk; int drops_by_luk2; @@ -310,10 +278,10 @@ extern struct Battle_Config int max_exp_gain_rate; //Max amount of exp bar % you can get in one go. int pk_mode; int pk_level_range; - + int manner_system; // end additions [Valaris] int show_mob_info; - + int gx_allhit; int gx_disptype; int devotion_level_difference; @@ -329,14 +297,13 @@ extern struct Battle_Config int bone_drop; int buyer_name; int dancing_weaponswitch_fix; - -// eAthena additions + + // eAthena additions int night_at_start; // added by [Yor] int day_duration; // added by [Yor] int night_duration; // added by [Yor] int ban_hack_trade; // added by [Yor] - int packet_ver_flag; // added by [Yor] - + int min_hair_style; // added by [MouseJstr] int max_hair_style; // added by [MouseJstr] int min_hair_color; // added by [MouseJstr] @@ -344,12 +311,12 @@ extern struct Battle_Config int min_cloth_color; // added by [MouseJstr] int max_cloth_color; // added by [MouseJstr] int pet_hair_style; // added by [Skotlex] - + int castrate_dex_scale; // added by [MouseJstr] int area_size; // added by [MouseJstr] - + int max_def, over_def_bonus; //added by [Skotlex] - + int zeny_from_mobs; // [Valaris] int mobs_level_up; // [Valaris] int mobs_level_up_exp_rate; // [Valaris] @@ -371,12 +338,12 @@ extern struct Battle_Config int delay_battle_damage; int hide_woe_damage; int display_version; - + int display_hallucination; // [Skotlex] int use_statpoint_table; // [Skotlex] - + int ignore_items_gender; //[Lupus] - + int copyskill_restrict; // [Aru] int berserk_cancels_buffs; // [Aru] int debuff_on_logout; // Removes a few "official" negative Scs on logout. [Skotlex] @@ -387,26 +354,25 @@ extern struct Battle_Config int mob_remove_delay; // Dynamic Mobs - delay before removing mobs from a map [Skotlex] int mob_active_time; //Duration through which mobs execute their Hard AI after players leave their area of sight. int boss_active_time; - + int show_hp_sp_drain, show_hp_sp_gain; //[Skotlex] - + int mob_npc_event_type; //Determines on who the npc_event is executed. [Skotlex] - + int character_size; // if riders have size=2, and baby class riders size=1 [Lupus] - int mob_max_skilllvl; // Max possible skill level [Lupus] int rare_drop_announce; // chance <= to show rare drops global announces - + int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex] - + int duel_allow_pvp; // [LuzZza] int duel_allow_gvg; // [LuzZza] int duel_allow_teleport; // [LuzZza] int duel_autoleave_when_die; // [LuzZza] int duel_time_interval; // [LuzZza] int duel_only_on_same_map; // [Toms] - + int skip_teleport_lv1_menu; // possibility to disable (skip) Teleport Lv1 menu, that have only two lines `Random` and `Cancel` [LuzZza] - + int mob_max_skilllvl; int allow_skill_without_day; // [Komurka] int allow_es_magic_pc; // [Skotlex] int skill_wall_check; // [Skotlex] @@ -415,11 +381,9 @@ extern struct Battle_Config int sc_castcancel; // [Skotlex] int pc_sc_def_rate; // [Skotlex] int mob_sc_def_rate; - int pc_luk_sc_def; - int mob_luk_sc_def; int pc_max_sc_def; int mob_max_sc_def; - + int sg_angel_skill_ratio; int sg_miracle_skill_ratio; int sg_miracle_skill_duration; @@ -459,45 +423,120 @@ extern struct Battle_Config int client_limit_unit_lv; int hom_max_level; int hom_S_max_level; - + // [BattleGround Settings] int bg_update_interval; - int bg_short_damage_rate; - int bg_long_damage_rate; - int bg_weapon_damage_rate; - int bg_magic_damage_rate; - int bg_misc_damage_rate; int bg_flee_penalty; - + // rAthena int max_third_parameter; int max_baby_third_parameter; int atcommand_max_stat_bypass; int max_third_aspd; int vcast_stat_scale; - + int mvp_tomb_enabled; - + int atcommand_suggestions_enabled; - int min_npc_vending_distance; + int min_npc_vendchat_distance; int atcommand_mobinfo_type; - + int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95] + + /** Hercules **/ + int skill_trap_type; + int item_restricted_consumption_type; + int max_walk_path; + int item_enabled_npc; + + int gm_ignore_warpable_area; + } battle_config; -void do_init_battle(void); -void do_final_battle(void); -extern int battle_config_read(const char *cfgName); -extern void battle_validate_conf(void); -extern void battle_set_defaults(void); -int battle_set_value(const char* w1, const char* w2); -int battle_get_value(const char* w1); -// -struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int range, int type, int ignore_id); /** - * Royal Guard + * Vars **/ -int battle_damage_area( struct block_list *bl, va_list ap); +//attribute table +extern int attr_fix_table[4][10][10]; +/** + * Battle.c Interface + **/ +struct battle_interface { + /* init */ + void (*init) (void); + /* final */ + void (*final) (void); + /* damage calculation */ + struct Damage (*calc_attack) (int attack_type, struct block_list *bl, struct block_list *target, uint16 skill_id, uint16 skill_lv, int count); + /* generic final damage calculation */ + int (*calc_damage) (struct block_list *src, struct block_list *bl, struct Damage *d, int damage, uint16 skill_id, uint16 skill_lv); + /* gvg final damage calculation */ + int (*calc_gvg_damage) (struct block_list *src, struct block_list *bl, int damage, int div_, uint16 skill_id, uint16 skill_lv, int flag); + /* battlegrounds final damage calculation */ + int (*calc_bg_damage) (struct block_list *src, struct block_list *bl, int damage, int div_, uint16 skill_id, uint16 skill_lv, int flag); + /* normal weapon attack */ + enum damage_lv (*weapon_attack) (struct block_list *bl, struct block_list *target, unsigned int tick, int flag); + /* calculate weapon attack */ + struct Damage (*calc_weapon_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag); + /* delays damage or skills by a timer */ + int (*delay_damage) (unsigned int tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects); + /* drain damage */ + void (*drain) (struct map_session_data *sd, struct block_list *tbl, int rdamage, int ldamage, int race, int boss); + /* damage return/reflect */ + int (*calc_return_damage) (struct block_list *bl, struct block_list *src, int *, int flag, uint16 skill_id); + /* attribute rate */ + int (*attr_ratio) (int atk_elem, int def_type, int def_lv); + /* applies attribute modifiers */ + int (*attr_fix) (struct block_list *src, struct block_list *target, int damage, int atk_elem, int def_type, int def_lv); + /* applies card modifiers */ + int (*calc_cardfix) (int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int damage, int left, int flag); + /* get master (who does this unit respond to?) */ + struct block_list *(*get_master) (struct block_list *src); + /* returns a random unit who is targeting this unit */ + struct block_list *(*get_targeted) (struct block_list *target); + /* picks a random enemy unit who is in the area of sight */ + struct block_list *(*get_enemy) (struct block_list *target, int type, int range); + /* the target id (if any) of this unit */ + int (*get_target) (struct block_list *bl); + /* the current skill being processed/casted by this unit */ + int (*get_current_skill) (struct block_list *bl); + /* is either this race or element enough to be considered undead? */ + int (*check_undead) (int race,int element); + /* check if src and target are part of flag (e.g. enemies or allies) */ + int (*check_target) (struct block_list *src, struct block_list *target,int flag); + /* is src and bl within range? */ + bool (*check_range) (struct block_list *src,struct block_list *bl,int range); + /* consume amo for this skill and lv */ + void (*consume_ammo) (struct map_session_data* sd, int skill, int lv); + int (*get_targeted_sub) (struct block_list *bl, va_list ap); + int (*get_enemy_sub) (struct block_list *bl, va_list ap); + int (*get_enemy_area_sub) (struct block_list *bl, va_list ap); + int (*delay_damage_sub) (int tid, unsigned int tick, int id, intptr_t data); + int (*blewcount_bonus) (struct map_session_data *sd, uint16 skill_id); + /* skill range criteria */ + int (*range_type) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv); + int (*calc_base_damage) (struct status_data *status, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag); + struct Damage (*calc_misc_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); + struct Damage (*calc_magic_attack) (struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag); + int (*adjust_skill_damage) (int m, unsigned short skill_id); + int (*add_mastery) (struct map_session_data *sd,struct block_list *target,int dmg,int type); + int (*calc_drain) (int damage, int rate, int per); + /* - battle_config */ + int (*config_read) (const char *cfgName); + void (*config_set_defaults) (void); + int (*config_set_value) (const char* w1, const char* w2); + int (*config_get_value) (const char* w1); + void (*config_adjust) (void); + /* ----------------------------------------- */ + /* picks a random enemy within the specified range */ + struct block_list* (*get_enemy_area) (struct block_list *src, int x, int y, int range, int type, int ignore_id); + /* damages area, originally for royal guard's reflect damage */ + int (*damage_area) ( struct block_list *bl, va_list ap); +} battle_s; + +struct battle_interface *battle; + +void battle_defaults(void); #endif /* _BATTLE_H_ */ diff --git a/src/map/battleground.c b/src/map/battleground.c index 7b605066d..618679406 100644 --- a/src/map/battleground.c +++ b/src/map/battleground.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -71,7 +72,7 @@ int bg_team_warp(int bg_id, unsigned short mapindex, short x, short y) int bg_send_dot_remove(struct map_session_data *sd) { if( sd && sd->bg_id ) - clif_bg_xy_remove(sd); + clif->bg_xy_remove(sd); return 0; } @@ -92,16 +93,16 @@ int bg_team_join(int bg_id, struct map_session_data *sd) bg->members[i].y = sd->bl.y; bg->count++; - guild_send_dot_remove(sd); + guild->send_dot_remove(sd); for( i = 0; i < MAX_BG_MEMBERS; i++ ) { if( (pl_sd = bg->members[i].sd) != NULL && pl_sd != sd ) - clif_hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp); + clif->hpmeter_single(sd->fd, pl_sd->bl.id, pl_sd->battle_status.hp, pl_sd->battle_status.max_hp); } - clif_bg_hp(sd); - clif_bg_xy(sd); + clif->bg_hp(sd); + clif->bg_xy(sd); return 1; } @@ -130,7 +131,7 @@ int bg_team_leave(struct map_session_data *sd, int flag) sprintf(output, "Server : %s has quit the game...", sd->status.name); else sprintf(output, "Server : %s is leaving the battlefield...", sd->status.name); - clif_bg_message(bg, 0, "Server", output, strlen(output) + 1); + clif->bg_message(bg, 0, "Server", output, strlen(output) + 1); if( bg->logout_event[0] && flag ) npc_event(sd, bg->logout_event, 0); @@ -212,7 +213,7 @@ int bg_send_message(struct map_session_data *sd, const char *mes, int len) nullpo_ret(sd); if( sd->bg_id == 0 || (bg = bg_team_search(sd->bg_id)) == NULL ) return 0; - clif_bg_message(bg, sd->bl.id, sd->status.name, mes, len); + clif->bg_message(bg, sd->bl.id, sd->status.name, mes, len); return 0; } @@ -221,7 +222,7 @@ int bg_send_message(struct map_session_data *sd, const char *mes, int len) */ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) { - struct battleground_data *bg = db_data2ptr(data); + struct battleground_data *bg = DB->data2ptr(data); struct map_session_data *sd; int i; nullpo_ret(bg); @@ -233,7 +234,7 @@ int bg_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) { // xy update bg->members[i].x = sd->bl.x; bg->members[i].y = sd->bl.y; - clif_bg_xy(sd); + clif->bg_xy(sd); } } return 0; diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c index 8e3c21bd4..0b59e8f1e 100644 --- a/src/map/buyingstore.c +++ b/src/map/buyingstore.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/db.h" // ARR_FIND @@ -9,9 +10,10 @@ #include "atcommand.h" // msg_txt #include "battle.h" // battle_config.* #include "buyingstore.h" // struct s_buyingstore -#include "clif.h" // clif_buyingstore_* +#include "clif.h" // clif->buyingstore_* #include "log.h" // log_pick_pc, log_zeny #include "pc.h" // struct map_session_data +#include "chrif.h" /// constants (client-side restrictions) @@ -58,13 +60,13 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) if( map[sd->bl.m].flag.novending ) {// custom: no vending maps - clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" + clif->message(sd->fd, msg_txt(276)); // "You can't open a shop on this map" return false; } if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) {// custom: no vending cells - clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." + clif->message(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." return false; } @@ -75,7 +77,7 @@ bool buyingstore_setup(struct map_session_data* sd, unsigned char slots) } sd->buyingstore.slots = slots; - clif_buyingstore_open(sd); + clif->buyingstore_open(sd); return true; } @@ -94,15 +96,15 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha if( !battle_config.feature_buying_store || pc_istrading(sd) || sd->buyingstore.slots == 0 || count > sd->buyingstore.slots || zenylimit <= 0 || zenylimit > sd->status.zeny || !storename[0] ) {// disabled or invalid input sd->buyingstore.slots = 0; - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return; } if( !pc_can_give_items(sd) ) {// custom: GM is not allowed to buy (give zeny) sd->buyingstore.slots = 0; - clif_displaymessage(sd->fd, msg_txt(246)); - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + clif->message(sd->fd, msg_txt(246)); + clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return; } @@ -113,13 +115,13 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha if( map[sd->bl.m].flag.novending ) {// custom: no vending maps - clif_displaymessage(sd->fd, msg_txt(276)); // "You can't open a shop on this map" + clif->message(sd->fd, msg_txt(276)); // "You can't open a shop on this map" return; } if( map_getcell(sd->bl.m, sd->bl.x, sd->bl.y, CELL_CHKNOVENDING) ) {// custom: no vending cells - clif_displaymessage(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." + clif->message(sd->fd, msg_txt(204)); // "You can't open a shop on this cell." return; } @@ -174,14 +176,14 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha if( i != count ) {// invalid item/amount/price sd->buyingstore.slots = 0; - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); + clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE, 0); return; } if( (sd->max_weight*90)/100 < weight ) {// not able to carry all wanted items without getting overweight (90%) sd->buyingstore.slots = 0; - clif_buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight); + clif->buyingstore_open_failed(sd, BUYINGSTORE_CREATE_OVERWEIGHT, weight); return; } @@ -191,8 +193,8 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha sd->buyingstore.zenylimit = zenylimit; sd->buyingstore.slots = i; // store actual amount of items safestrncpy(sd->message, storename, sizeof(sd->message)); - clif_buyingstore_myitemlist(sd); - clif_buyingstore_entry(sd); + clif->buyingstore_myitemlist(sd); + clif->buyingstore_entry(sd); } @@ -205,7 +207,7 @@ void buyingstore_close(struct map_session_data* sd) memset(&sd->buyingstore, 0, sizeof(sd->buyingstore)); // notify other players - clif_buyingstore_disappear_entry(sd); + clif->buyingstore_disappear_entry(sd); } } @@ -221,7 +223,7 @@ void buyingstore_open(struct map_session_data* sd, int account_id) if( !pc_can_give_items(sd) ) {// custom: GM is not allowed to sell - clif_displaymessage(sd->fd, msg_txt(246)); + clif->message(sd->fd, msg_txt(246)); return; } @@ -230,13 +232,13 @@ void buyingstore_open(struct map_session_data* sd, int account_id) return; } - if( !searchstore_queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) + if( !searchstore->queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) {// out of view range return; } // success - clif_buyingstore_itemlist(sd, pl_sd); + clif->buyingstore_itemlist(sd, pl_sd); } @@ -253,30 +255,30 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int if( !battle_config.feature_buying_store || pc_istrading(sd) ) {// not allowed to sell - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( !pc_can_give_items(sd) ) {// custom: GM is not allowed to sell - clif_displaymessage(sd->fd, msg_txt(246)); - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + clif->message(sd->fd, msg_txt(246)); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } if( ( pl_sd = map_id2sd(account_id) ) == NULL || !pl_sd->state.buyingstore || pl_sd->buyer_id != buyer_id ) {// not online, not buying or not same store - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } - if( !searchstore_queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) + if( !searchstore->queryremote(sd, account_id) && ( sd->bl.m != pl_sd->bl.m || !check_distance_bl(&sd->bl, &pl_sd->bl, AREA_SIZE) ) ) {// out of view range - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, 0); return; } - searchstore_clearremote(sd); + searchstore->clearremote(sd); if( pl_sd->status.zeny < pl_sd->buyingstore.zenylimit ) {// buyer lost zeny in the mean time? fix the limit @@ -301,53 +303,53 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int {// duplicate ShowWarning("buyingstore_trade: Found duplicate item on selling list (prevnameid=%hu, prevamount=%hu, nameid=%hu, amount=%hu, account_id=%d, char_id=%d).\n", RBUFW(itemlist,k*6+2), RBUFW(itemlist,k*6+4), nameid, amount, sd->status.account_id, sd->status.char_id); - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } } if( index < 0 || index >= ARRAYLENGTH(sd->status.inventory) || sd->inventory_data[index] == NULL || sd->status.inventory[index].nameid != nameid || sd->status.inventory[index].amount < amount ) {// invalid input - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( sd->status.inventory[index].expire_time || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore_blankslots, sizeof(buyingstore_blankslots)) ) {// non-tradable item - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } ARR_FIND( 0, pl_sd->buyingstore.slots, listidx, pl_sd->buyingstore.items[listidx].nameid == nameid ); if( listidx == pl_sd->buyingstore.slots || pl_sd->buyingstore.items[listidx].amount == 0 ) {// there is no such item or the buyer has already bought all of them - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( pl_sd->buyingstore.items[listidx].amount < amount ) {// buyer does not need that much of the item - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_COUNT, nameid); return; } if( pc_checkadditem(pl_sd, nameid, amount) == ADDITEM_OVERAMOUNT ) {// buyer does not have enough space for this item - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } if( amount*(unsigned int)sd->inventory_data[index]->weight > pl_sd->max_weight-weight ) {// normally this is not supposed to happen, as the total weight is // checked upon creation, but the buyer could have gained items - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid); return; } weight+= amount*sd->inventory_data[index]->weight; if( amount*pl_sd->buyingstore.items[listidx].price > pl_sd->buyingstore.zenylimit-zeny ) {// buyer does not have enough zeny - clif_buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid); + clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_ZENY, nameid); return; } zeny+= amount*pl_sd->buyingstore.items[listidx].price; @@ -377,19 +379,24 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int pl_sd->buyingstore.zenylimit-= zeny; // notify clients - clif_buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price); - clif_buyingstore_update_item(pl_sd, nameid, amount); + clif->buyingstore_delete_item(sd, index, amount, pl_sd->buyingstore.items[listidx].price); + clif->buyingstore_update_item(pl_sd, nameid, amount); } + if( save_settings&128 ) { + chrif_save(sd, 0); + chrif_save(pl_sd, 0); + } + // check whether or not there is still something to buy ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 ); if( i == pl_sd->buyingstore.slots ) {// everything was bought - clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS); + clif->buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_NO_ITEMS); } else if( pl_sd->buyingstore.zenylimit == 0 ) {// zeny limit reached - clif_buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY); + clif->buyingstore_trade_failed_buyer(pl_sd, BUYINGSTORE_TRADE_BUYER_ZENY); } else {// continue buying @@ -463,7 +470,7 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st ; } - if( !searchstore_result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore_blankslots, 0) ) + if( !searchstore->result(s->search_sd, sd->buyer_id, sd->status.account_id, sd->message, it->nameid, it->amount, it->price, buyingstore_blankslots, 0) ) {// result set full return false; } @@ -471,3 +478,15 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st return true; } +void buyingstore_defaults(void) { + buyingstore = &buyingstore_s; + + buyingstore->setup = buyingstore_setup; + buyingstore->create = buyingstore_create; + buyingstore->close = buyingstore_close; + buyingstore->open = buyingstore_open; + buyingstore->trade = buyingstore_trade; + buyingstore->search = buyingstore_search; + buyingstore->searchall = buyingstore_searchall; + +} diff --git a/src/map/buyingstore.h b/src/map/buyingstore.h index 0ed6e5457..a416317be 100644 --- a/src/map/buyingstore.h +++ b/src/map/buyingstore.h @@ -1,5 +1,6 @@ -// 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 _BUYINGSTORE_H_ #define _BUYINGSTORE_H_ @@ -8,26 +9,30 @@ struct s_search_store_search; #define MAX_BUYINGSTORE_SLOTS 5 -struct s_buyingstore_item -{ +struct s_buyingstore_item { int price; unsigned short amount; unsigned short nameid; }; -struct s_buyingstore -{ +struct s_buyingstore { struct s_buyingstore_item items[MAX_BUYINGSTORE_SLOTS]; int zenylimit; unsigned char slots; }; -bool buyingstore_setup(struct map_session_data* sd, unsigned char slots); -void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count); -void buyingstore_close(struct map_session_data* sd); -void buyingstore_open(struct map_session_data* sd, int account_id); -void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count); -bool buyingstore_search(struct map_session_data* sd, unsigned short nameid); -bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_store_search* s); +struct buyingstore_interface { + bool (*setup) (struct map_session_data* sd, unsigned char slots); + void (*create) (struct map_session_data* sd, int zenylimit, unsigned char result, const char* storename, const uint8* itemlist, unsigned int count); + void (*close) (struct map_session_data* sd); + void (*open) (struct map_session_data* sd, int account_id); + void (*trade) (struct map_session_data* sd, int account_id, unsigned int buyer_id, const uint8* itemlist, unsigned int count); + bool (*search) (struct map_session_data* sd, unsigned short nameid); + bool (*searchall) (struct map_session_data* sd, const struct s_search_store_search* s); +} buyingstore_s; + +struct buyingstore_interface *buyingstore; + +void buyingstore_defaults (void); #endif // _BUYINGSTORE_H_ diff --git a/src/map/chat.c b/src/map/chat.c index dfeb16cad..a18e87eef 100644 --- a/src/map/chat.c +++ b/src/map/chat.c @@ -83,29 +83,28 @@ int chat_createpcchat(struct map_session_data* sd, const char* title, const char if( map[sd->bl.m].flag.nochat ) { - clif_displaymessage(sd->fd, msg_txt(281)); + clif->message(sd->fd, msg_txt(281)); return 0; //Can't create chatrooms on this map. } if( map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOCHAT) ) { - clif_displaymessage (sd->fd, msg_txt(665)); + clif->message (sd->fd, msg_txt(665)); return 0; } pc_stop_walking(sd,1); cd = chat_createchat(&sd->bl, title, pass, limit, pub, 0, "", 0, 1, MAX_LEVEL); - if( cd ) - { + if( cd ) { cd->users = 1; cd->usersd[0] = sd; pc_setchatid(sd,cd->bl.id); - clif_createchat(sd,0); - clif_dispchat(cd,0); - } - else - clif_createchat(sd,1); + pc_stop_attack(sd); + clif->createchat(sd,0); + clif->dispchat(cd,0); + } else + clif->createchat(sd,1); return 0; } @@ -122,32 +121,32 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) if( cd == NULL || cd->bl.type != BL_CHAT || cd->bl.m != sd->bl.m || sd->state.vending || sd->state.buyingstore || sd->chatID || ((cd->owner->type == BL_NPC) ? cd->users+1 : cd->users) >= cd->limit ) { - clif_joinchatfail(sd,0); + clif->joinchatfail(sd,0); return 0; } if( !cd->pub && strncmp(pass, cd->pass, sizeof(cd->pass)) != 0 && !pc_has_permission(sd, PC_PERM_JOIN_ALL_CHAT) ) { - clif_joinchatfail(sd,1); + clif->joinchatfail(sd,1); return 0; } if( sd->status.base_level < cd->minLvl || sd->status.base_level > cd->maxLvl ) { if(sd->status.base_level < cd->minLvl) - clif_joinchatfail(sd,5); + clif->joinchatfail(sd,5); else - clif_joinchatfail(sd,6); + clif->joinchatfail(sd,6); return 0; } if( sd->status.zeny < cd->zeny ) { - clif_joinchatfail(sd,4); + clif->joinchatfail(sd,4); return 0; } if( cd->owner->type != BL_NPC && idb_exists(cd->kick_list,sd->status.char_id) ) { - clif_joinchatfail(sd,2);//You have been kicked out of the room. + clif->joinchatfail(sd,2);//You have been kicked out of the room. return 0; } @@ -157,9 +156,9 @@ int chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) pc_setchatid(sd,cd->bl.id); - clif_joinchatok(sd, cd); //To the person who newly joined the list of all - clif_addchat(cd, sd); //Reports To the person who already in the chat - clif_dispchat(cd, 0); //Reported number of changes to the people around + clif->joinchatok(sd, cd); //To the person who newly joined the list of all + clif->addchat(cd, sd); //Reports To the person who already in the chat + clif->dispchat(cd, 0); //Reported number of changes to the people around chat_triggerevent(cd); //Event @@ -192,7 +191,7 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) return -1; } - clif_leavechat(cd, sd, kicked); + clif->leavechat(cd, sd, kicked); pc_setchatid(sd, 0); cd->users--; @@ -203,10 +202,10 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) if( cd->users == 0 && cd->owner->type == BL_PC ) { // Delete empty chatroom - struct skill_unit* unit = NULL; - struct skill_unit_group* group = NULL; + struct skill_unit* unit; + struct skill_unit_group* group; - clif_clearchat(cd, 0); + clif->clearchat(cd, 0); db_destroy(cd->kick_list); map_deliddb(&cd->bl); map_delblock(&cd->bl); @@ -215,7 +214,7 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) unit = map_find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0); group = (unit != NULL) ? unit->group : NULL; if (group != NULL) - ext_skill_unit_onplace(unit, &sd->bl, group->tick); + skill->unit_onplace(unit, &sd->bl, group->tick); return 1; } @@ -223,8 +222,8 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) if( leavechar == 0 && cd->owner->type == BL_PC ) { // Set and announce new owner cd->owner = (struct block_list*) cd->usersd[0]; - clif_changechatowner(cd, cd->usersd[0]); - clif_clearchat(cd, 0); + clif->changechatowner(cd, cd->usersd[0]); + clif->clearchat(cd, 0); //Adjust Chat location after owner has been changed. map_delblock( &cd->bl ); @@ -232,10 +231,10 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) cd->bl.y=cd->usersd[0]->bl.y; map_addblock( &cd->bl ); - clif_dispchat(cd,0); + clif->dispchat(cd,0); } else - clif_dispchat(cd,0); // refresh chatroom + clif->dispchat(cd,0); // refresh chatroom return 0; } @@ -260,11 +259,11 @@ int chat_changechatowner(struct map_session_data* sd, const char* nextownername) return -1; // name not found // erase temporarily - clif_clearchat(cd,0); + clif->clearchat(cd,0); // set new owner cd->owner = (struct block_list*) cd->usersd[i]; - clif_changechatowner(cd,cd->usersd[i]); + clif->changechatowner(cd,cd->usersd[i]); // swap the old and new owners' positions tmpsd = cd->usersd[i]; @@ -278,7 +277,7 @@ int chat_changechatowner(struct map_session_data* sd, const char* nextownername) map_addblock( &cd->bl ); // and display again - clif_dispchat(cd,0); + clif->dispchat(cd,0); return 0; } @@ -301,8 +300,8 @@ int chat_changechatstatus(struct map_session_data* sd, const char* title, const cd->limit = min(limit, ARRAYLENGTH(cd->usersd)); cd->pub = pub; - clif_changechatstatus(cd); - clif_dispchat(cd,0); + clif->changechatstatus(cd); + clif->dispchat(cd,0); return 0; } @@ -355,7 +354,7 @@ int chat_createnpcchat(struct npc_data* nd, const char* title, int limit, bool p if( cd ) { nd->chat_id = cd->bl.id; - clif_dispchat(cd,0); + clif->dispchat(cd,0); } return 0; @@ -372,7 +371,7 @@ int chat_deletenpcchat(struct npc_data* nd) return 0; chat_npckickall(cd); - clif_clearchat(cd, 0); + clif->clearchat(cd, 0); map_deliddb(&cd->bl); map_delblock(&cd->bl); map_freeblock(&cd->bl); diff --git a/src/map/chrif.c b/src/map/chrif.c index e109f7095..efe976942 100644 --- a/src/map/chrif.c +++ b/src/map/chrif.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -41,7 +42,7 @@ static DBMap* auth_db; // int id -> struct auth_node* static const int packet_len_table[0x3d] = { // U - used, F - free 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff 6,-1,18, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07 - 6,30, 0, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, F->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f + 6,30, -1, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f 11,10,10, 0,11, 0,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27 @@ -66,8 +67,8 @@ static const int packet_len_table[0x3d] = { // U - used, F - free //2b07: Outgoing, chrif_removefriend -> 'Tell charserver to remove friend_id from char_id friend list' //2b08: Outgoing, chrif_searchcharid -> '...' //2b09: Incoming, map_addchariddb -> 'Adds a name to the nick db' -//2b0a: FREE -//2b0b: FREE +//2b0a: Incoming/Outgoing, socket_datasync() +//2b0b: Outgoing, update charserv skillid2idx //2b0c: Outgoing, chrif_changeemail -> 'change mail address ...' //2b0d: Incoming, chrif_changedsex -> 'Change sex of acc XY' //2b0e: Outgoing, chrif_char_ask_name -> 'Do some operations (change sex, ban / unban etc)' @@ -246,7 +247,7 @@ int chrif_setip(const char* ip) { return 0; } - strncpy(char_ip_str, ip, sizeof(char_ip_str)); + safestrncpy(char_ip_str, ip, sizeof(char_ip_str)); ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(char_ip, ip_str)); @@ -309,8 +310,8 @@ int chrif_save(struct map_session_data *sd, int flag) { if( sd->status.pet_id > 0 && sd->pd ) intif_save_petdata(sd->status.account_id,&sd->pd->pet); - if( sd->hd && merc_is_hom_active(sd->hd) ) - merc_save(sd->hd); + if( sd->hd && homun_alive(sd->hd) ) + homun->save(sd->hd); if( sd->md && mercenary_get_lifetime(sd->md) > 0 ) mercenary_save(sd->md); if( sd->ed && elemental_get_lifetime(sd->ed) > 0 ) @@ -329,8 +330,8 @@ int chrif_connect(int fd) { memcpy(WFIFOP(fd,2), userid, NAME_LENGTH); memcpy(WFIFOP(fd,26), passwd, NAME_LENGTH); WFIFOL(fd,50) = 0; - WFIFOL(fd,54) = htonl(clif_getip()); - WFIFOW(fd,58) = htons(clif_getport()); + WFIFOL(fd,54) = htonl(clif->map_ip); + WFIFOW(fd,58) = htons(clif->map_port); WFIFOSET(fd,60); return 0; @@ -399,7 +400,7 @@ int chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port) { nullpo_retr(-1, sd); if (other_mapserver_count < 1) {//No other map servers are online! - clif_authfail_fd(sd->fd, 0); + clif->authfail_fd(sd->fd, 0); return -1; } @@ -434,9 +435,9 @@ int chrif_changemapserverack(int account_id, int login_id1, int login_id2, int c if ( !login_id1 ) { ShowError("map server change failed.\n"); - clif_authfail_fd(node->fd, 0); + clif->authfail_fd(node->fd, 0); } else - clif_changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port)); + clif->changemapserver(node->sd, map_index, x, y, ntohl(ip), ntohs(port)); //Player has been saved already, remove him from memory. [Skotlex] chrif_auth_delete(account_id, char_id, ST_MAPCHANGE); @@ -465,8 +466,11 @@ int chrif_connectack(int fd) { if( !char_init_done ) { char_init_done = true; ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc_event_doall("OnInterIfInitOnce")); - guild_castle_map_init(); + guild->castle_map_init(); } + + socket_datasync(fd, true); + chrif_skillid2idx(fd); return 0; } @@ -475,7 +479,7 @@ int chrif_connectack(int fd) { * @see DBApply */ static int chrif_reconnect(DBKey key, DBData *data, va_list ap) { - struct auth_node *node = db_data2ptr(data); + struct auth_node *node = DB->data2ptr(data); switch (node->state) { case ST_LOGIN: @@ -497,7 +501,7 @@ static int chrif_reconnect(DBKey key, DBData *data, va_list ap) { if( map_mapname2ipport(sd->mapindex,&ip,&port) == 0 ) chrif_changemapserver(sd, ip, port); else //too much lag/timeout is the closest explanation for this error. - clif_authfail_fd(sd->fd, 3); + clif->authfail_fd(sd->fd, 3); break; } @@ -525,7 +529,7 @@ void chrif_on_ready(void) { do_reconnect_storage(); //Re-save any guild castles that were modified in the disconnection time. - guild_castle_reconnect(-1, 0, 0); + guild->castle_reconnect(-1, 0, 0); } @@ -672,7 +676,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used ( node->sex == sex && node->state == ST_LOGIN ) {// found a match - clif_authfail_fd(node->fd, 0); + clif->authfail_fd(node->fd, 0); chrif_auth_delete(account_id, char_id, ST_LOGIN); } } @@ -683,7 +687,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used ( * @see DBApply */ int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) { - struct auth_node *node = db_data2ptr(data); + struct auth_node *node = DB->data2ptr(data); const char* states[] = { "Login", "Logout", "Map change" }; if(DIFF_TICK(gettick(),node->node_created)>60000) { @@ -810,10 +814,10 @@ int chrif_changesex(struct map_session_data *sd) { WFIFOW(char_fd,30) = 5; WFIFOSET(char_fd,44); - clif_displaymessage(sd->fd, msg_txt(408)); //"Need disconnection to perform change-sex request..." + clif->message(sd->fd, msg_txt(408)); //"Need disconnection to perform change-sex request..." if (sd->fd) - clif_authfail_fd(sd->fd, 15); + clif->authfail_fd(sd->fd, 15); else map_quit(sd); return 0; @@ -855,14 +859,14 @@ static void chrif_char_ask_name_answer(int acc, const char* player_name, uint16 default: output[0] = '\0'; break; } - clif_displaymessage(sd->fd, output); + clif->message(sd->fd, output); } /*========================================== * Request char server to change sex of char (modified by Yor) *------------------------------------------*/ int chrif_changedsex(int fd) { - int acc, sex, i; + int acc, sex; struct map_session_data *sd; acc = RFIFOL(fd,2); @@ -879,23 +883,26 @@ int chrif_changedsex(int fd) { // reset skill of some job if ((sd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER) { + int i, idx = 0; // remove specifical skills of Bard classes for(i = 315; i <= 322; i++) { - if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { - sd->status.skill_point += sd->status.skill[i].lv; - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; + idx = skill->get_index(i); + if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) { + sd->status.skill_point += sd->status.skill[idx].lv; + sd->status.skill[idx].id = 0; + sd->status.skill[idx].lv = 0; } } // remove specifical skills of Dancer classes for(i = 323; i <= 330; i++) { - if (sd->status.skill[i].id > 0 && sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) { - sd->status.skill_point += sd->status.skill[i].lv; - sd->status.skill[i].id = 0; - sd->status.skill[i].lv = 0; + idx = skill->get_index(i); + if (sd->status.skill[idx].id > 0 && sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT) { + sd->status.skill_point += sd->status.skill[idx].lv; + sd->status.skill[idx].id = 0; + sd->status.skill[idx].lv = 0; } } - clif_updatestatus(sd, SP_SKILLPOINT); + clif->updatestatus(sd, SP_SKILLPOINT); // change job if necessary if (sd->status.sex) //Changed from Dancer sd->status.class_ -= 1; @@ -906,7 +913,7 @@ int chrif_changedsex(int fd) { // save character sd->login_id1++; // change identify, because if player come back in char within the 5 seconds, he can change its characters // do same modify in login-server for the account, but no in char-server (it ask again login_id1 to login, and don't remember it) - clif_displaymessage(sd->fd, msg_txt(409)); //"Your sex has been changed (need disconnection by the server)..." + clif->message(sd->fd, msg_txt(409)); //"Your sex has been changed (need disconnection by the server)..." set_eof(sd->fd); // forced to disconnect for the change map_quit(sd); // Remove leftovers (e.g. autotrading) [Paradox924X] } @@ -959,21 +966,22 @@ int chrif_divorceack(int char_id, int partner_id) { *------------------------------------------*/ int chrif_deadopt(int father_id, int mother_id, int child_id) { struct map_session_data* sd; + int idx = skill->get_index(WE_CALLBABY); if( father_id && ( sd = map_charid2sd(father_id) ) != NULL && sd->status.child == child_id ) { sd->status.child = 0; - sd->status.skill[WE_CALLBABY].id = 0; - sd->status.skill[WE_CALLBABY].lv = 0; - sd->status.skill[WE_CALLBABY].flag = 0; - clif_deleteskill(sd,WE_CALLBABY); + sd->status.skill[idx].id = 0; + sd->status.skill[idx].lv = 0; + sd->status.skill[idx].flag = 0; + clif->deleteskill(sd,WE_CALLBABY); } if( mother_id && ( sd = map_charid2sd(mother_id) ) != NULL && sd->status.child == child_id ) { sd->status.child = 0; - sd->status.skill[WE_CALLBABY].id = 0; - sd->status.skill[WE_CALLBABY].lv = 0; - sd->status.skill[WE_CALLBABY].flag = 0; - clif_deleteskill(sd,WE_CALLBABY); + sd->status.skill[idx].id = 0; + sd->status.skill[idx].lv = 0; + sd->status.skill[idx].flag = 0; + clif->deleteskill(sd,WE_CALLBABY); } return 0; @@ -1002,18 +1010,18 @@ int chrif_accountban(int fd) { if (RFIFOB(fd,6) == 0) { // 0: change of statut, 1: ban int ret_status = RFIFOL(fd,7); // status or final date of a banishment if(0<ret_status && ret_status<=9) - clif_displaymessage(sd->fd, msg_txt(411+ret_status)); + clif->message(sd->fd, msg_txt(411+ret_status)); else if(ret_status==100) - clif_displaymessage(sd->fd, msg_txt(421)); + clif->message(sd->fd, msg_txt(421)); else - clif_displaymessage(sd->fd, msg_txt(420)); //"Your account has not more authorised." + clif->message(sd->fd, msg_txt(420)); //"Your account has not more authorised." } else if (RFIFOB(fd,6) == 1) { // 0: change of statut, 1: ban time_t timestamp; char tmpstr[2048]; timestamp = (time_t)RFIFOL(fd,7); // status or final date of a banishment strcpy(tmpstr, msg_txt(423)); //"Your account has been banished until " strftime(tmpstr + strlen(tmpstr), 24, "%d-%m-%Y %H:%M:%S", localtime(×tamp)); - clif_displaymessage(sd->fd, tmpstr); + clif->message(sd->fd, tmpstr); } set_eof(sd->fd); // forced to disconnect for the change @@ -1046,11 +1054,11 @@ int chrif_disconnectplayer(int fd) { } switch(RFIFOB(fd, 6)) { - case 1: clif_authfail_fd(sd->fd, 1); break; //server closed - case 2: clif_authfail_fd(sd->fd, 2); break; //someone else logged in - case 3: clif_authfail_fd(sd->fd, 4); break; //server overpopulated - case 4: clif_authfail_fd(sd->fd, 10); break; //out of available time paid for - case 5: clif_authfail_fd(sd->fd, 15); break; //forced to dc by gm + case 1: clif->authfail_fd(sd->fd, 1); break; //server closed + case 2: clif->authfail_fd(sd->fd, 2); break; //someone else logged in + case 3: clif->authfail_fd(sd->fd, 4); break; //server overpopulated + case 4: clif->authfail_fd(sd->fd, 10); break; //out of available time paid for + case 5: clif->authfail_fd(sd->fd, 15); break; //forced to dc by gm } return 0; } @@ -1347,7 +1355,7 @@ void chrif_update_ip(int fd) { if (new_ip && new_ip != char_ip) char_ip = new_ip; //Update char_ip - new_ip = clif_refresh_ip(); + new_ip = clif->refresh_ip(); if (!new_ip) return; //No change @@ -1366,6 +1374,24 @@ void chrif_keepalive(int fd) { void chrif_keepalive_ack(int fd) { session[fd]->flag.ping = 0;/* reset ping state, we received a packet */ } +void chrif_skillid2idx(int fd) { + int i, count = 0; + + if( fd == 0 ) fd = char_fd; + + WFIFOHEAD(fd,4 + (MAX_SKILL * 4)); + WFIFOW(fd,0) = 0x2b0b; + for(i = 0; i < MAX_SKILL; i++) { + if( skill_db[i].nameid ) { + WFIFOW(fd, 4 + (count*4)) = skill_db[i].nameid; + WFIFOW(fd, 6 + (count*4)) = i; + count++; + } + } + WFIFOW(fd,2) = 4 + (count * 4); + WFIFOSET(fd,4 + (count * 4)); + +} /*========================================== * *------------------------------------------*/ @@ -1423,10 +1449,11 @@ int chrif_parse(int fd) { case 0x2afb: chrif_sendmapack(fd); break; case 0x2afd: chrif_authok(fd); break; case 0x2b00: map_setusers(RFIFOL(fd,2)); chrif_keepalive(fd); break; - case 0x2b03: clif_charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break; + case 0x2b03: clif->charselectok(RFIFOL(fd,2), RFIFOB(fd,6)); break; case 0x2b04: chrif_recvmap(fd); break; case 0x2b06: chrif_changemapserverack(RFIFOL(fd,2), RFIFOL(fd,6), RFIFOL(fd,10), RFIFOL(fd,14), RFIFOW(fd,18), RFIFOW(fd,20), RFIFOW(fd,22), RFIFOL(fd,24), RFIFOW(fd,28)); break; case 0x2b09: map_addnickdb(RFIFOL(fd,2), (char*)RFIFOP(fd,6)); break; + case 0x2b0a: socket_datasync(fd, false); break; case 0x2b0d: chrif_changedsex(fd); break; case 0x2b0f: chrif_char_ask_name_answer(RFIFOL(fd,2), (char*)RFIFOP(fd,6), RFIFOW(fd,30), RFIFOW(fd,32)); break; case 0x2b12: chrif_divorceack(RFIFOL(fd,2), RFIFOL(fd,6)); break; @@ -1482,13 +1509,13 @@ int send_users_tochar(void) { iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) { + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { WFIFOL(char_fd,6+8*i) = sd->status.account_id; WFIFOL(char_fd,6+8*i+4) = sd->status.char_id; i++; } - mapit_free(iter); + mapit->free(iter); WFIFOW(char_fd,2) = 6 + 8*users; WFIFOW(char_fd,4) = users; @@ -1550,26 +1577,26 @@ int chrif_removefriend(int char_id, int friend_id) { } void chrif_send_report(char* buf, int len) { - #ifndef STATS_OPT_OUT - WFIFOHEAD(char_fd,len + 2); - - WFIFOW(char_fd,0) = 0x3008; - - memcpy(WFIFOP(char_fd,2), buf, len); - - WFIFOSET(char_fd,len + 2); - - flush_fifo(char_fd); /* ensure it's sent now. */ + if( char_fd ) { + WFIFOHEAD(char_fd,len + 2); + + WFIFOW(char_fd,0) = 0x3008; + + memcpy(WFIFOP(char_fd,2), buf, len); + + WFIFOSET(char_fd,len + 2); + + flush_fifo(char_fd); /* ensure it's sent now. */ + } #endif - } /** * @see DBApply */ int auth_db_final(DBKey key, DBData *data, va_list ap) { - struct auth_node *node = db_data2ptr(data); + struct auth_node *node = DB->data2ptr(data); if (node->char_dat) aFree(node->char_dat); @@ -1621,3 +1648,4 @@ int do_init_chrif(void) { return 0; } + diff --git a/src/map/chrif.h b/src/map/chrif.h index 0aadb1a7b..9c7142905 100644 --- a/src/map/chrif.h +++ b/src/map/chrif.h @@ -1,5 +1,6 @@ -// 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 _CHRIF_H_ #define _CHRIF_H_ @@ -65,5 +66,6 @@ int do_final_chrif(void); int do_init_chrif(void); int chrif_flush_fifo(void); +void chrif_skillid2idx(int fd); #endif /* _CHRIF_H_ */ diff --git a/src/map/clif.c b/src/map/clif.c index 961e3bf0c..0c5143ffd 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/socket.h" @@ -12,6 +13,7 @@ #include "../common/strlib.h" #include "../common/utils.h" #include "../common/ers.h" +#include "../common/conf.h" #include "map.h" #include "chrif.h" @@ -42,6 +44,8 @@ #include "clif.h" #include "mail.h" #include "quest.h" +#include "packets_struct.h" +#include "irc-bot.h" #include <stdio.h> #include <stdlib.h> @@ -49,28 +53,16 @@ #include <stdarg.h> #include <time.h> -/* for clif_clearunit_delayed */ -static struct eri *delay_clearunit_ers; - //#define DUMP_UNKNOWN_PACKET //#define DUMP_INVALID_PACKET -struct Clif_Config { - int packet_db_ver; //Preferred packet version. - int connect_cmd[MAX_PACKET_VER + 1]; //Store the connect command for all versions. [Skotlex] -} clif_config; - -struct s_packet_db packet_db[MAX_PACKET_VER + 1][MAX_PACKET_DB + 1]; - //Converts item type in case of pet eggs. -static inline int itemtype(int type) -{ +static inline int itemtype(int type) { return ( type == IT_PETEGG ) ? IT_WEAPON : type; } -static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsigned char dir) -{ +static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsigned char dir) { p += pos; p[0] = (uint8)(x>>2); p[1] = (uint8)((x<<6) | ((y>>4)&0x3f)); @@ -79,8 +71,7 @@ static inline void WBUFPOS(uint8* p, unsigned short pos, short x, short y, unsig // client-side: x0+=sx0*0.0625-0.5 and y0+=sy0*0.0625-0.5 -static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) -{ +static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) { p += pos; p[0] = (uint8)(x0>>2); p[1] = (uint8)((x0<<6) | ((y0>>4)&0x3f)); @@ -91,20 +82,17 @@ static inline void WBUFPOS2(uint8* p, unsigned short pos, short x0, short y0, sh } -static inline void WFIFOPOS(int fd, unsigned short pos, short x, short y, unsigned char dir) -{ +static inline void WFIFOPOS(int fd, unsigned short pos, short x, short y, unsigned char dir) { WBUFPOS(WFIFOP(fd,pos), 0, x, y, dir); } -static inline void WFIFOPOS2(int fd, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) -{ +static inline void WFIFOPOS2(int fd, unsigned short pos, short x0, short y0, short x1, short y1, unsigned char sx0, unsigned char sy0) { WBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0); } -static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short* y, unsigned char* dir) -{ +static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short* y, unsigned char* dir) { p += pos; if( x ) { @@ -121,8 +109,7 @@ static inline void RBUFPOS(const uint8* p, unsigned short pos, short* x, short* } -static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) -{ +static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) { p += pos; if( x0 ) { @@ -151,28 +138,24 @@ static inline void RBUFPOS2(const uint8* p, unsigned short pos, short* x0, short } -static inline void RFIFOPOS(int fd, unsigned short pos, short* x, short* y, unsigned char* dir) -{ +static inline void RFIFOPOS(int fd, unsigned short pos, short* x, short* y, unsigned char* dir) { RBUFPOS(RFIFOP(fd,pos), 0, x, y, dir); } -static inline void RFIFOPOS2(int fd, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) -{ +static inline void RFIFOPOS2(int fd, unsigned short pos, short* x0, short* y0, short* x1, short* y1, unsigned char* sx0, unsigned char* sy0) { RBUFPOS2(WFIFOP(fd,pos), 0, x0, y0, x1, y1, sx0, sy0); } //To idenfity disguised characters. -static inline bool disguised(struct block_list* bl) -{ - return (bool)( bl->type == BL_PC && ((TBL_PC*)bl)->disguise ); +static inline bool disguised(struct block_list* bl) { + return (bool)( bl->type == BL_PC && ((TBL_PC*)bl)->disguise != -1 ); } //Guarantees that the given string does not exceeds the allowed size, as well as making sure it's null terminated. [Skotlex] -static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned int max) -{ +static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned int max) { if( len > max ) len = max; @@ -181,38 +164,27 @@ static inline unsigned int mes_len_check(char* mes, unsigned int len, unsigned i return len; } - -static char map_ip_str[128]; -static uint32 map_ip; -static uint32 bind_ip = INADDR_ANY; -static uint16 map_port = 5121; -int map_fd; - -static int clif_parse (int fd); - /*========================================== * Ip setting of map-server *------------------------------------------*/ -int clif_setip(const char* ip) -{ +int clif_setip(const char* ip) { char ip_str[16]; - map_ip = host2ip(ip); - if (!map_ip) { + clif->map_ip = host2ip(ip); + if (!clif->map_ip) { ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); return 0; } - strncpy(map_ip_str, ip, sizeof(map_ip_str)); - ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(map_ip, ip_str)); + safestrncpy(clif->map_ip_str, ip, sizeof(clif->map_ip_str)); + ShowInfo("Map Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(clif->map_ip, ip_str)); return 1; } -void clif_setbindip(const char* ip) -{ - char ip_str[16]; - bind_ip = host2ip(ip); - if (bind_ip) { - ShowInfo("Map Server Bind IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(bind_ip, ip_str)); +void clif_setbindip(const char* ip) { + clif->bind_ip = host2ip(ip); + if (clif->bind_ip) { + char ip_str[16]; + ShowInfo("Map Server Bind IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(clif->bind_ip, ip_str)); } else { ShowWarning("Failed to Resolve Map Server Address! (%s)\n", ip); } @@ -224,7 +196,7 @@ void clif_setbindip(const char* ip) *------------------------------------------*/ void clif_setport(uint16 port) { - map_port = port; + clif->map_port = port; } /*========================================== @@ -232,21 +204,7 @@ void clif_setport(uint16 port) *------------------------------------------*/ uint32 clif_getip(void) { - return map_ip; -} - -//Refreshes map_server ip, returns the new ip if the ip changed, otherwise it returns 0. -uint32 clif_refresh_ip(void) -{ - uint32 new_ip; - - new_ip = host2ip(map_ip_str); - if (new_ip && new_ip != map_ip) { - map_ip = new_ip; - ShowInfo("Updating IP resolution of [%s].\n", map_ip_str); - return map_ip; - } - return 0; + return clif->map_ip; } /*========================================== @@ -254,23 +212,35 @@ uint32 clif_refresh_ip(void) *------------------------------------------*/ uint16 clif_getport(void) { - return map_port; + return clif->map_port; +} + +uint32 clif_refresh_ip(void) { + uint32 new_ip; + + new_ip = host2ip(clif->map_ip_str); + if (new_ip && new_ip != clif->map_ip) { + clif->map_ip = new_ip; + ShowInfo("Updating IP resolution of [%s].\n", clif->map_ip_str); + return clif->map_ip; + } + return 0; } #if PACKETVER >= 20071106 static inline unsigned char clif_bl_type(struct block_list *bl) { switch (bl->type) { - case BL_PC: return disguised(bl)?0x1:0x0; //PC_TYPE - case BL_ITEM: return 0x2; //ITEM_TYPE - case BL_SKILL: return 0x3; //SKILL_TYPE - case BL_CHAT: return 0x4; //UNKNOWN_TYPE - case BL_MOB: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE - case BL_NPC: return 0x6; //NPC_EVT_TYPE - case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE - case BL_HOM: return 0x8; //NPC_HOM_TYPE - case BL_MER: return 0x9; //NPC_MERSOL_TYPE - case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE - default: return 0x1; //NPC_TYPE + case BL_PC: return (disguised(bl) && !pcdb_checkid(status_get_viewdata(bl)->class_))? 0x1:0x0; //PC_TYPE + case BL_ITEM: return 0x2; //ITEM_TYPE + case BL_SKILL: return 0x3; //SKILL_TYPE + case BL_CHAT: return 0x4; //UNKNOWN_TYPE + case BL_MOB: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x5; //NPC_MOB_TYPE + case BL_NPC: return 0x6; //NPC_EVT_TYPE + case BL_PET: return pcdb_checkid(status_get_viewdata(bl)->class_)?0x0:0x7; //NPC_PET_TYPE + case BL_HOM: return 0x8; //NPC_HOM_TYPE + case BL_MER: return 0x9; //NPC_MERSOL_TYPE + case BL_ELEM: return 0xa; //NPC_ELEMENTAL_TYPE + default: return 0x1; //NPC_TYPE } } #endif @@ -285,57 +255,51 @@ static inline unsigned char clif_bl_type(struct block_list *bl) { * - AREA_WOS (AREA WITHOUT SELF) : Not run for self * - AREA_CHAT_WOC : Everyone in the area of your chat without a chat *------------------------------------------*/ -static int clif_send_sub(struct block_list *bl, va_list ap) -{ +int clif_send_sub(struct block_list *bl, va_list ap) { struct block_list *src_bl; struct map_session_data *sd; - unsigned char *buf; + void *buf; int len, type, fd; nullpo_ret(bl); nullpo_ret(sd = (struct map_session_data *)bl); fd = sd->fd; - if (!fd) //Don't send to disconnected clients. + if (!fd || session[fd] == NULL) //Don't send to disconnected clients. return 0; - buf = va_arg(ap,unsigned char*); + buf = va_arg(ap,void*); len = va_arg(ap,int); nullpo_ret(src_bl = va_arg(ap,struct block_list*)); type = va_arg(ap,int); - switch(type) - { - case AREA_WOS: - if (bl == src_bl) - return 0; - break; - case AREA_WOC: - if (sd->chatID || bl == src_bl) - return 0; - break; - case AREA_WOSC: - { - if(src_bl->type == BL_PC){ - struct map_session_data *ssd = (struct map_session_data *)src_bl; - if (ssd && sd->chatID && (sd->chatID == ssd->chatID)) - return 0; - } - else if(src_bl->type == BL_NPC) { - struct npc_data *nd = (struct npc_data *)src_bl; - if (nd && sd->chatID && (sd->chatID == nd->chat_id)) - return 0; + switch(type) { + case AREA_WOS: + if (bl == src_bl) + return 0; + break; + case AREA_WOC: + if (sd->chatID || bl == src_bl) + return 0; + break; + case AREA_WOSC: { + if(src_bl->type == BL_PC){ + struct map_session_data *ssd = (struct map_session_data *)src_bl; + if (ssd && sd->chatID && (sd->chatID == ssd->chatID)) + return 0; + } + else if(src_bl->type == BL_NPC) { + struct npc_data *nd = (struct npc_data *)src_bl; + if (nd && sd->chatID && (sd->chatID == nd->chat_id)) + return 0; + } } + break; } - break; - } - - if (session[fd] == NULL) - return 0; WFIFOHEAD(fd, len); if (WFIFOP(fd,0) == buf) { - ShowError("WARNING: Invalid use of clif_send function\n"); + ShowError("WARNING: Invalid use of clif->send function\n"); ShowError(" Packet x%4x use a WFIFO of a player instead of to use a buffer.\n", WBUFW(buf,0)); ShowError(" Please correct your code.\n"); // don't send to not move the pointer of the packet for next sessions in the loop @@ -344,10 +308,8 @@ static int clif_send_sub(struct block_list *bl, va_list ap) return 0; } - if (packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); return 0; } @@ -356,8 +318,7 @@ static int clif_send_sub(struct block_list *bl, va_list ap) * Packet Delegation (called on all packets that require data to be sent to more than one client) * functions that are sent solely to one use whose ID it posses use WFIFOSET *------------------------------------------*/ -int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type) -{ +int clif_send(const void* buf, int len, struct block_list* bl, enum send_target type) { int i; struct map_session_data *sd, *tsd; struct party_data *p = NULL; @@ -366,298 +327,250 @@ int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target int x0 = 0, x1 = 0, y0 = 0, y1 = 0, fd; struct s_mapiterator* iter; - if( type != ALL_CLIENT && type != CHAT_MAINCHAT ) + if( type != ALL_CLIENT ) nullpo_ret(bl); sd = BL_CAST(BL_PC, bl); switch(type) { - case ALL_CLIENT: //All player clients. - iter = mapit_getallusers(); - while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) - { - if( packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version + case ALL_CLIENT: //All player clients. + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit->next(iter)) != NULL ) { WFIFOHEAD(tsd->fd, len); memcpy(WFIFOP(tsd->fd,0), buf, len); WFIFOSET(tsd->fd,len); } - } - mapit_free(iter); - break; + mapit->free(iter); + break; - case ALL_SAMEMAP: //All players on the same map - iter = mapit_getallusers(); - while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) - { - if( bl->m == tsd->bl.m && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); + case ALL_SAMEMAP: //All players on the same map + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit->next(iter)) != NULL ) { + if( bl->m == tsd->bl.m ) { + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } } - } - mapit_free(iter); - break; + mapit->free(iter); + break; - case AREA: - case AREA_WOSC: - if (sd && bl->prev == NULL) //Otherwise source misses the packet.[Skotlex] - clif_send (buf, len, bl, SELF); - case AREA_WOC: - case AREA_WOS: - map_foreachinarea(clif_send_sub, bl->m, bl->x-AREA_SIZE, bl->y-AREA_SIZE, bl->x+AREA_SIZE, bl->y+AREA_SIZE, - BL_PC, buf, len, bl, type); - break; - case AREA_CHAT_WOC: - map_foreachinarea(clif_send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5), - bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC); - break; + case AREA: + case AREA_WOSC: + if (sd && bl->prev == NULL) //Otherwise source misses the packet.[Skotlex] + clif->send (buf, len, bl, SELF); + case AREA_WOC: + case AREA_WOS: + map_foreachinarea(clif->send_sub, bl->m, bl->x-AREA_SIZE, bl->y-AREA_SIZE, bl->x+AREA_SIZE, bl->y+AREA_SIZE, + BL_PC, buf, len, bl, type); + break; + case AREA_CHAT_WOC: + map_foreachinarea(clif->send_sub, bl->m, bl->x-(AREA_SIZE-5), bl->y-(AREA_SIZE-5), + bl->x+(AREA_SIZE-5), bl->y+(AREA_SIZE-5), BL_PC, buf, len, bl, AREA_WOC); + break; - case CHAT: - case CHAT_WOS: - { - struct chat_data *cd; - if (sd) { - cd = (struct chat_data*)map_id2bl(sd->chatID); - } else if (bl->type == BL_CHAT) { - cd = (struct chat_data*)bl; - } else break; - if (cd == NULL) - break; - for(i = 0; i < cd->users; i++) { - if (type == CHAT_WOS && cd->usersd[i] == sd) - continue; - if (packet_db[cd->usersd[i]->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - if ((fd=cd->usersd[i]->fd) >0 && session[fd]) // Added check to see if session exists [PoW] - { + case CHAT: + case CHAT_WOS: + { + struct chat_data *cd; + if (sd) { + cd = (struct chat_data*)map_id2bl(sd->chatID); + } else if (bl->type == BL_CHAT) { + cd = (struct chat_data*)bl; + } else break; + if (cd == NULL) + break; + for(i = 0; i < cd->users; i++) { + if (type == CHAT_WOS && cd->usersd[i] == sd) + continue; + if ((fd=cd->usersd[i]->fd) >0 && session[fd]) { // Added check to see if session exists [PoW] WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); } } } - } - break; - - case CHAT_MAINCHAT: //[LuzZza] - iter = mapit_getallusers(); - while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) - { - if( tsd->state.mainchat && tsd->chatID == 0 && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); - } - } - mapit_free(iter); - break; + break; - case PARTY_AREA: - case PARTY_AREA_WOS: - x0 = bl->x - AREA_SIZE; - y0 = bl->y - AREA_SIZE; - x1 = bl->x + AREA_SIZE; - y1 = bl->y + AREA_SIZE; - case PARTY: - case PARTY_WOS: - case PARTY_SAMEMAP: - case PARTY_SAMEMAP_WOS: - if (sd && sd->status.party_id) - p = party_search(sd->status.party_id); - - if (p) { - for(i=0;i<MAX_PARTY;i++){ - if( (sd = p->data[i].sd) == NULL ) - continue; + case PARTY_AREA: + case PARTY_AREA_WOS: + x0 = bl->x - AREA_SIZE; + y0 = bl->y - AREA_SIZE; + x1 = bl->x + AREA_SIZE; + y1 = bl->y + AREA_SIZE; + case PARTY: + case PARTY_WOS: + case PARTY_SAMEMAP: + case PARTY_SAMEMAP_WOS: + if (sd && sd->status.party_id) + p = party_search(sd->status.party_id); + + if (p) { + for(i=0;i<MAX_PARTY;i++){ + if( (sd = p->data[i].sd) == NULL ) + continue; - if( !(fd=sd->fd) ) - continue; + if( !(fd=sd->fd) ) + continue; - if( sd->bl.id == bl->id && (type == PARTY_WOS || type == PARTY_SAMEMAP_WOS || type == PARTY_AREA_WOS) ) - continue; + if( sd->bl.id == bl->id && (type == PARTY_WOS || type == PARTY_SAMEMAP_WOS || type == PARTY_AREA_WOS) ) + continue; - if( type != PARTY && type != PARTY_WOS && bl->m != sd->bl.m ) - continue; + if( type != PARTY && type != PARTY_WOS && bl->m != sd->bl.m ) + continue; - if( (type == PARTY_AREA || type == PARTY_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) - continue; + if( (type == PARTY_AREA || type == PARTY_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) + continue; - if( packet_db[sd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); } + if (!enable_spy) //Skip unnecessary parsing. [Skotlex] + break; + + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit->next(iter)) != NULL ) { + if( tsd->partyspy == p->party.party_id ) { + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } + } + mapit->free(iter); } - if (!enable_spy) //Skip unnecessary parsing. [Skotlex] - break; + break; + + case DUEL: + case DUEL_WOS: + if (!sd || !sd->duel_group) break; //Invalid usage. iter = mapit_getallusers(); - while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) - { - if( tsd->partyspy == p->party.party_id && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version + while( (tsd = (TBL_PC*)mapit->next(iter)) != NULL ) { + if( type == DUEL_WOS && bl->id == tsd->bl.id ) + continue; + if( sd->duel_group == tsd->duel_group ) { WFIFOHEAD(tsd->fd, len); memcpy(WFIFOP(tsd->fd,0), buf, len); WFIFOSET(tsd->fd,len); } } - mapit_free(iter); - } - break; - - case DUEL: - case DUEL_WOS: - if (!sd || !sd->duel_group) break; //Invalid usage. + mapit->free(iter); + break; - iter = mapit_getallusers(); - while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) - { - if( type == DUEL_WOS && bl->id == tsd->bl.id ) - continue; - if( sd->duel_group == tsd->duel_group && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); + case SELF: + if (sd && (fd=sd->fd) ) { + WFIFOHEAD(fd,len); + memcpy(WFIFOP(fd,0), buf, len); + WFIFOSET(fd,len); } - } - mapit_free(iter); - break; - - case SELF: - if (sd && (fd=sd->fd) && packet_db[sd->packet_ver][RBUFW(buf,0)].len) { // packet must exist for the client version - WFIFOHEAD(fd,len); - memcpy(WFIFOP(fd,0), buf, len); - WFIFOSET(fd,len); - } - break; - - // New definitions for guilds [Valaris] - Cleaned up and reorganized by [Skotlex] - case GUILD_AREA: - case GUILD_AREA_WOS: - x0 = bl->x - AREA_SIZE; - y0 = bl->y - AREA_SIZE; - x1 = bl->x + AREA_SIZE; - y1 = bl->y + AREA_SIZE; - case GUILD_SAMEMAP: - case GUILD_SAMEMAP_WOS: - case GUILD: - case GUILD_WOS: - case GUILD_NOBG: - if (sd && sd->status.guild_id) - g = guild_search(sd->status.guild_id); - - if (g) { - for(i = 0; i < g->max_member; i++) { - if( (sd = g->member[i].sd) != NULL ) - { - if( !(fd=sd->fd) ) - continue; - - if( type == GUILD_NOBG && sd->bg_id ) - continue; - - if( sd->bl.id == bl->id && (type == GUILD_WOS || type == GUILD_SAMEMAP_WOS || type == GUILD_AREA_WOS) ) - continue; - - if( type != GUILD && type != GUILD_NOBG && type != GUILD_WOS && sd->bl.m != bl->m ) - continue; - - if( (type == GUILD_AREA || type == GUILD_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) - continue; + break; - if( packet_db[sd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version + // New definitions for guilds [Valaris] - Cleaned up and reorganized by [Skotlex] + case GUILD_AREA: + case GUILD_AREA_WOS: + x0 = bl->x - AREA_SIZE; + y0 = bl->y - AREA_SIZE; + x1 = bl->x + AREA_SIZE; + y1 = bl->y + AREA_SIZE; + case GUILD_SAMEMAP: + case GUILD_SAMEMAP_WOS: + case GUILD: + case GUILD_WOS: + case GUILD_NOBG: + if (sd && sd->status.guild_id) + g = sd->guild; + + if (g) { + for(i = 0; i < g->max_member; i++) { + if( (sd = g->member[i].sd) != NULL ) { + if( !(fd=sd->fd) ) + continue; + + if( type == GUILD_NOBG && sd->bg_id ) + continue; + + if( sd->bl.id == bl->id && (type == GUILD_WOS || type == GUILD_SAMEMAP_WOS || type == GUILD_AREA_WOS) ) + continue; + + if( type != GUILD && type != GUILD_NOBG && type != GUILD_WOS && sd->bl.m != bl->m ) + continue; + + if( (type == GUILD_AREA || type == GUILD_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) + continue; WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); } } - } - if (!enable_spy) //Skip unnecessary parsing. [Skotlex] - break; + if (!enable_spy) //Skip unnecessary parsing. [Skotlex] + break; - iter = mapit_getallusers(); - while( (tsd = (TBL_PC*)mapit_next(iter)) != NULL ) - { - if( tsd->guildspy == g->guild_id && packet_db[tsd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version - WFIFOHEAD(tsd->fd, len); - memcpy(WFIFOP(tsd->fd,0), buf, len); - WFIFOSET(tsd->fd,len); + iter = mapit_getallusers(); + while( (tsd = (TBL_PC*)mapit->next(iter)) != NULL ) { + if( tsd->guildspy == g->guild_id ) { + WFIFOHEAD(tsd->fd, len); + memcpy(WFIFOP(tsd->fd,0), buf, len); + WFIFOSET(tsd->fd,len); + } } + mapit->free(iter); } - mapit_free(iter); - } - break; + break; - case BG_AREA: - case BG_AREA_WOS: - x0 = bl->x - AREA_SIZE; - y0 = bl->y - AREA_SIZE; - x1 = bl->x + AREA_SIZE; - y1 = bl->y + AREA_SIZE; - case BG_SAMEMAP: - case BG_SAMEMAP_WOS: - case BG: - case BG_WOS: - if( sd && sd->bg_id && (bg = bg_team_search(sd->bg_id)) != NULL ) - { - for( i = 0; i < MAX_BG_MEMBERS; i++ ) - { - if( (sd = bg->members[i].sd) == NULL || !(fd = sd->fd) ) - continue; - if( sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS) ) - continue; - if( type != BG && type != BG_WOS && sd->bl.m != bl->m ) - continue; - if( (type == BG_AREA || type == BG_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) - continue; - if( packet_db[sd->packet_ver][RBUFW(buf,0)].len ) - { // packet must exist for the client version + case BG_AREA: + case BG_AREA_WOS: + x0 = bl->x - AREA_SIZE; + y0 = bl->y - AREA_SIZE; + x1 = bl->x + AREA_SIZE; + y1 = bl->y + AREA_SIZE; + case BG_SAMEMAP: + case BG_SAMEMAP_WOS: + case BG: + case BG_WOS: + if( sd && sd->bg_id && (bg = bg_team_search(sd->bg_id)) != NULL ) { + for( i = 0; i < MAX_BG_MEMBERS; i++ ) { + if( (sd = bg->members[i].sd) == NULL || !(fd = sd->fd) ) + continue; + if( sd->bl.id == bl->id && (type == BG_WOS || type == BG_SAMEMAP_WOS || type == BG_AREA_WOS) ) + continue; + if( type != BG && type != BG_WOS && sd->bl.m != bl->m ) + continue; + if( (type == BG_AREA || type == BG_AREA_WOS) && (sd->bl.x < x0 || sd->bl.y < y0 || sd->bl.x > x1 || sd->bl.y > y1) ) + continue; WFIFOHEAD(fd,len); memcpy(WFIFOP(fd,0), buf, len); WFIFOSET(fd,len); } } - } - break; + break; - default: - ShowError("clif_send: Unrecognized type %d\n",type); - return -1; + default: + ShowError("clif->send: Unrecognized type %d\n",type); + return -1; } return 0; } - /// Notifies the client, that it's connection attempt was accepted. /// 0073 <start time>.L <position>.3B <x size>.B <y size>.B (ZC_ACCEPT_ENTER) /// 02eb <start time>.L <position>.3B <x size>.B <y size>.B <font>.W (ZC_ACCEPT_ENTER2) void clif_authok(struct map_session_data *sd) { -#if PACKETVER < 20080102 - const int cmd = 0x73; -#else - const int cmd = 0x2eb; -#endif - int fd = sd->fd; - - WFIFOHEAD(fd,packet_len(cmd)); - WFIFOW(fd, 0) = cmd; - WFIFOL(fd, 2) = gettick(); - WFIFOPOS(fd, 6, sd->bl.x, sd->bl.y, sd->ud.dir); - WFIFOB(fd, 9) = 5; // ignored - WFIFOB(fd,10) = 5; // ignored + struct packet_authok p; + + p.PacketType = authokType; + p.startTime = gettick(); + WBUFPOS(&p.PosDir[0],0,sd->bl.x,sd->bl.y,sd->ud.dir); /* do the stupid client math */ + p.xSize = p.ySize = 5; /* not-used */ + #if PACKETVER >= 20080102 - WFIFOW(fd,11) = sd->user_font; // FIXME: Font is currently not saved. + p.font = sd->user_font; // FIXME: Font is currently not saved. #endif - WFIFOSET(fd,packet_len(cmd)); + + clif->send(&p,sizeof(p),&sd->bl,SELF); } @@ -712,7 +625,7 @@ void clif_authrefuse(int fd, uint8 error_code) /// ? = disconnected -> MsgStringTable[3] void clif_authfail_fd(int fd, int type) { - if (!fd || !session[fd] || session[fd]->func_parse != clif_parse) //clif_authfail should only be invoked on players! + if (!fd || !session[fd] || session[fd]->func_parse != clif->parse) //clif_authfail should only be invoked on players! return; WFIFOHEAD(fd, packet_len(0x81)); @@ -746,27 +659,29 @@ void clif_charselectok(int id, uint8 ok) /// Makes an item appear on the ground. /// 009e <id>.L <name id>.W <identified>.B <x>.W <y>.W <subX>.B <subY>.B <amount>.W (ZC_ITEM_FALL_ENTRY) /// 084b (ZC_ITEM_FALL_ENTRY4) -void clif_dropflooritem(struct flooritem_data* fitem) -{ - uint8 buf[17]; +void clif_dropflooritem(struct flooritem_data* fitem) { + struct packet_dropflooritem p; int view; nullpo_retv(fitem); if (fitem->item_data.nameid <= 0) return; - - WBUFW(buf, 0) = 0x9e; - WBUFL(buf, 2) = fitem->bl.id; - WBUFW(buf, 6) = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid; - WBUFB(buf, 8) = fitem->item_data.identify; - WBUFW(buf, 9) = fitem->bl.x; - WBUFW(buf,11) = fitem->bl.y; - WBUFB(buf,13) = fitem->subx; - WBUFB(buf,14) = fitem->suby; - WBUFW(buf,15) = fitem->item_data.amount; - - clif_send(buf, packet_len(0x9e), &fitem->bl, AREA); + + p.PacketType = dropflooritemType; + p.ITAID = fitem->bl.id; + p.ITID = ((view = itemdb_viewid(fitem->item_data.nameid)) > 0) ? view : fitem->item_data.nameid; +#if PACKETVER >= 20130000 /* not sure date */ + p.type = itemtype(itemdb_type(fitem->item_data.nameid)); +#endif + p.IsIdentified = fitem->item_data.identify; + p.xPos = fitem->bl.x; + p.yPos = fitem->bl.y; + p.subX = fitem->subx; + p.subY = fitem->suby; + p.count = fitem->item_data.amount; + + clif->send(&p, sizeof(p), &fitem->bl, AREA); } @@ -783,7 +698,7 @@ void clif_clearflooritem(struct flooritem_data *fitem, int fd) WBUFL(buf,2) = fitem->bl.id; if (fd == 0) { - clif_send(buf, packet_len(0xa1), &fitem->bl, AREA); + clif->send(buf, packet_len(0xa1), &fitem->bl, AREA); } else { WFIFOHEAD(fd,packet_len(0xa1)); memcpy(WFIFOP(fd,0), buf, packet_len(0xa1)); @@ -827,11 +742,11 @@ void clif_clearunit_area(struct block_list* bl, clr_type type) WBUFL(buf,2) = bl->id; WBUFB(buf,6) = type; - clif_send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA : AREA_WOS); + clif->send(buf, packet_len(0x80), bl, type == CLR_DEAD ? AREA : AREA_WOS); if(disguised(bl)) { WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x80), bl, SELF); + clif->send(buf, packet_len(0x80), bl, SELF); } } @@ -839,24 +754,22 @@ void clif_clearunit_area(struct block_list* bl, clr_type type) /// Used to make monsters with player-sprites disappear after dying /// like normal monsters, because the client does not remove those /// automatically. -static int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data) -{ +int clif_clearunit_delayed_sub(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *bl = (struct block_list *)data; - clif_clearunit_area(bl, (clr_type) id); - ers_free(delay_clearunit_ers,bl); + clif->clearunit_area(bl, (clr_type) id); + ers_free(clif->delay_clearunit_ers,bl); return 0; } void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick) { - struct block_list *tbl = ers_alloc(delay_clearunit_ers, struct block_list); + struct block_list *tbl = ers_alloc(clif->delay_clearunit_ers, struct block_list); memcpy (tbl, bl, sizeof (struct block_list)); - add_timer(tick, clif_clearunit_delayed_sub, (int)type, (intptr_t)tbl); + add_timer(tick, clif->clearunit_delayed_sub, (int)type, (intptr_t)tbl); } void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand) { - if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER)) - { + if(sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK)) { *rhand = *lhand = 0; return; } @@ -891,31 +804,23 @@ void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, un } //To make the assignation of the level based on limits clearer/easier. [Skotlex] -static int clif_setlevel_sub(int lv) -{ - if( lv < battle_config.max_lv ) - { +static int clif_setlevel_sub(int lv) { + if( lv < battle_config.max_lv ) { ; - } - else if( lv < battle_config.aura_lv ) - { + } else if( lv < battle_config.aura_lv ) { lv = battle_config.max_lv - 1; - } - else - { + } else { lv = battle_config.max_lv; } return lv; } -static int clif_setlevel(struct block_list* bl) -{ +static int clif_setlevel(struct block_list* bl) { int lv = status_get_lv(bl); if( battle_config.client_limit_unit_lv&bl->type ) return clif_setlevel_sub(lv); - switch( bl->type ) - { + switch( bl->type ) { case BL_NPC: case BL_PET: // npcs and pets do not have level @@ -925,13 +830,91 @@ static int clif_setlevel(struct block_list* bl) } /*========================================== - * Prepares 'unit standing/spawning' packet + * Prepares 'unit standing' packet *------------------------------------------*/ -static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool spawn) -{ +void clif_set_unit_idle(struct block_list* bl, struct map_session_data *tsd, enum send_target target) { struct map_session_data* sd; struct status_change* sc = status_get_sc(bl); struct view_data* vd = status_get_viewdata(bl); + struct packet_idle_unit p; + int g_id = status_get_guild_id(bl); + + sd = BL_CAST(BL_PC, bl); + + p.PacketType = idle_unitType; +#if PACKETVER >= 20091103 + p.PacketLength = sizeof(p); + p.objecttype = clif_bl_type(bl); +#endif + p.GID = bl->id; + p.speed = status_get_speed(bl); + p.bodyState = (sc) ? sc->opt1 : 0; + p.healthState = (sc) ? sc->opt2 : 0; + p.effectState = (sc) ? sc->option : 0; + p.job = vd->class_; + p.head = vd->hair_style; + p.weapon = vd->weapon; + p.accessory = vd->head_bottom; +#if PACKETVER < 7 + p.shield = vd->shield; +#endif + p.accessory2 = vd->head_top; + p.accessory3 = vd->head_mid; + if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? + p.accessory = g_id; + p.accessory2 = GetWord(g_id, 1); + p.accessory3 = GetWord(g_id, 0); + } + p.headpalette = vd->hair_color; + p.bodypalette = vd->cloth_color; + p.headDir = (sd)? sd->head_dir : 0; +#if PACKETVER >= 20101124 + p.robe = vd->robe; +#endif + p.GUID = g_id; + p.GEmblemVer = status_get_emblem_id(bl); + p.honor = (sd) ? sd->status.manner : 0; + p.virtue = (sc) ? sc->opt3 : 0; + p.isPKModeON = (sd) ? sd->status.karma : 0; + p.sex = vd->sex; + WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit_getdir(bl)); + p.xSize = p.ySize = (sd) ? 5 : 0; + p.state = vd->dead_sit; + p.clevel = clif_setlevel(bl); +#if PACKETVER >= 20080102 + p.font = (sd) ? sd->user_font : 0; +#endif +#if PACKETVER >= 20140000 //actual 20120221 + if( bl->type == BL_MOB ) { + p.maxHP = status_get_max_hp(bl); + p.HP = status_get_hp(bl); + p.isBoss = ( ((TBL_MOB*)bl)->spawn && ((TBL_MOB*)bl)->spawn->state.boss ) ? 1 : 0; + } else { + p.maxHP = -1; + p.HP = -1; + p.isBoss = 0; + } +#endif + + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); + + if( disguised(bl) ) { +#if PACKETVER >= 20071106 + p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.GID = -bl->id; +#else + p.GID = -bl->id; +#endif + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,SELF); + } + +} +/* todo for packetver 20091103 0x7c non-pc-looking unit handling */ +int clif_spawn_unit2(struct block_list* bl, enum send_target target) { + return 0; + /*struct map_session_data* sd; + struct status_change* sc = status_get_sc(bl); + struct view_data* vd = status_get_viewdata(bl); unsigned char *buf = WBUFP(buffer,0); #if PACKETVER < 20091103 bool type = !pcdb_checkid(vd->class_); @@ -941,26 +924,26 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool const char *name; #endif sd = BL_CAST(BL_PC, bl); - + #if PACKETVER < 20091103 if(type) - WBUFW(buf,0) = spawn?0x7c:0x78; + WBUFW(buf,0) = 0x7c; else #endif #if PACKETVER < 4 - WBUFW(buf,0) = spawn?0x79:0x78; + WBUFW(buf,0) = 0x79; #elif PACKETVER < 7 - WBUFW(buf,0) = spawn?0x1d9:0x1d8; + WBUFW(buf,0) = 0x1d9; #elif PACKETVER < 20080102 - WBUFW(buf,0) = spawn?0x22b:0x22a; + WBUFW(buf,0) = 0x22b; #elif PACKETVER < 20091103 - WBUFW(buf,0) = spawn?0x2ed:0x2ee; + WBUFW(buf,0) = 0x2ed; #elif PACKETVER < 20101124 - WBUFW(buf,0) = spawn?0x7f8:0x7f9; + WBUFW(buf,0) = 0x7f8; #else - WBUFW(buf,0) = spawn?0x858:0x857; + WBUFW(buf,0) = 0x858; #endif - + #if PACKETVER >= 20091103 name = status_get_name(bl); #if PACKETVER < 20110111 @@ -1021,14 +1004,14 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool #endif WBUFW(buf,24) = vd->head_top; WBUFW(buf,26) = vd->head_mid; - + if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? WBUFW(buf,22) = status_get_emblem_id(bl); WBUFW(buf,24) = GetWord(status_get_guild_id(bl), 1); WBUFW(buf,26) = GetWord(status_get_guild_id(bl), 0); } - + WBUFW(buf,28) = vd->hair_color; WBUFW(buf,30) = vd->cloth_color; WBUFW(buf,32) = (sd)? sd->head_dir : 0; @@ -1088,149 +1071,176 @@ static int clif_set_unit_idle(struct block_list* bl, unsigned char* buffer, bool #else return packet_len(WBUFW(buffer,0)); #endif + */ } -/*========================================== - * Prepares 'unit walking' packet - *------------------------------------------*/ -static int clif_set_unit_walking(struct block_list* bl, struct unit_data* ud, unsigned char* buffer) -{ +void clif_spawn_unit(struct block_list* bl, enum send_target target) { struct map_session_data* sd; struct status_change* sc = status_get_sc(bl); struct view_data* vd = status_get_viewdata(bl); - unsigned char* buf = WBUFP(buffer,0); -#if PACKETVER >= 7 - unsigned short offset = 0; -#endif -#if PACKETVER >= 20091103 - const char *name; -#endif + struct packet_spawn_unit p; + int g_id = status_get_guild_id(bl); sd = BL_CAST(BL_PC, bl); - -#if PACKETVER < 4 - WBUFW(buf, 0) = 0x7b; -#elif PACKETVER < 7 - WBUFW(buf, 0) = 0x1da; -#elif PACKETVER < 20080102 - WBUFW(buf, 0) = 0x22c; -#elif PACKETVER < 20091103 - WBUFW(buf, 0) = 0x2ec; -#elif PACKETVER < 20101124 - WBUFW(buf, 0) = 0x7f7; -#else - WBUFW(buf, 0) = 0x856; -#endif - + + p.PacketType = spawn_unitType; #if PACKETVER >= 20091103 - name = status_get_name(bl); -#if PACKETVER < 20110111 - WBUFW(buf, 2) = 69+strlen(name); -#else - WBUFW(buf, 2) = 71+strlen(name); + p.PacketLength = sizeof(p); + p.objecttype = clif_bl_type(bl); #endif - offset+=2; - buf = WBUFP(buffer,offset); + p.GID = bl->id; + p.speed = status_get_speed(bl); + p.bodyState = (sc) ? sc->opt1 : 0; + p.healthState = (sc) ? sc->opt2 : 0; + p.effectState = (sc) ? sc->option : 0; + p.job = vd->class_; + p.head = vd->hair_style; + p.weapon = vd->weapon; + p.accessory = vd->head_bottom; +#if PACKETVER < 7 + p.shield = vd->shield; #endif -#if PACKETVER >= 20071106 - WBUFB(buf, 2) = clif_bl_type(bl); - offset++; - buf = WBUFP(buffer,offset); + p.accessory2 = vd->head_top; + p.accessory3 = vd->head_mid; + if( bl->type == BL_NPC && vd->class_ == FLAG_CLASS ) { //The hell, why flags work like this? + p.accessory = g_id; + p.accessory2 = GetWord(g_id, 1); + p.accessory3 = GetWord(g_id, 0); + } + p.headpalette = vd->hair_color; + p.bodypalette = vd->cloth_color; + p.headDir = (sd)? sd->head_dir : 0; +#if PACKETVER >= 20101124 + p.robe = vd->robe; #endif - WBUFL(buf, 2) = bl->id; - WBUFW(buf, 6) = status_get_speed(bl); - WBUFW(buf, 8) = (sc)? sc->opt1 : 0; - WBUFW(buf,10) = (sc)? sc->opt2 : 0; -#if PACKETVER < 7 - WBUFW(buf,12) = (sc)? sc->option : 0; -#else - WBUFL(buf,12) = (sc)? sc->option : 0; - offset+=2; //Shift the rest of elements by 2 bytes. - buf = WBUFP(buffer,offset); + p.GUID = g_id; + p.GEmblemVer = status_get_emblem_id(bl); + p.honor = (sd) ? sd->status.manner : 0; + p.virtue = (sc) ? sc->opt3 : 0; + p.isPKModeON = (sd) ? sd->status.karma : 0; + p.sex = vd->sex; + WBUFPOS(&p.PosDir[0],0,bl->x,bl->y,unit_getdir(bl)); + p.xSize = p.ySize = (sd) ? 5 : 0; + p.clevel = clif_setlevel(bl); +#if PACKETVER >= 20080102 + p.font = (sd) ? sd->user_font : 0; #endif - WBUFW(buf,14) = vd->class_; - WBUFW(buf,16) = vd->hair_style; - WBUFW(buf,18) = vd->weapon; -#if PACKETVER < 4 - WBUFW(buf,20) = vd->head_bottom; - WBUFL(buf,22) = gettick(); - WBUFW(buf,26) = vd->shield; +#if PACKETVER >= 20140000 //actual 20120221 + if( bl->type == BL_MOB ) { + p.maxHP = status_get_max_hp(bl); + p.HP = status_get_hp(bl); + p.isBoss = ( ((TBL_MOB*)bl)->spawn && ((TBL_MOB*)bl)->spawn->state.boss ) ? 1 : 0; + } else { + p.maxHP = -1; + p.HP = -1; + p.isBoss = 0; + } +#endif + clif->send(&p,sizeof(p),bl,target); + + if( disguised(bl) ) { +#if PACKETVER >= 20071106 + p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.GID = -bl->id; #else - WBUFW(buf,20) = vd->shield; - WBUFW(buf,22) = vd->head_bottom; - WBUFL(buf,24) = gettick(); + p.GID = -bl->id; #endif - WBUFW(buf,28) = vd->head_top; - WBUFW(buf,30) = vd->head_mid; - WBUFW(buf,32) = vd->hair_color; - WBUFW(buf,34) = vd->cloth_color; - WBUFW(buf,36) = (sd)? sd->head_dir : 0; -#if PACKETVER >= 20110111 - WBUFW(buf,38) = vd->robe; - offset+= 2; - buf = WBUFP(buffer,offset); + clif->send(&p,sizeof(p),bl,SELF); + } + +} + +/*========================================== + * Prepares 'unit walking' packet + *------------------------------------------*/ +void clif_set_unit_walking(struct block_list* bl, struct map_session_data *tsd, struct unit_data* ud, enum send_target target) { + struct map_session_data* sd; + struct status_change* sc = status_get_sc(bl); + struct view_data* vd = status_get_viewdata(bl); + struct packet_unit_walking p; + int g_id = status_get_guild_id(bl); + + sd = BL_CAST(BL_PC, bl); + + p.PacketType = unit_walkingType; +#if PACKETVER >= 20091103 + p.PacketLength = sizeof(p); + p.objecttype = clif_bl_type(bl); #endif - WBUFL(buf,38) = status_get_guild_id(bl); - WBUFW(buf,42) = status_get_emblem_id(bl); - WBUFW(buf,44) = (sd)? sd->status.manner : 0; + p.GID = bl->id; + p.speed = status_get_speed(bl); + p.bodyState = (sc) ? sc->opt1 : 0; + p.healthState = (sc) ? sc->opt2 : 0; + p.effectState = (sc) ? sc->option : 0; + p.job = vd->class_; + p.head = vd->hair_style; + p.weapon = vd->weapon; + p.accessory = vd->head_bottom; + p.moveStartTime = gettick(); #if PACKETVER < 7 - WBUFW(buf,46) = (sc)? sc->opt3 : 0; -#else - WBUFL(buf,46) = (sc)? sc->opt3 : 0; - offset+=2; //Shift the rest of elements by 2 bytes. - buf = WBUFP(buffer,offset); + p.shield = vd->shield; +#endif + p.accessory2 = vd->head_top; + p.accessory3 = vd->head_mid; + p.headpalette = vd->hair_color; + p.bodypalette = vd->cloth_color; + p.headDir = (sd)? sd->head_dir : 0; +#if PACKETVER >= 20101124 + p.robe = vd->robe; #endif - WBUFB(buf,48) = (sd)? sd->status.karma : 0; - WBUFB(buf,49) = vd->sex; - WBUFPOS2(buf,50,bl->x,bl->y,ud->to_x,ud->to_y,8,8); - WBUFB(buf,56) = (sd)? 5 : 0; - WBUFB(buf,57) = (sd)? 5 : 0; - WBUFW(buf,58) = clif_setlevel(bl); + p.GUID = g_id; + p.GEmblemVer = status_get_emblem_id(bl); + p.honor = (sd) ? sd->status.manner : 0; + p.virtue = (sc) ? sc->opt3 : 0; + p.isPKModeON = (sd) ? sd->status.karma : 0; + p.sex = vd->sex; + WBUFPOS2(&p.MoveData[0],0,bl->x,bl->y,ud->to_x,ud->to_y,8,8); + p.xSize = p.ySize = (sd) ? 5 : 0; + p.clevel = clif_setlevel(bl); #if PACKETVER >= 20080102 - WBUFW(buf,60) = sd?sd->user_font:0; + p.font = (sd) ? sd->user_font : 0; #endif -#if PACKETVER >= 20091103 - memcpy((char*)WBUFP(buf,62), name, NAME_LENGTH); - return WBUFW(buffer,2); -#else - return packet_len(WBUFW(buffer,0)); +#if PACKETVER >= 20140000 //actual 20120221 + if( bl->type == BL_MOB ) { + p.maxHP = status_get_max_hp(bl); + p.HP = status_get_hp(bl); + p.isBoss = ( ((TBL_MOB*)bl)->spawn && ((TBL_MOB*)bl)->spawn->state.boss ) ? 1 : 0; + } else { + p.maxHP = -1; + p.HP = -1; + p.isBoss = 0; + } #endif -} + + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,target); -//Modifies the buffer for disguise characters and sends it to self. -//Used for spawn/walk packets, where the ID offset changes for packetver >=9 -static void clif_setdisguise(struct block_list *bl, unsigned char *buf,int len) -{ -#if PACKETVER >= 20091103 - WBUFB(buf,4)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE - WBUFL(buf,5)=-bl->id; -#elif PACKETVER >= 20071106 - WBUFB(buf,2)= pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE - WBUFL(buf,3)=-bl->id; + if( disguised(bl) ) { +#if PACKETVER >= 20071106 + p.objecttype = pcdb_checkid(status_get_viewdata(bl)->class_) ? 0x0 : 0x5; //PC_TYPE : NPC_MOB_TYPE + p.GID = -bl->id; #else - WBUFL(buf,2)=-bl->id; -#endif - clif_send(buf, len, bl, SELF); + p.GID = -bl->id; +#endif + clif->send(&p,sizeof(p),tsd?&tsd->bl:bl,SELF); + } } - /// Changes sprite of an NPC object (ZC_NPCSPRITE_CHANGE). /// 01b0 <id>.L <type>.B <value>.L /// type: /// unused void clif_class_change(struct block_list *bl,int class_,int type) { - unsigned char buf[16]; - nullpo_retv(bl); if(!pcdb_checkid(class_)) {// player classes yield missing sprites + unsigned char buf[16]; WBUFW(buf,0)=0x1b0; WBUFL(buf,2)=bl->id; WBUFB(buf,6)=type; WBUFL(buf,7)=class_; - clif_send(buf,packet_len(0x1b0),bl,AREA); + clif->send(buf,packet_len(0x1b0),bl,AREA); } } @@ -1238,8 +1248,7 @@ void clif_class_change(struct block_list *bl,int class_,int type) /// Notifies the client of an object's spirits. /// 01d0 <id>.L <amount>.W (ZC_SPIRITS) /// 01e1 <id>.L <amount>.W (ZC_SPIRITS2) -static void clif_spiritball_single(int fd, struct map_session_data *sd) -{ +void clif_spiritball_single(int fd, struct map_session_data *sd) { WFIFOHEAD(fd, packet_len(0x1e1)); WFIFOW(fd,0)=0x1e1; WFIFOL(fd,2)=sd->bl.id; @@ -1250,8 +1259,7 @@ static void clif_spiritball_single(int fd, struct map_session_data *sd) /*========================================== * Kagerou/Oboro amulet spirit *------------------------------------------*/ -static void clif_talisman_single(int fd, struct map_session_data *sd, short type) -{ +void clif_talisman_single(int fd, struct map_session_data *sd, short type) { WFIFOHEAD(fd, packet_len(0x08cf)); WFIFOW(fd,0)=0x08cf; WFIFOL(fd,2)=sd->bl.id; @@ -1264,8 +1272,7 @@ static void clif_talisman_single(int fd, struct map_session_data *sd, short type * Run when player changes map / refreshes * Tells its client to display all weather settings being used by this map *------------------------------------------*/ -static void clif_weather_check(struct map_session_data *sd) -{ +void clif_weather_check(struct map_session_data *sd) { int16 m = sd->bl.m; int fd = sd->fd; @@ -1275,34 +1282,24 @@ static void clif_weather_check(struct map_session_data *sd) || map[m].flag.fireworks || map[m].flag.sakura || map[m].flag.leaves - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //|| map[m].flag.rain - || map[m].flag.clouds2) - { + || map[m].flag.clouds2) { if (map[m].flag.snow) - clif_specialeffect_single(&sd->bl, 162, fd); + clif->specialeffect_single(&sd->bl, 162, fd); if (map[m].flag.clouds) - clif_specialeffect_single(&sd->bl, 233, fd); + clif->specialeffect_single(&sd->bl, 233, fd); if (map[m].flag.clouds2) - clif_specialeffect_single(&sd->bl, 516, fd); + clif->specialeffect_single(&sd->bl, 516, fd); if (map[m].flag.fog) - clif_specialeffect_single(&sd->bl, 515, fd); + clif->specialeffect_single(&sd->bl, 515, fd); if (map[m].flag.fireworks) { - clif_specialeffect_single(&sd->bl, 297, fd); - clif_specialeffect_single(&sd->bl, 299, fd); - clif_specialeffect_single(&sd->bl, 301, fd); + clif->specialeffect_single(&sd->bl, 297, fd); + clif->specialeffect_single(&sd->bl, 299, fd); + clif->specialeffect_single(&sd->bl, 301, fd); } if (map[m].flag.sakura) - clif_specialeffect_single(&sd->bl, 163, fd); + clif->specialeffect_single(&sd->bl, 163, fd); if (map[m].flag.leaves) - clif_specialeffect_single(&sd->bl, 333, fd); - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //if (map[m].flag.rain) - // clif_specialeffect_single(&sd->bl, 161, fd); + clif->specialeffect_single(&sd->bl, 333, fd); } } /** @@ -1314,21 +1311,19 @@ void clif_weather(int16 m) struct map_session_data *sd=NULL; iter = mapit_getallusers(); - for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) + for( sd = (struct map_session_data*)mapit->first(iter); mapit->exists(iter); sd = (struct map_session_data*)mapit->next(iter) ) { if( sd->bl.m == m ) clif_weather_check(sd); } - mapit_free(iter); + mapit->free(iter); } /** * Main function to spawn a unit on the client (player/mob/pet/etc) **/ int clif_spawn(struct block_list *bl) { - unsigned char buf[128]; struct view_data *vd; - int len; vd = status_get_viewdata(bl); if( !vd || vd->class_ == INVISIBLE_CLASS ) @@ -1340,84 +1335,73 @@ int clif_spawn(struct block_list *bl) if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE)) return 0; - len = clif_set_unit_idle(bl, buf,true); - clif_send(buf, len, bl, AREA_WOS); - if (disguised(bl)) - clif_setdisguise(bl, buf, len); + clif->spawn_unit(bl,AREA_WOS); if (vd->cloth_color) - clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); + clif->refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); - switch (bl->type) - { - case BL_PC: - { - TBL_PC *sd = ((TBL_PC*)bl); - int i; - if (sd->spiritball > 0) - clif_spiritball(&sd->bl); - if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif_specialeffect(bl,423,AREA); - else if(sd->state.size==SZ_MEDIUM) - clif_specialeffect(bl,421,AREA); - if( sd->bg_id && map[sd->bl.m].flag.battleground ) - clif_sendbgemblem_area(sd); - if( sd->sc.option&OPTION_MOUNTING ) { - //New Mounts are not complaint to the original method, so we gotta tell this guy that he is mounting. - clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); + + switch (bl->type) { + case BL_PC: + { + TBL_PC *sd = ((TBL_PC*)bl); + int i; + if (sd->spiritball > 0) + clif->spiritball(&sd->bl); + if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif->specialeffect(bl,423,AREA); + else if(sd->state.size==SZ_MEDIUM) + clif->specialeffect(bl,421,AREA); + if( sd->bg_id && map[sd->bl.m].flag.battleground ) + clif->sendbgemblem_area(sd); + for( i = 0; i < sd->sc_display_count; i++ ) { + clif->sc_load(&sd->bl, sd->bl.id,AREA,StatusIconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3); + } + for(i = 1; i < 5; i++){ + if( sd->talisman[i] > 0 ) + clif->talisman(sd, i); + } + if (sd->status.robe) + clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); } - for(i = 1; i < 5; i++){ - if( sd->talisman[i] > 0 ) - clif_talisman(sd, i); + break; + case BL_MOB: + { + TBL_MOB *md = ((TBL_MOB*)bl); + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif->specialeffect(&md->bl,423,AREA); + else if(md->special_state.size==SZ_MEDIUM) + clif->specialeffect(&md->bl,421,AREA); } - #ifdef NEW_CARTS - if( sd->sc.data[SC_PUSH_CART] ) - clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2, sd->sc.data[SC_PUSH_CART]->val1, 0, 0); - #endif - #if PACKETVER <= 20120207 - if (sd->status.robe) - clif_refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA); - #endif - } - break; - case BL_MOB: - { - TBL_MOB *md = ((TBL_MOB*)bl); - if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif_specialeffect(&md->bl,423,AREA); - else if(md->special_state.size==SZ_MEDIUM) - clif_specialeffect(&md->bl,421,AREA); - } - break; - case BL_NPC: - { - TBL_NPC *nd = ((TBL_NPC*)bl); - if( nd->size == SZ_BIG ) - clif_specialeffect(&nd->bl,423,AREA); - else if( nd->size == SZ_MEDIUM ) - clif_specialeffect(&nd->bl,421,AREA); - } - break; - case BL_PET: - if (vd->head_bottom) - clif_pet_equip_area((TBL_PET*)bl); // needed to display pet equip properly - break; + break; + case BL_NPC: + { + TBL_NPC *nd = ((TBL_NPC*)bl); + if( nd->size == SZ_BIG ) + clif->specialeffect(&nd->bl,423,AREA); + else if( nd->size == SZ_MEDIUM ) + clif->specialeffect(&nd->bl,421,AREA); + } + break; + case BL_PET: + if (vd->head_bottom) + clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); // needed to display pet equip properly + break; } return 0; } /// Sends information about owned homunculus to the client (ZC_PROPERTY_HOMUN). [orn] /// 022e <name>.24B <modified>.B <level>.W <hunger>.W <intimacy>.W <equip id>.W <atk>.W <matk>.W <hit>.W <crit>.W <def>.W <mdef>.W <flee>.W <aspd>.W <hp>.W <max hp>.W <sp>.W <max sp>.W <exp>.L <max exp>.L <skill points>.W <atk range>.W -void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) -{ +void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) { struct status_data *status; unsigned char buf[128]; - int m_class; + enum homun_type htype; nullpo_retv(hd); status = &hd->battle_status; - m_class = hom_class2mapid(hd->homunculus.class_); + htype = homun->class2type(hd->homunculus.class_); memset(buf,0,packet_len(0x22e)); WBUFW(buf,0)=0x22e; @@ -1454,13 +1438,21 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) WBUFW(buf,57)=status->max_sp; } WBUFL(buf,59)=hd->homunculus.exp; - if( ((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) || ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) ) - WBUFL(buf,63)=0; - else - WBUFL(buf,63)=hd->exp_next; + WBUFL(buf,63)=hd->exp_next; + switch( htype ) { + case HT_REG: + case HT_EVO: + if( hd->homunculus.level >= battle_config.hom_max_level ) + WBUFL(buf,63)=0; + break; + case HT_S: + if( hd->homunculus.level >= battle_config.hom_S_max_level ) + WBUFL(buf,63)=0; + break; + } WBUFW(buf,67)=hd->homunculus.skillpts; WBUFW(buf,69)=status_get_range(&hd->bl); - clif_send(buf,packet_len(0x22e),&sd->bl,SELF); + clif->send(buf,packet_len(0x22e),&sd->bl,SELF); } @@ -1479,7 +1471,7 @@ void clif_send_homdata(struct map_session_data *sd, int state, int param) int fd = sd->fd; if ( (state == SP_INTIMATE) && (param >= 910) && (sd->hd->homunculus.class_ == sd->hd->homunculusDB->evo_class) ) - merc_hom_calc_skilltree(sd->hd, 0); + homun->calc_skilltree(sd->hd, 0); WFIFOHEAD(fd, packet_len(0x230)); WFIFOW(fd,0)=0x230; @@ -1491,8 +1483,7 @@ void clif_send_homdata(struct map_session_data *sd, int state, int param) } -int clif_homskillinfoblock(struct map_session_data *sd) -{ //[orn] +int clif_homskillinfoblock(struct map_session_data *sd) { //[orn] struct homun_data *hd; int fd = sd->fd; int i,j,len=4,id; @@ -1507,13 +1498,13 @@ int clif_homskillinfoblock(struct map_session_data *sd) if( (id = hd->homunculus.hskill[i].id) != 0 ){ j = id - HM_SKILLBASE; WFIFOW(fd,len ) = id; - WFIFOW(fd,len+2) = skill_get_inf(id); + WFIFOW(fd,len+2) = skill->get_inf(id); WFIFOW(fd,len+4) = 0; WFIFOW(fd,len+6) = hd->homunculus.hskill[j].lv; - WFIFOW(fd,len+8) = skill_get_sp(id,hd->homunculus.hskill[j].lv); - WFIFOW(fd,len+10)= skill_get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv); - safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); - WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < merc_skill_tree_get_max(id, hd->homunculus.class_))?1:0; + WFIFOW(fd,len+8) = skill->get_sp(id,hd->homunculus.hskill[j].lv); + WFIFOW(fd,len+10)= skill->get_range2(&sd->hd->bl, id,hd->homunculus.hskill[j].lv); + safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); + WFIFOB(fd,len+36) = (hd->homunculus.hskill[j].lv < homun->skill_tree_get_max(id, hd->homunculus.class_))?1:0; len+=37; } } @@ -1523,8 +1514,7 @@ int clif_homskillinfoblock(struct map_session_data *sd) return 0; } -void clif_homskillup(struct map_session_data *sd, uint16 skill_id) -{ //[orn] +void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn] struct homun_data *hd; int fd, idx; nullpo_retv(sd); @@ -1537,9 +1527,9 @@ void clif_homskillup(struct map_session_data *sd, uint16 skill_id) WFIFOW(fd,0) = 0x239; WFIFOW(fd,2) = skill_id; WFIFOW(fd,4) = hd->homunculus.hskill[idx].lv; - WFIFOW(fd,6) = skill_get_sp(skill_id,hd->homunculus.hskill[idx].lv); - WFIFOW(fd,8) = skill_get_range2(&hd->bl, skill_id,hd->homunculus.hskill[idx].lv); - WFIFOB(fd,10) = (hd->homunculus.hskill[idx].lv < skill_get_max(hd->homunculus.hskill[idx].id)) ? 1 : 0; + WFIFOW(fd,6) = skill->get_sp(skill_id,hd->homunculus.hskill[idx].lv); + WFIFOW(fd,8) = skill->get_range2(&hd->bl, skill_id,hd->homunculus.hskill[idx].lv); + WFIFOB(fd,10) = (hd->homunculus.hskill[idx].lv < skill->get_max(hd->homunculus.hskill[idx].id)) ? 1 : 0; WFIFOSET(fd,packet_len(0x239)); } @@ -1570,46 +1560,37 @@ void clif_walkok(struct map_session_data *sd) } -static void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) -{ - uint8 buf[128]; - int len; +void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *ud) { - len = clif_set_unit_walking(bl,ud,buf); - clif_send(buf,len,bl,AREA_WOS); - if (disguised(bl)) - clif_setdisguise(bl, buf, len); + clif->set_unit_walking(bl,NULL,ud,AREA_WOS); if(vd->cloth_color) - clif_refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); + clif->refreshlook(bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,AREA_WOS); - switch(bl->type) - { - case BL_PC: - { - TBL_PC *sd = ((TBL_PC*)bl); -// clif_movepc(sd); - if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif_specialeffect(&sd->bl,423,AREA); - else if(sd->state.size==SZ_MEDIUM) - clif_specialeffect(&sd->bl,421,AREA); - } - break; - case BL_MOB: - { - TBL_MOB *md = ((TBL_MOB*)bl); - if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif_specialeffect(&md->bl,423,AREA); - else if(md->special_state.size==SZ_MEDIUM) - clif_specialeffect(&md->bl,421,AREA); - } - break; - case BL_PET: - if( vd->head_bottom ) - {// needed to display pet equip properly - clif_pet_equip_area((TBL_PET*)bl); - } - break; + switch(bl->type) { + case BL_PC: + { + TBL_PC *sd = ((TBL_PC*)bl); + // clif_movepc(sd); + if(sd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif->specialeffect(&sd->bl,423,AREA); + else if(sd->state.size==SZ_MEDIUM) + clif->specialeffect(&sd->bl,421,AREA); + } + break; + case BL_MOB: + { + TBL_MOB *md = ((TBL_MOB*)bl); + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif->specialeffect(&md->bl,423,AREA); + else if(md->special_state.size==SZ_MEDIUM) + clif->specialeffect(&md->bl,421,AREA); + } + break; + case BL_PET: + if( vd->head_bottom ) // needed to display pet equip properly + clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); + break; } } @@ -1637,7 +1618,7 @@ void clif_move(struct unit_data *ud) // Since we don't know how to update the speed of other objects, // use the old walk packet to update the data. ud->state.speed_changed = 0; - clif_move2(bl, vd, ud); + clif->move2(bl, vd, ud); return; } @@ -1645,11 +1626,11 @@ void clif_move(struct unit_data *ud) WBUFL(buf,2)=bl->id; WBUFPOS2(buf,6,bl->x,bl->y,ud->to_x,ud->to_y,8,8); WBUFL(buf,12)=gettick(); - clif_send(buf, packet_len(0x86), bl, AREA_WOS); + clif->send(buf, packet_len(0x86), bl, AREA_WOS); if (disguised(bl)) { WBUFL(buf,2)=-bl->id; - clif_send(buf, packet_len(0x86), bl, SELF); + clif->send(buf, packet_len(0x86), bl, SELF); } } @@ -1657,8 +1638,7 @@ void clif_move(struct unit_data *ud) /*========================================== * Delays the map_quit of a player after they are disconnected. [Skotlex] *------------------------------------------*/ -static int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) -{ +int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd = NULL; //Remove player from map server @@ -1670,17 +1650,16 @@ static int clif_delayquit(int tid, unsigned int tick, int id, intptr_t data) /*========================================== * *------------------------------------------*/ -void clif_quitsave(int fd,struct map_session_data *sd) -{ +void clif_quitsave(int fd,struct map_session_data *sd) { if (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) map_quit(sd); - else if (sd->fd) - { //Disassociate session from player (session is deleted after this function was called) + else if (sd->fd) { + //Disassociate session from player (session is deleted after this function was called) //And set a timer to make him quit later. session[sd->fd]->session_data = NULL; sd->fd = 0; - add_timer(gettick() + 10000, clif_delayquit, sd->bl.id, 0); + add_timer(gettick() + 10000, clif->delayquit, sd->bl.id, 0); } } @@ -1724,7 +1703,7 @@ void clif_blown(struct block_list *bl) { //Aegis packets says fixpos, but it's unsure whether slide works better or not. // clif_fixpos(bl); - clif_slide(bl, bl->x, bl->y); + clif->slide(bl, bl->x, bl->y); } @@ -1741,12 +1720,11 @@ void clif_fixpos(struct block_list *bl) WBUFL(buf,2) = bl->id; WBUFW(buf,6) = bl->x; WBUFW(buf,8) = bl->y; - clif_send(buf, packet_len(0x88), bl, AREA); + clif->send(buf, packet_len(0x88), bl, AREA); - if( disguised(bl) ) - { + if( disguised(bl) ) { WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x88), bl, SELF); + clif->send(buf, packet_len(0x88), bl, SELF); } } @@ -1797,7 +1775,24 @@ void clif_buylist(struct map_session_data *sd, struct npc_data *nd) WFIFOW(fd,2) = 4 + c*11; WFIFOSET(fd,WFIFOW(fd,2)); } - +void clif_hercules_chsys_create(struct hChSysCh *channel, char *name, char *pass, unsigned char color) { + channel->users = idb_alloc(DB_OPT_BASE); + if( name ) + safestrncpy(channel->name, name, HCHSYS_NAME_LENGTH); + channel->color = color; + if( !pass ) + channel->pass[0] = '\0'; + else + safestrncpy(channel->pass, pass, HCHSYS_NAME_LENGTH); + + channel->opt = hChSys_OPT_BASE; + channel->banned = NULL; + + channel->msg_delay = 0; + + if( channel->type != hChSys_MAP && channel->type != hChSys_ALLY ) + strdb_put(clif->channel_db, channel->name, channel); +} /// Presents list of items, that can be sold to an NPC shop (ZC_PC_SELL_ITEMLIST). /// 00c7 <packet len>.W { <index>.W <price>.L <overcharge price>.L }* @@ -1911,8 +1906,7 @@ void clif_scriptclose(struct map_session_data *sd, int npcid) /*========================================== * *------------------------------------------*/ -void clif_sendfakenpc(struct map_session_data *sd, int npcid) -{ +void clif_sendfakenpc(struct map_session_data *sd, int npcid) { unsigned char *buf; int fd = sd->fd; sd->state.using_fake_npc = 1; @@ -1963,7 +1957,7 @@ void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes) if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) - clif_sendfakenpc(sd, npcid); + clif->sendfakenpc(sd, npcid); WFIFOHEAD(fd, slen); WFIFOW(fd,0)=0xb7; @@ -1995,7 +1989,7 @@ void clif_scriptinput(struct map_session_data *sd, int npcid) if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) - clif_sendfakenpc(sd, npcid); + clif->sendfakenpc(sd, npcid); fd=sd->fd; WFIFOHEAD(fd, packet_len(0x142)); @@ -2026,7 +2020,7 @@ void clif_scriptinputstr(struct map_session_data *sd, int npcid) if (!sd->state.using_fake_npc && (npcid == fake_nd->bl.id || ((bl = map_id2bl(npcid)) && (bl->m!=sd->bl.m || bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 || bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)))) - clif_sendfakenpc(sd, npcid); + clif->sendfakenpc(sd, npcid); fd=sd->fd; WFIFOHEAD(fd, packet_len(0x1d4)); @@ -2063,8 +2057,27 @@ void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, in WFIFOL(fd,19)=color; WFIFOSET(fd,packet_len(0x144)); } - - +void clif_hercules_chsys_join(struct hChSysCh *channel, struct map_session_data *sd) { + if( idb_put(channel->users, sd->status.char_id, sd) ) + return; + + RECREATE(sd->channels, struct hChSysCh *, ++sd->channel_count); + sd->channels[ sd->channel_count - 1 ] = channel; + + if( sd->stealth ) { + sd->stealth = false; + } else if( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) { + char message[60]; + sprintf(message, "#%s '%s' joined",channel->name,sd->status.name); + clif->chsys_msg(channel,sd,message); + } + + /* someone is cheating, we kindly disconnect the bastard */ + if( sd->channel_count > 200 ) { + set_eof(sd->fd); + } + +} /// Displays an illustration image. /// 0145 <image name>.16B <type>.B (ZC_SHOW_IMAGE) /// 01b3 <image name>.64B <type>.B (ZC_SHOW_IMAGE2) @@ -2092,8 +2105,7 @@ void clif_cutin(struct map_session_data* sd, const char* image, int type) /*========================================== * Fills in card data from the given item and into the buffer. [Skotlex] *------------------------------------------*/ -static void clif_addcards(unsigned char* buf, struct item* item) -{ +void clif_addcards(unsigned char* buf, struct item* item) { int i=0,j; if( item == NULL ) { //Blank data WBUFW(buf,0) = 0; @@ -2142,79 +2154,99 @@ static void clif_addcards(unsigned char* buf, struct item* item) WBUFW(buf,6) = item->card[i]; } +void clif_addcards2(unsigned short *cards, struct item* item) { + int i=0,j; + if( item == NULL ) { //Blank data + cards[0] = 0; + cards[1] = 0; + cards[2] = 0; + cards[3] = 0; + return; + } + if( item->card[0] == CARD0_PET ) { //pet eggs + cards[0] = 0; + cards[1] = 0; + cards[2] = 0; + cards[3] = item->card[3]; //Pet renamed flag. + return; + } + if( item->card[0] == CARD0_FORGE || item->card[0] == CARD0_CREATE ) { //Forged/created items + cards[0] = item->card[0]; + cards[1] = item->card[1]; + cards[2] = item->card[2]; + cards[3] = item->card[3]; + return; + } + //Client only receives four cards.. so randomly send them a set of cards. [Skotlex] + if( MAX_SLOTS > 4 && (j = itemdb_slot(item->nameid)) > 4 ) + i = rnd()%(j-3); //eg: 6 slots, possible i values: 0->3, 1->4, 2->5 => i = rnd()%3; + + //Normal items. + if( item->card[i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[0] = j; + else + cards[0] = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[1] = j; + else + cards[1] = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[2] = j; + else + cards[2] = item->card[i]; + + if( item->card[++i] > 0 && (j=itemdb_viewid(item->card[i])) > 0 ) + cards[3] = j; + else + cards[3] = item->card[i]; +} + /// Notifies the client, about a received inventory item or the result of a pick-up request. /// 00a0 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B (ZC_ITEM_PICKUP_ACK) /// 029a <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B <expire time>.L (ZC_ITEM_PICKUP_ACK2) /// 02d4 <index>.W <amount>.W <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W <equip location>.W <item type>.B <result>.B <expire time>.L <bindOnEquipType>.W (ZC_ITEM_PICKUP_ACK3) -void clif_additem(struct map_session_data *sd, int n, int amount, int fail) -{ - int fd; -#if PACKETVER < 20061218 - const int cmd = 0xa0; -#elif PACKETVER < 20071002 - const int cmd = 0x29a; -#else - const int cmd = 0x2d4; -#endif +void clif_additem(struct map_session_data *sd, int n, int amount, int fail) { + struct packet_additem p; nullpo_retv(sd); - fd = sd->fd; - if( !session_isActive(fd) ) //Sasuke- + if( !session_isActive(sd->fd) ) //Sasuke- return; - WFIFOHEAD(fd,packet_len(cmd)); if( fail ) - { - WFIFOW(fd,0)=cmd; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=amount; - WFIFOW(fd,6)=0; - WFIFOB(fd,8)=0; - WFIFOB(fd,9)=0; - WFIFOB(fd,10)=0; - WFIFOW(fd,11)=0; - WFIFOW(fd,13)=0; - WFIFOW(fd,15)=0; - WFIFOW(fd,17)=0; - WFIFOW(fd,19)=0; - WFIFOB(fd,21)=0; - WFIFOB(fd,22)=fail; -#if PACKETVER >= 20061218 - WFIFOL(fd,23)=0; -#endif -#if PACKETVER >= 20071002 - WFIFOW(fd,27)=0; // unknown -#endif - } - else - { + memset(&p, 0, sizeof(p)); + + p.PacketType = additemType; + p.Index = n+2; + p.count = amount; + + if( !fail ) { if( n < 0 || n >= MAX_INVENTORY || sd->status.inventory[n].nameid <=0 || sd->inventory_data[n] == NULL ) return; - - WFIFOW(fd,0)=cmd; - WFIFOW(fd,2)=n+2; - WFIFOW(fd,4)=amount; + if (sd->inventory_data[n]->view_id > 0) - WFIFOW(fd,6)=sd->inventory_data[n]->view_id; + p.nameid = sd->inventory_data[n]->view_id; else - WFIFOW(fd,6)=sd->status.inventory[n].nameid; - WFIFOB(fd,8)=sd->status.inventory[n].identify; - WFIFOB(fd,9)=sd->status.inventory[n].attribute; - WFIFOB(fd,10)=sd->status.inventory[n].refine; - clif_addcards(WFIFOP(fd,11), &sd->status.inventory[n]); - WFIFOW(fd,19)=pc_equippoint(sd,n); - WFIFOB(fd,21)=itemtype(sd->inventory_data[n]->type); - WFIFOB(fd,22)=fail; + p.nameid = sd->status.inventory[n].nameid; + + p.IsIdentified = sd->status.inventory[n].identify; + p.IsDamaged = sd->status.inventory[n].attribute; + p.refiningLevel =sd->status.inventory[n].refine; + clif->addcards2(&p.slot.card[0], &sd->status.inventory[n]); + p.location = pc_equippoint(sd,n); + p.type = itemtype(sd->inventory_data[n]->type); #if PACKETVER >= 20061218 - WFIFOL(fd,23)=sd->status.inventory[n].expire_time; + p.HireExpireDate = sd->status.inventory[n].expire_time; #endif #if PACKETVER >= 20071002 - WFIFOW(fd,27)=0; // unknown + p.bindOnEquipType = 0; // unused #endif } + p.result = (unsigned char)fail; - WFIFOSET(fd,packet_len(cmd)); + clif->send(&p,sizeof(p),&sd->bl,SELF); } @@ -2249,7 +2281,7 @@ void clif_dropitem(struct map_session_data *sd,int n,int amount) void clif_delitem(struct map_session_data *sd,int n,int amount, short reason) { #if PACKETVER < 20091117 - clif_dropitem(sd,n,amount); + clif->dropitem(sd,n,amount); #else int fd; @@ -2270,8 +2302,7 @@ void clif_delitem(struct map_session_data *sd,int n,int amount, short reason) // Simplifies inventory/cart/storage packets by handling the packet section relevant to items. [Skotlex] // Equip is >= 0 for equippable items (holds the equip-point, is 0 for pet // armor/egg) -1 for stackable items, -2 for stackable items where arrows must send in the equip-point. -void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data *id, int equip) -{ +void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data *id, int equip) { if (id->view_id > 0) WBUFW(buf,n)=id->view_id; else @@ -2292,10 +2323,8 @@ void clif_item_sub(unsigned char *buf, int n, struct item *i, struct item_data * } } -void clif_favorite_item(struct map_session_data* sd, unsigned short index); //Unified inventory function which sends all of the inventory (requires two packets, one for equipable items and one for stackable ones. [Skotlex] -void clif_inventorylist(struct map_session_data *sd) -{ +void clif_inventorylist(struct map_session_data *sd) { int i,n,ne,arrow=-1; unsigned char *buf; unsigned char *bufe; @@ -2326,8 +2355,8 @@ void clif_inventorylist(struct map_session_data *sd) if( !itemdb_isstackable2(sd->inventory_data[i]) ) { //Non-stackable (Equippable) WBUFW(bufe,ne*se+4)=i+2; - clif_item_sub(bufe, ne*se+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); - clif_addcards(WBUFP(bufe, ne*se+16), &sd->status.inventory[i]); + clif->item_sub(bufe, ne*se+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); + clif->addcards(WBUFP(bufe, ne*se+16), &sd->status.inventory[i]); #if PACKETVER >= 20071002 WBUFL(bufe,ne*se+24)=sd->status.inventory[i].expire_time; WBUFW(bufe,ne*se+28)=0; //Unknown @@ -2343,11 +2372,11 @@ void clif_inventorylist(struct map_session_data *sd) else { //Stackable. WBUFW(buf,n*s+4)=i+2; - clif_item_sub(buf, n*s+6, &sd->status.inventory[i], sd->inventory_data[i], -2); + clif->item_sub(buf, n*s+6, &sd->status.inventory[i], sd->inventory_data[i], -2); if( sd->inventory_data[i]->equip == EQP_AMMO && sd->status.inventory[i].equip ) arrow=i; #if PACKETVER >= 5 - clif_addcards(WBUFP(buf, n*s+14), &sd->status.inventory[i]); + clif->addcards(WBUFP(buf, n*s+14), &sd->status.inventory[i]); #endif #if PACKETVER >= 20080102 WBUFL(buf,n*s+22)=sd->status.inventory[i].expire_time; @@ -2355,8 +2384,7 @@ void clif_inventorylist(struct map_session_data *sd) n++; } } - if( n ) - { + if( n ) { #if PACKETVER < 5 WBUFW(buf,0)=0xa3; #elif PACKETVER < 20080102 @@ -2365,20 +2393,19 @@ void clif_inventorylist(struct map_session_data *sd) WBUFW(buf,0)=0x2e8; #endif WBUFW(buf,2)=4+n*s; - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); } if( arrow >= 0 ) - clif_arrowequip(sd,arrow); + clif->arrowequip(sd,arrow); - if( ne ) - { + if( ne ) { #if PACKETVER < 20071002 WBUFW(bufe,0)=0xa4; #else WBUFW(bufe,0)=0x2d0; #endif WBUFW(bufe,2)=4+ne*se; - clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF); } #if PACKETVER >= 20111122 for( i = 0; i < MAX_INVENTORY; i++ ) { @@ -2386,7 +2413,7 @@ void clif_inventorylist(struct map_session_data *sd) continue; if ( sd->status.inventory[i].favorite ) - clif_favorite_item(sd, i); + clif->favorite_item(sd, i); } #endif @@ -2418,8 +2445,8 @@ void clif_equiplist(struct map_session_data *sd) continue; //Equippable WBUFW(buf,n*cmd+4)=i+2; - clif_item_sub(buf, n*cmd+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); - clif_addcards(WBUFP(buf, n*cmd+16), &sd->status.inventory[i]); + clif->item_sub(buf, n*cmd+6, &sd->status.inventory[i], sd->inventory_data[i], pc_equippoint(sd,i)); + clif->addcards(WBUFP(buf, n*cmd+16), &sd->status.inventory[i]); #if PACKETVER >= 20071002 WBUFL(buf,n*cmd+24)=sd->status.inventory[i].expire_time; WBUFW(buf,n*cmd+28)=0; //Unknown @@ -2475,8 +2502,8 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items if( !itemdb_isstackable2(id) ) { //Equippable WBUFW(bufe,ne*cmd+4)=i+1; - clif_item_sub(bufe, ne*cmd+6, &items[i], id, id->equip); - clif_addcards(WBUFP(bufe, ne*cmd+16), &items[i]); + clif->item_sub(bufe, ne*cmd+6, &items[i], id, id->equip); + clif->addcards(WBUFP(bufe, ne*cmd+16), &items[i]); #if PACKETVER >= 20071002 WBUFL(bufe,ne*cmd+24)=items[i].expire_time; WBUFW(bufe,ne*cmd+28)=0; //Unknown @@ -2486,9 +2513,9 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items else { //Stackable WBUFW(buf,n*s+4)=i+1; - clif_item_sub(buf, n*s+6, &items[i], id,-1); + clif->item_sub(buf, n*s+6, &items[i], id,-1); #if PACKETVER >= 5 - clif_addcards(WBUFP(buf,n*s+14), &items[i]); + clif->addcards(WBUFP(buf,n*s+14), &items[i]); #endif #if PACKETVER >= 20080102 WBUFL(buf,n*s+22)=items[i].expire_time; @@ -2506,7 +2533,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items WBUFW(buf,0)=0x2ea; #endif WBUFW(buf,2)=4+n*s; - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); } if( ne ) { @@ -2516,7 +2543,7 @@ void clif_storagelist(struct map_session_data* sd, struct item* items, int items WBUFW(bufe,0)=0x2d1; #endif WBUFW(bufe,2)=4+ne*cmd; - clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF); } if( buf ) aFree(buf); @@ -2555,8 +2582,8 @@ void clif_cartlist(struct map_session_data *sd) if( !itemdb_isstackable2(id) ) { //Equippable WBUFW(bufe,ne*cmd+4)=i+2; - clif_item_sub(bufe, ne*cmd+6, &sd->status.cart[i], id, id->equip); - clif_addcards(WBUFP(bufe, ne*cmd+16), &sd->status.cart[i]); + clif->item_sub(bufe, ne*cmd+6, &sd->status.cart[i], id, id->equip); + clif->addcards(WBUFP(bufe, ne*cmd+16), &sd->status.cart[i]); #if PACKETVER >= 20071002 WBUFL(bufe,ne*cmd+24)=sd->status.cart[i].expire_time; WBUFW(bufe,ne*cmd+28)=0; //Unknown @@ -2566,9 +2593,9 @@ void clif_cartlist(struct map_session_data *sd) else { //Stackable WBUFW(buf,n*s+4)=i+2; - clif_item_sub(buf, n*s+6, &sd->status.cart[i], id,-1); + clif->item_sub(buf, n*s+6, &sd->status.cart[i], id,-1); #if PACKETVER >= 5 - clif_addcards(WBUFP(buf,n*s+14), &sd->status.cart[i]); + clif->addcards(WBUFP(buf,n*s+14), &sd->status.cart[i]); #endif #if PACKETVER >= 20080102 WBUFL(buf,n*s+22)=sd->status.cart[i].expire_time; @@ -2586,7 +2613,7 @@ void clif_cartlist(struct map_session_data *sd) WBUFW(buf,0)=0x2e9; #endif WBUFW(buf,2)=4+n*s; - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); } if( ne ) { @@ -2596,7 +2623,7 @@ void clif_cartlist(struct map_session_data *sd) WBUFW(bufe,0)=0x2d2; #endif WBUFW(bufe,2)=4+ne*cmd; - clif_send(bufe, WBUFW(bufe,2), &sd->bl, SELF); + clif->send(bufe, WBUFW(bufe,2), &sd->bl, SELF); } if( buf ) aFree(buf); @@ -2630,7 +2657,7 @@ void clif_guild_xy(struct map_session_data *sd) WBUFL(buf,2)=sd->status.account_id; WBUFW(buf,6)=sd->bl.x; WBUFW(buf,8)=sd->bl.y; - clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); + clif->send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); } /*========================================== @@ -2660,14 +2687,224 @@ void clif_guild_xy_remove(struct map_session_data *sd) WBUFL(buf,2)=sd->status.account_id; WBUFW(buf,6)=-1; WBUFW(buf,8)=-1; - clif_send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); + clif->send(buf,packet_len(0x1eb),&sd->bl,GUILD_SAMEMAP_WOS); +} +void read_channels_config(void) { + config_t channels_conf; + config_setting_t *chsys = NULL; + const char *config_filename = "conf/channels.conf"; // FIXME hardcoded name + + if (conf_read_file(&channels_conf, config_filename)) + return; + + chsys = config_lookup(&channels_conf, "chsys"); + + if (chsys != NULL) { + config_setting_t *settings = config_setting_get_elem(chsys, 0); + config_setting_t *channels; + config_setting_t *colors; + int i,k; + const char *local_name, *ally_name, + *local_color, *ally_color, + *irc_name, *irc_color; + int ally_enabled = 0, local_enabled = 0, + local_autojoin = 0, ally_autojoin = 0, + allow_user_channel_creation = 0, + irc_enabled = 0; + + if( !config_setting_lookup_string(settings, "map_local_channel_name", &local_name) ) + local_name = "map"; + safestrncpy(hChSys.local_name, local_name, HCHSYS_NAME_LENGTH); + + if( !config_setting_lookup_string(settings, "ally_channel_name", &ally_name) ) + ally_name = "ally"; + safestrncpy(hChSys.ally_name, ally_name, HCHSYS_NAME_LENGTH); + + if( !config_setting_lookup_string(settings, "irc_channel_name", &irc_name) ) + irc_name = "irc"; + safestrncpy(hChSys.irc_name, irc_name, HCHSYS_NAME_LENGTH); + + config_setting_lookup_bool(settings, "map_local_channel", &local_enabled); + config_setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled); + config_setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled); + + if( local_enabled ) + hChSys.local = true; + if( ally_enabled ) + hChSys.ally = true; + if( irc_enabled ) + hChSys.irc = true; + + hChSys.irc_server[0] = hChSys.irc_channel[0] = hChSys.irc_nick[0] = hChSys.irc_nick_pw[0] = '\0'; + + if( hChSys.irc ) { + const char *irc_server, *irc_channel, + *irc_nick, *irc_nick_pw; + if( config_setting_lookup_string(settings, "irc_channel_network", &irc_server) ) { + if( !strstr(irc_server,":") ) { + hChSys.irc = false; + ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n"); + } else { + unsigned char d = 0, dlen = strlen(irc_server); + char server[40]; + for(d = 0; d < dlen; d++) { + if(irc_server[d] == ':') { + memcpy(server, irc_server, d); + safestrncpy(hChSys.irc_server, server, 40); + memcpy(server, &irc_server[d+1], dlen); + hChSys.irc_server_port = atoi(server); + break; + } + } + } + } else { + hChSys.irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n"); + } + if( config_setting_lookup_string(settings, "irc_channel_channel", &irc_channel) ) + safestrncpy(hChSys.irc_channel, irc_channel, 20); + else { + hChSys.irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n"); + } + if( config_setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) { + if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) { + sprintf(hChSys.irc_nick, "Hercules_chSysBot%d",rand()%777); + } else + safestrncpy(hChSys.irc_nick, irc_nick, 30); + } else { + hChSys.irc = false; + ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n"); + } + if( config_setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) + safestrncpy(hChSys.irc_nick_pw, irc_nick_pw, 30); + + } + + config_setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin); + config_setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin); + + if( local_autojoin ) + hChSys.local_autojoin = true; + if( ally_autojoin ) + hChSys.ally_autojoin = true; + + config_setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation); + + if( allow_user_channel_creation ) + hChSys.allow_user_channel_creation = true; + + if( (colors = config_setting_get_member(settings, "colors")) != NULL ) { + int color_count = config_setting_length(colors); + CREATE( hChSys.colors, unsigned long, color_count ); + CREATE( hChSys.colors_name, char *, color_count ); + for(i = 0; i < color_count; i++) { + config_setting_t *color = config_setting_get_elem(colors, i); + + CREATE( hChSys.colors_name[i], char, HCHSYS_NAME_LENGTH ); + + safestrncpy(hChSys.colors_name[i], config_setting_name(color), HCHSYS_NAME_LENGTH); + + hChSys.colors[i] = strtoul(config_setting_get_string_elem(colors,i),NULL,0); + hChSys.colors[i] = (hChSys.colors[i] & 0x0000FF) << 16 | (hChSys.colors[i] & 0x00FF00) | (hChSys.colors[i] & 0xFF0000) >> 16;//RGB to BGR + } + hChSys.colors_count = color_count; + } + + config_setting_lookup_string(settings, "map_local_channel_color", &local_color); + + for (k = 0; k < hChSys.colors_count; k++) { + if( strcmpi(hChSys.colors_name[k],local_color) == 0 ) + break; + } + + if( k < hChSys.colors_count ) { + hChSys.local_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name); + hChSys.local = false; + } + + config_setting_lookup_string(settings, "ally_channel_color", &ally_color); + + for (k = 0; k < hChSys.colors_count; k++) { + if( strcmpi(hChSys.colors_name[k],ally_color) == 0 ) + break; + } + + if( k < hChSys.colors_count ) { + hChSys.ally_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name); + hChSys.ally = false; + } + + config_setting_lookup_string(settings, "irc_channel_color", &irc_color); + + for (k = 0; k < hChSys.colors_count; k++) { + if( strcmpi(hChSys.colors_name[k],irc_color) == 0 ) + break; + } + + if( k < hChSys.colors_count ) { + hChSys.irc_color = k; + } else { + ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name); + hChSys.irc = false; + } + + if( hChSys.irc ) { + struct hChSysCh *chd; + CREATE( chd, struct hChSysCh, 1 ); + + safestrncpy(chd->name, hChSys.irc_name, HCHSYS_NAME_LENGTH); + chd->type = hChSys_IRC; + + clif->chsys_create(chd,NULL,NULL,hChSys.irc_color); + ircbot->channel = chd; + } + + if( (channels = config_setting_get_member(settings, "default_channels")) != NULL ) { + int channel_count = config_setting_length(channels); + + for(i = 0; i < channel_count; i++) { + config_setting_t *channel = config_setting_get_elem(channels, i); + const char *name = config_setting_name(channel); + const char *color = config_setting_get_string_elem(channels,i); + struct hChSysCh *chd; + + for (k = 0; k < hChSys.colors_count; k++) { + if( strcmpi(hChSys.colors_name[k],color) == 0 ) + break; + } + if( k == hChSys.colors_count ) { + ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name); + continue; + } + if( strcmpi(name,hChSys.local_name) == 0 || strcmpi(name,hChSys.ally_name) == 0 || strcmpi(name,hChSys.irc_name) == 0 || strdb_exists(clif->channel_db, name) ) { + ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name); + continue; + + } + CREATE( chd, struct hChSysCh, 1 ); + + safestrncpy(chd->name, name, HCHSYS_NAME_LENGTH); + chd->type = hChSys_PUBLIC; + + clif->chsys_create(chd,NULL,NULL,k); + } + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' channels in '"CL_WHITE"%s"CL_RESET"'.\n", db_size(clif->channel_db), config_filename); + config_destroy(&channels_conf); + } } + /*========================================== * *------------------------------------------*/ -static int clif_hpmeter_sub(struct block_list *bl, va_list ap) -{ +int clif_hpmeter_sub(struct block_list *bl, va_list ap) { struct map_session_data *sd, *tsd; #if PACKETVER < 20100126 const int cmd = 0x106; @@ -2710,10 +2947,9 @@ static int clif_hpmeter_sub(struct block_list *bl, va_list ap) * Server tells all players that are allowed to view HP bars * and are nearby 'sd' that 'sd' hp bar was updated. *------------------------------------------*/ -static int clif_hpmeter(struct map_session_data *sd) -{ +int clif_hpmeter(struct map_session_data *sd) { nullpo_ret(sd); - map_foreachinarea(clif_hpmeter_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd); + map_foreachinarea(clif->hpmeter_sub, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd); return 0; } @@ -2741,205 +2977,205 @@ void clif_updatestatus(struct map_session_data *sd,int type) WFIFOW(fd,0)=0xb0; WFIFOW(fd,2)=type; switch(type){ - // 00b0 - case SP_WEIGHT: - pc_updateweightstatus(sd); - WFIFOHEAD(fd,14); - WFIFOW(fd,0)=0xb0; //Need to re-set as pc_updateweightstatus can alter the buffer. [Skotlex] - WFIFOW(fd,2)=type; - WFIFOL(fd,4)=sd->weight; - break; - case SP_MAXWEIGHT: - WFIFOL(fd,4)=sd->max_weight; - break; - case SP_SPEED: - WFIFOL(fd,4)=sd->battle_status.speed; - break; - case SP_BASELEVEL: - WFIFOL(fd,4)=sd->status.base_level; - break; - case SP_JOBLEVEL: - WFIFOL(fd,4)=sd->status.job_level; - break; - case SP_KARMA: // Adding this back, I wonder if the client intercepts this - [Lance] - WFIFOL(fd,4)=sd->status.karma; - break; - case SP_MANNER: - WFIFOL(fd,4)=sd->status.manner; - break; - case SP_STATUSPOINT: - WFIFOL(fd,4)=sd->status.status_point; - break; - case SP_SKILLPOINT: - WFIFOL(fd,4)=sd->status.skill_point; - break; - case SP_HIT: - WFIFOL(fd,4)=sd->battle_status.hit; - break; - case SP_FLEE1: - WFIFOL(fd,4)=sd->battle_status.flee; - break; - case SP_FLEE2: - WFIFOL(fd,4)=sd->battle_status.flee2/10; - break; - case SP_MAXHP: - WFIFOL(fd,4)=sd->battle_status.max_hp; - break; - case SP_MAXSP: - WFIFOL(fd,4)=sd->battle_status.max_sp; - break; - case SP_HP: - WFIFOL(fd,4)=sd->battle_status.hp; - // TODO: Won't these overwrite the current packet? - clif_hpmeter(sd); - if( !battle_config.party_hp_mode && sd->status.party_id ) - clif_party_hp(sd); - if( sd->bg_id ) - clif_bg_hp(sd); - break; - case SP_SP: - WFIFOL(fd,4)=sd->battle_status.sp; - break; - case SP_ASPD: - WFIFOL(fd,4)=sd->battle_status.amotion; - break; - case SP_ATK1: - WFIFOL(fd,4)=pc_leftside_atk(sd); - break; - case SP_DEF1: - WFIFOL(fd,4)=pc_leftside_def(sd); - break; - case SP_MDEF1: - WFIFOL(fd,4)=pc_leftside_mdef(sd); - break; - case SP_ATK2: - WFIFOL(fd,4)=pc_rightside_atk(sd); - break; - case SP_DEF2: - WFIFOL(fd,4)=pc_rightside_def(sd); - break; - case SP_MDEF2: { - //negative check (in case you have something like Berserk active) - int mdef2 = pc_rightside_mdef(sd); + // 00b0 + case SP_WEIGHT: + pc_updateweightstatus(sd); + WFIFOHEAD(fd,14); + WFIFOW(fd,0)=0xb0; //Need to re-set as pc_updateweightstatus can alter the buffer. [Skotlex] + WFIFOW(fd,2)=type; + WFIFOL(fd,4)=sd->weight; + break; + case SP_MAXWEIGHT: + WFIFOL(fd,4)=sd->max_weight; + break; + case SP_SPEED: + WFIFOL(fd,4)=sd->battle_status.speed; + break; + case SP_BASELEVEL: + WFIFOL(fd,4)=sd->status.base_level; + break; + case SP_JOBLEVEL: + WFIFOL(fd,4)=sd->status.job_level; + break; + case SP_KARMA: // Adding this back, I wonder if the client intercepts this - [Lance] + WFIFOL(fd,4)=sd->status.karma; + break; + case SP_MANNER: + WFIFOL(fd,4)=sd->status.manner; + break; + case SP_STATUSPOINT: + WFIFOL(fd,4)=sd->status.status_point; + break; + case SP_SKILLPOINT: + WFIFOL(fd,4)=sd->status.skill_point; + break; + case SP_HIT: + WFIFOL(fd,4)=sd->battle_status.hit; + break; + case SP_FLEE1: + WFIFOL(fd,4)=sd->battle_status.flee; + break; + case SP_FLEE2: + WFIFOL(fd,4)=sd->battle_status.flee2/10; + break; + case SP_MAXHP: + WFIFOL(fd,4)=sd->battle_status.max_hp; + break; + case SP_MAXSP: + WFIFOL(fd,4)=sd->battle_status.max_sp; + break; + case SP_HP: + WFIFOL(fd,4)=sd->battle_status.hp; + // TODO: Won't these overwrite the current packet? + clif->hpmeter(sd); + if( !battle_config.party_hp_mode && sd->status.party_id ) + clif->party_hp(sd); + if( sd->bg_id ) + clif->bg_hp(sd); + break; + case SP_SP: + WFIFOL(fd,4)=sd->battle_status.sp; + break; + case SP_ASPD: + WFIFOL(fd,4)=sd->battle_status.amotion; + break; + case SP_ATK1: + WFIFOL(fd,4)=pc_leftside_atk(sd); + break; + case SP_DEF1: + WFIFOL(fd,4)=pc_leftside_def(sd); + break; + case SP_MDEF1: + WFIFOL(fd,4)=pc_leftside_mdef(sd); + break; + case SP_ATK2: + WFIFOL(fd,4)=pc_rightside_atk(sd); + break; + case SP_DEF2: + WFIFOL(fd,4)=pc_rightside_def(sd); + break; + case SP_MDEF2: { + //negative check (in case you have something like Berserk active) + int mdef2 = pc_rightside_mdef(sd); - WFIFOL(fd,4)= -#ifndef RENEWAL - ( mdef2 < 0 ) ? 0 : -#endif - mdef2; + WFIFOL(fd,4)= + #ifndef RENEWAL + ( mdef2 < 0 ) ? 0 : + #endif + mdef2; - } - break; - case SP_CRITICAL: - WFIFOL(fd,4)=sd->battle_status.cri/10; - break; - case SP_MATK1: - WFIFOL(fd,4)=pc_rightside_matk(sd); - break; - case SP_MATK2: - WFIFOL(fd,4)=pc_leftside_matk(sd); - break; + } + break; + case SP_CRITICAL: + WFIFOL(fd,4)=sd->battle_status.cri/10; + break; + case SP_MATK1: + WFIFOL(fd,4)=pc_rightside_matk(sd); + break; + case SP_MATK2: + WFIFOL(fd,4)=pc_leftside_matk(sd); + break; - case SP_ZENY: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.zeny; - break; - case SP_BASEEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.base_exp; - break; - case SP_JOBEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=sd->status.job_exp; - break; - case SP_NEXTBASEEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=pc_nextbaseexp(sd); - break; - case SP_NEXTJOBEXP: - WFIFOW(fd,0)=0xb1; - WFIFOL(fd,4)=pc_nextjobexp(sd); - break; + case SP_ZENY: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=sd->status.zeny; + break; + case SP_BASEEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=sd->status.base_exp; + break; + case SP_JOBEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=sd->status.job_exp; + break; + case SP_NEXTBASEEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=pc_nextbaseexp(sd); + break; + case SP_NEXTJOBEXP: + WFIFOW(fd,0)=0xb1; + WFIFOL(fd,4)=pc_nextjobexp(sd); + break; - /** - * SP_U<STAT> are used to update the amount of points necessary to increase that stat - **/ - case SP_USTR: - case SP_UAGI: - case SP_UVIT: - case SP_UINT: - case SP_UDEX: - case SP_ULUK: - WFIFOW(fd,0)=0xbe; - WFIFOB(fd,4)=pc_need_status_point(sd,type-SP_USTR+SP_STR,1); - len=5; - break; + /** + * SP_U<STAT> are used to update the amount of points necessary to increase that stat + **/ + case SP_USTR: + case SP_UAGI: + case SP_UVIT: + case SP_UINT: + case SP_UDEX: + case SP_ULUK: + WFIFOW(fd,0)=0xbe; + WFIFOB(fd,4)=pc_need_status_point(sd,type-SP_USTR+SP_STR,1); + len=5; + break; - /** - * Tells the client how far it is allowed to attack (weapon range) - **/ - case SP_ATTACKRANGE: - WFIFOW(fd,0)=0x13a; - WFIFOW(fd,2)=sd->battle_status.rhw.range; - len=4; - break; + /** + * Tells the client how far it is allowed to attack (weapon range) + **/ + case SP_ATTACKRANGE: + WFIFOW(fd,0)=0x13a; + WFIFOW(fd,2)=sd->battle_status.rhw.range; + len=4; + break; - case SP_STR: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.str; - WFIFOL(fd,10)=sd->battle_status.str - sd->status.str; - len=14; - break; - case SP_AGI: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.agi; - WFIFOL(fd,10)=sd->battle_status.agi - sd->status.agi; - len=14; - break; - case SP_VIT: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.vit; - WFIFOL(fd,10)=sd->battle_status.vit - sd->status.vit; - len=14; - break; - case SP_INT: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.int_; - WFIFOL(fd,10)=sd->battle_status.int_ - sd->status.int_; - len=14; - break; - case SP_DEX: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.dex; - WFIFOL(fd,10)=sd->battle_status.dex - sd->status.dex; - len=14; - break; - case SP_LUK: - WFIFOW(fd,0)=0x141; - WFIFOL(fd,2)=type; - WFIFOL(fd,6)=sd->status.luk; - WFIFOL(fd,10)=sd->battle_status.luk - sd->status.luk; - len=14; - break; + case SP_STR: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.str; + WFIFOL(fd,10)=sd->battle_status.str - sd->status.str; + len=14; + break; + case SP_AGI: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.agi; + WFIFOL(fd,10)=sd->battle_status.agi - sd->status.agi; + len=14; + break; + case SP_VIT: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.vit; + WFIFOL(fd,10)=sd->battle_status.vit - sd->status.vit; + len=14; + break; + case SP_INT: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.int_; + WFIFOL(fd,10)=sd->battle_status.int_ - sd->status.int_; + len=14; + break; + case SP_DEX: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.dex; + WFIFOL(fd,10)=sd->battle_status.dex - sd->status.dex; + len=14; + break; + case SP_LUK: + WFIFOW(fd,0)=0x141; + WFIFOL(fd,2)=type; + WFIFOL(fd,6)=sd->status.luk; + WFIFOL(fd,10)=sd->battle_status.luk - sd->status.luk; + len=14; + break; - case SP_CARTINFO: - WFIFOW(fd,0)=0x121; - WFIFOW(fd,2)=sd->cart_num; - WFIFOW(fd,4)=MAX_CART; - WFIFOL(fd,6)=sd->cart_weight; - WFIFOL(fd,10)=sd->cart_weight_max; - len=14; - break; + case SP_CARTINFO: + WFIFOW(fd,0)=0x121; + WFIFOW(fd,2)=sd->cart_num; + WFIFOW(fd,4)=MAX_CART; + WFIFOL(fd,6)=sd->cart_weight; + WFIFOL(fd,10)=sd->cart_weight_max; + len=14; + break; - default: - ShowError("clif_updatestatus : unrecognized type %d\n",type); - return; + default: + ShowError("clif->updatestatus : unrecognized type %d\n",type); + return; } WFIFOSET(fd,len); } @@ -2967,7 +3203,7 @@ void clif_changestatus(struct map_session_data* sd,int type,int val) return; } - clif_send(buf,packet_len(0x1ab),&sd->bl,AREA_WOS); + clif->send(buf,packet_len(0x1ab),&sd->bl,AREA_WOS); } @@ -2977,7 +3213,7 @@ void clif_changestatus(struct map_session_data* sd,int type,int val) void clif_changelook(struct block_list *bl,int type,int val) { unsigned char buf[16]; - struct map_session_data* sd = NULL; + struct map_session_data* sd; struct status_change* sc; struct view_data* vd; enum send_target target = AREA; @@ -2988,85 +3224,97 @@ void clif_changelook(struct block_list *bl,int type,int val) vd = status_get_viewdata(bl); //nullpo_ret(vd); if( vd ) //temp hack to let Warp Portal change appearance - switch(type) - { - case LOOK_WEAPON: - if (sd) - { - clif_get_weapon_view(sd, &vd->weapon, &vd->shield); - val = vd->weapon; - } - else vd->weapon = val; - break; - case LOOK_SHIELD: - if (sd) - { - clif_get_weapon_view(sd, &vd->weapon, &vd->shield); - val = vd->shield; - } - else vd->shield = val; - break; - case LOOK_BASE: - vd->class_ = val; - if (vd->class_ == JOB_WEDDING || vd->class_ == JOB_XMAS || vd->class_ == JOB_SUMMER) - vd->weapon = vd->shield = 0; - if (vd->cloth_color && ( - (vd->class_ == JOB_WEDDING && battle_config.wedding_ignorepalette) || - (vd->class_ == JOB_XMAS && battle_config.xmas_ignorepalette) || - (vd->class_ == JOB_SUMMER && battle_config.summer_ignorepalette) - )) - clif_changelook(bl,LOOK_CLOTHES_COLOR,0); - break; - case LOOK_HAIR: - vd->hair_style = val; - break; - case LOOK_HEAD_BOTTOM: - vd->head_bottom = val; - break; - case LOOK_HEAD_TOP: - vd->head_top = val; - break; - case LOOK_HEAD_MID: - vd->head_mid = val; - break; - case LOOK_HAIR_COLOR: - vd->hair_color = val; - break; - case LOOK_CLOTHES_COLOR: - if (val && ( - (vd->class_ == JOB_WEDDING && battle_config.wedding_ignorepalette) || - (vd->class_ == JOB_XMAS && battle_config.xmas_ignorepalette) || - (vd->class_ == JOB_SUMMER && battle_config.summer_ignorepalette) - )) - val = 0; - vd->cloth_color = val; - break; - case LOOK_SHOES: -#if PACKETVER > 3 - if (sd) { - int n; - if((n = sd->equip_index[2]) >= 0 && sd->inventory_data[n]) { - if(sd->inventory_data[n]->view_id > 0) - val = sd->inventory_data[n]->view_id; - else - val = sd->status.inventory[n].nameid; - } else - val = 0; - } -#endif - //Shoes? No packet uses this.... - break; - case LOOK_BODY: - case LOOK_FLOOR: - // unknown purpose - break; - case LOOK_ROBE: -#if PACKETVER < 20110111 - return; -#else - vd->robe = val; -#endif - break; + switch(type) { + case LOOK_WEAPON: + if (sd) { + clif->get_weapon_view(sd, &vd->weapon, &vd->shield); + val = vd->weapon; + } + else + vd->weapon = val; + break; + case LOOK_SHIELD: + if (sd) { + clif->get_weapon_view(sd, &vd->weapon, &vd->shield); + val = vd->shield; + } + else + vd->shield = val; + break; + case LOOK_BASE: + if( !sd ) break; + + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) + vd->weapon = vd->shield = 0; + + if( !vd->cloth_color ) + break; + + if( sd ) { + if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette ) + vd->cloth_color = 0; + if( sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette ) + vd->cloth_color = 0; + if( sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette ) + vd->cloth_color = 0; + if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette ) + vd->cloth_color = 0; + } + break; + case LOOK_HAIR: + vd->hair_style = val; + break; + case LOOK_HEAD_BOTTOM: + vd->head_bottom = val; + break; + case LOOK_HEAD_TOP: + vd->head_top = val; + break; + case LOOK_HEAD_MID: + vd->head_mid = val; + break; + case LOOK_HAIR_COLOR: + vd->hair_color = val; + break; + case LOOK_CLOTHES_COLOR: + if( val && sd ) { + if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette ) + val = 0; + if( sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette ) + val = 0; + if( sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette ) + val = 0; + if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette ) + val = 0; + } + vd->cloth_color = val; + break; + case LOOK_SHOES: + #if PACKETVER > 3 + if (sd) { + int n; + if((n = sd->equip_index[2]) >= 0 && sd->inventory_data[n]) { + if(sd->inventory_data[n]->view_id > 0) + val = sd->inventory_data[n]->view_id; + else + val = sd->status.inventory[n].nameid; + } else + val = 0; + } + #endif + //Shoes? No packet uses this.... + break; + case LOOK_BODY: + case LOOK_FLOOR: + // unknown purpose + break; + case LOOK_ROBE: + #if PACKETVER < 20110111 + return; + #else + vd->robe = val; + #endif + break; } // prevent leaking the presence of GM-hidden objects @@ -3078,7 +3326,7 @@ void clif_changelook(struct block_list *bl,int type,int val) WBUFL(buf,2)=bl->id; WBUFB(buf,6)=type; WBUFB(buf,7)=val; - clif_send(buf,packet_len(0xc3),bl,target); + clif->send(buf,packet_len(0xc3),bl,target); #else WBUFW(buf,0)=0x1d7; WBUFL(buf,2)=bl->id; @@ -3090,7 +3338,11 @@ void clif_changelook(struct block_list *bl,int type,int val) WBUFB(buf,6)=type; WBUFL(buf,7)=val; } - clif_send(buf,packet_len(0x1d7),bl,target); + clif->send(buf,packet_len(0x1d7),bl,target); + if( disguised(bl) && ((TBL_PC*)sd)->fontcolor ) { + WBUFL(buf,2)=-bl->id; + clif->send(buf,packet_len(0x1d7),bl,SELF); + } #endif } @@ -3103,14 +3355,14 @@ void clif_changetraplook(struct block_list *bl,int val) WBUFL(buf,2)=bl->id; WBUFB(buf,6)=LOOK_BASE; WBUFB(buf,7)=val; - clif_send(buf,packet_len(0xc3),bl,AREA); + clif->send(buf,packet_len(0xc3),bl,AREA); #else WBUFW(buf,0)=0x1d7; WBUFL(buf,2)=bl->id; WBUFB(buf,6)=LOOK_BASE; WBUFW(buf,7)=val; WBUFW(buf,9)=0; - clif_send(buf,packet_len(0x1d7),bl,AREA); + clif->send(buf,packet_len(0x1d7),bl,AREA); #endif } @@ -3123,14 +3375,14 @@ void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_ta WBUFL(buf,2)=id; WBUFB(buf,6)=type; WBUFB(buf,7)=val; - clif_send(buf,packet_len(0xc3),bl,target); + clif->send(buf,packet_len(0xc3),bl,target); #else WBUFW(buf,0)=0x1d7; WBUFL(buf,2)=id; WBUFB(buf,6)=type; WBUFW(buf,7)=val; WBUFW(buf,9)=0; - clif_send(buf,packet_len(0x1d7),bl,target); + clif->send(buf,packet_len(0x1d7),bl,target); #endif } @@ -3140,8 +3392,7 @@ void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_ta /// <int>.B <need int>.B <dex>.B <need dex>.B <luk>.B <need luk>.B <atk>.W <atk2>.W /// <matk min>.W <matk max>.W <def>.W <def2>.W <mdef>.W <mdef2>.W <hit>.W /// <flee>.W <flee2>.W <crit>.W <aspd>.W <aspd2>.W -void clif_initialstatus(struct map_session_data *sd) -{ +void clif_initialstatus(struct map_session_data *sd) { int fd, mdef2; unsigned char *buf; @@ -3188,15 +3439,15 @@ void clif_initialstatus(struct map_session_data *sd) WFIFOSET(fd,packet_len(0xbd)); - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); + clif->updatestatus(sd,SP_STR); + clif->updatestatus(sd,SP_AGI); + clif->updatestatus(sd,SP_VIT); + clif->updatestatus(sd,SP_INT); + clif->updatestatus(sd,SP_DEX); + clif->updatestatus(sd,SP_LUK); - clif_updatestatus(sd,SP_ATTACKRANGE); - clif_updatestatus(sd,SP_ASPD); + clif->updatestatus(sd,SP_ATTACKRANGE); + clif->updatestatus(sd,SP_ASPD); } @@ -3373,7 +3624,7 @@ void clif_misceffect(struct block_list* bl,int type) WBUFL(buf,2) = bl->id; WBUFL(buf,6) = type; - clif_send(buf,packet_len(0x19b),bl,AREA); + clif->send(buf,packet_len(0x19b),bl,AREA); } @@ -3399,14 +3650,14 @@ void clif_changeoption(struct block_list* bl) WBUFL(buf,10) = sc->option; WBUFB(buf,14) = (sd)? sd->status.karma : 0; if(disguised(bl)) { - clif_send(buf,packet_len(0x229),bl,AREA_WOS); + clif->send(buf,packet_len(0x229),bl,AREA_WOS); WBUFL(buf,2) = -bl->id; - clif_send(buf,packet_len(0x229),bl,SELF); + clif->send(buf,packet_len(0x229),bl,SELF); WBUFL(buf,2) = bl->id; WBUFL(buf,10) = OPTION_INVISIBLE; - clif_send(buf,packet_len(0x229),bl,SELF); + clif->send(buf,packet_len(0x229),bl,SELF); } else - clif_send(buf,packet_len(0x229),bl,AREA); + clif->send(buf,packet_len(0x229),bl,AREA); #else WBUFW(buf,0) = 0x119; WBUFL(buf,2) = bl->id; @@ -3415,14 +3666,14 @@ void clif_changeoption(struct block_list* bl) WBUFW(buf,10) = sc->option; WBUFB(buf,12) = (sd)? sd->status.karma : 0; if(disguised(bl)) { - clif_send(buf,packet_len(0x119),bl,AREA_WOS); + clif->send(buf,packet_len(0x119),bl,AREA_WOS); WBUFL(buf,2) = -bl->id; - clif_send(buf,packet_len(0x119),bl,SELF); + clif->send(buf,packet_len(0x119),bl,SELF); WBUFL(buf,2) = bl->id; WBUFW(buf,10) = OPTION_INVISIBLE; - clif_send(buf,packet_len(0x119),bl,SELF); + clif->send(buf,packet_len(0x119),bl,SELF); } else - clif_send(buf,packet_len(0x119),bl,AREA); + clif->send(buf,packet_len(0x119),bl,AREA); #endif } @@ -3443,14 +3694,14 @@ void clif_changeoption2(struct block_list* bl) WBUFL(buf,10) = clif_setlevel(bl); WBUFL(buf,14) = sc->opt3; if(disguised(bl)) { - clif_send(buf,packet_len(0x28a),bl,AREA_WOS); + clif->send(buf,packet_len(0x28a),bl,AREA_WOS); WBUFL(buf,2) = -bl->id; - clif_send(buf,packet_len(0x28a),bl,SELF); + clif->send(buf,packet_len(0x28a),bl,SELF); WBUFL(buf,2) = bl->id; WBUFL(buf,6) = OPTION_INVISIBLE; - clif_send(buf,packet_len(0x28a),bl,SELF); + clif->send(buf,packet_len(0x28a),bl,SELF); } else - clif_send(buf,packet_len(0x28a),bl,AREA); + clif->send(buf,packet_len(0x28a),bl,AREA); } @@ -3491,11 +3742,25 @@ void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok) WBUFL(buf,6)=sd->bl.id; WBUFW(buf,10)=amount; WBUFB(buf,12)=ok; - clif_send(buf,packet_len(0x1c8),&sd->bl,AREA); + clif->send(buf,packet_len(0x1c8),&sd->bl,AREA); #endif } } +void clif_hercules_chsys_send(struct hChSysCh *channel, struct map_session_data *sd, char *msg) { + if( channel->msg_delay != 0 && DIFF_TICK(sd->hchsysch_tick + ( channel->msg_delay * 1000 ), gettick()) > 0 && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ) { + clif->colormes(sd->fd,COLOR_RED,msg_txt(1455)); + return; + } else { + char message[150]; + snprintf(message, 150, "[ #%s ] %s : %s",channel->name,sd->status.name, msg); + clif->chsys_msg(channel,sd,message); + if( channel->type == hChSys_IRC ) + ircbot->relay(sd->status.name,msg); + if( channel->msg_delay != 0 ) + sd->hchsysch_tick = gettick(); + } +} /// Inform client whether chatroom creation was successful or not (ZC_ACK_CREATE_CHATROOM). /// 00d6 <flag>.B @@ -3550,7 +3815,7 @@ void clif_dispchat(struct chat_data* cd, int fd) memcpy(WFIFOP(fd,0),buf,WBUFW(buf,2)); WFIFOSET(fd,WBUFW(buf,2)); } else { - clif_send(buf,WBUFW(buf,2),cd->owner,AREA_WOSC); + clif->send(buf,WBUFW(buf,2),cd->owner,AREA_WOSC); } } @@ -3583,7 +3848,7 @@ void clif_changechatstatus(struct chat_data* cd) WBUFB(buf,16) = type; memcpy((char*)WBUFP(buf,17), cd->title, strlen(cd->title)); // not zero-terminated - clif_send(buf,WBUFW(buf,2),cd->owner,CHAT); + clif->send(buf,WBUFW(buf,2),cd->owner,CHAT); } @@ -3602,7 +3867,7 @@ void clif_clearchat(struct chat_data *cd,int fd) memcpy(WFIFOP(fd,0),buf,packet_len(0xd8)); WFIFOSET(fd,packet_len(0xd8)); } else { - clif_send(buf,packet_len(0xd8),cd->owner,AREA_WOSC); + clif->send(buf,packet_len(0xd8),cd->owner,AREA_WOSC); } } @@ -3684,7 +3949,7 @@ void clif_addchat(struct chat_data* cd,struct map_session_data *sd) WBUFW(buf, 0) = 0xdc; WBUFW(buf, 2) = cd->users; memcpy(WBUFP(buf, 4),sd->status.name,NAME_LENGTH); - clif_send(buf,packet_len(0xdc),&sd->bl,CHAT_WOS); + clif->send(buf,packet_len(0xdc),&sd->bl,CHAT_WOS); } @@ -3708,7 +3973,7 @@ void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd) WBUFL(buf,32) = 0; memcpy(WBUFP(buf,36),sd->status.name,NAME_LENGTH); - clif_send(buf,packet_len(0xe1)*2,&sd->bl,CHAT); + clif->send(buf,packet_len(0xe1)*2,&sd->bl,CHAT); } @@ -3729,7 +3994,7 @@ void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag memcpy(WBUFP(buf,4),sd->status.name,NAME_LENGTH); WBUFB(buf,28) = flag; - clif_send(buf,packet_len(0xdd),&sd->bl,CHAT); + clif->send(buf,packet_len(0xdd),&sd->bl,CHAT); } @@ -3848,7 +4113,7 @@ void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd WBUFB(buf,8) = sd->status.inventory[index].identify; //identify flag WBUFB(buf,9) = sd->status.inventory[index].attribute; // attribute WBUFB(buf,10)= sd->status.inventory[index].refine; //refine - clif_addcards(WBUFP(buf, 11), &sd->status.inventory[index]); + clif->addcards(WBUFP(buf, 11), &sd->status.inventory[index]); } WFIFOSET(fd,packet_len(cmd)); } @@ -3976,7 +4241,7 @@ void clif_storageitemadded(struct map_session_data* sd, struct item* i, int inde WFIFOB(fd,10) = i->identify; //identify flag WFIFOB(fd,11) = i->attribute; // attribute WFIFOB(fd,12) = i->refine; //refine - clif_addcards(WFIFOP(fd,13), i); + clif->addcards(WFIFOP(fd,13), i); WFIFOSET(fd,packet_len(0xf4)); #else WFIFOHEAD(fd,packet_len(0x1c4)); @@ -3988,7 +4253,7 @@ void clif_storageitemadded(struct map_session_data* sd, struct item* i, int inde WFIFOB(fd,11) = i->identify; //identify flag WFIFOB(fd,12) = i->attribute; // attribute WFIFOB(fd,13) = i->refine; //refine - clif_addcards(WFIFOP(fd,14), i); + clif->addcards(WFIFOP(fd,14), i); WFIFOSET(fd,packet_len(0x1c4)); #endif } @@ -4028,57 +4293,48 @@ void clif_storageclose(struct map_session_data* sd) /*========================================== * Server tells 'sd' player client the abouts of 'dstsd' player *------------------------------------------*/ -static void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* dstsd) -{ +void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* dstsd) { struct block_list *d_bl; int i; if( dstsd->chatID ) { struct chat_data *cd = NULL; if( (cd = (struct chat_data*)map_id2bl(dstsd->chatID)) && cd->usersd[0]==dstsd) - clif_dispchat(cd,sd->fd); + clif->dispchat(cd,sd->fd); } else if( dstsd->state.vending ) - clif_showvendingboard(&dstsd->bl,dstsd->message,sd->fd); + clif->showvendingboard(&dstsd->bl,dstsd->message,sd->fd); else if( dstsd->state.buyingstore ) - clif_buyingstore_entry_single(sd, dstsd); + clif->buyingstore_entry_single(sd, dstsd); if(dstsd->spiritball > 0) - clif_spiritball_single(sd->fd, dstsd); + clif->spiritball_single(sd->fd, dstsd); for(i = 1; i < 5; i++){ if( dstsd->talisman[i] > 0 ) - clif_talisman_single(sd->fd, dstsd, i); + clif->talisman_single(sd->fd, dstsd, i); } - if( dstsd->sc.option&OPTION_MOUNTING ) { - //New Mounts are not complaint to the original method, so we gotta tell this guy that I'm mounting. - clif_status_load_single(sd->fd,dstsd->bl.id,SI_ALL_RIDING,2,1,0,0); + for( i = 0; i < dstsd->sc_display_count; i++ ) { + clif->sc_load(&sd->bl,dstsd->bl.id,SELF,StatusIconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3); } -#ifdef NEW_CARTS - if( dstsd->sc.data[SC_PUSH_CART] ) - clif_status_load_single(sd->fd, dstsd->bl.id, SI_ON_PUSH_CART, 2, dstsd->sc.data[SC_PUSH_CART]->val1, 0, 0); -#endif if( (sd->status.party_id && dstsd->status.party_id == sd->status.party_id) || //Party-mate, or hpdisp setting. (sd->bg_id && sd->bg_id == dstsd->bg_id) || //BattleGround pc_has_permission(sd, PC_PERM_VIEW_HPMETER) ) - clif_hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); + clif->hpmeter_single(sd->fd, dstsd->bl.id, dstsd->battle_status.hp, dstsd->battle_status.max_hp); // display link (sd - dstsd) to sd ARR_FIND( 0, 5, i, sd->devotion[i] == dstsd->bl.id ); - if( i < 5 ) clif_devotion(&sd->bl, sd); + if( i < 5 ) clif->devotion(&sd->bl, sd); // display links (dstsd - devotees) to sd ARR_FIND( 0, 5, i, dstsd->devotion[i] > 0 ); - if( i < 5 ) clif_devotion(&dstsd->bl, sd); + if( i < 5 ) clif->devotion(&dstsd->bl, sd); // display link (dstsd - crusader) to sd if( dstsd->sc.data[SC_DEVOTION] && (d_bl = map_id2bl(dstsd->sc.data[SC_DEVOTION]->val1)) != NULL ) - clif_devotion(d_bl, sd); + clif->devotion(d_bl, sd); } -void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) -{ - uint8 buf[128]; +void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) { struct unit_data *ud; struct view_data *vd; - int len; vd = status_get_viewdata(bl); if (!vd || vd->class_ == INVISIBLE_CLASS) @@ -4090,65 +4346,67 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) if(bl->type == BL_NPC && !((TBL_NPC*)bl)->chat_id && (((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE)) return; - ud = unit_bl2ud(bl); - len = ( ud && ud->walktimer != INVALID_TIMER ) ? clif_set_unit_walking(bl,ud,buf) : clif_set_unit_idle(bl,buf,false); - clif_send(buf,len,&sd->bl,SELF); + if ( ( ud = unit_bl2ud(bl) ) && ud->walktimer != INVALID_TIMER ) + clif->set_unit_walking(bl,sd,ud,SELF); + else + clif->set_unit_idle(bl,sd,SELF); if (vd->cloth_color) - clif_refreshlook(&sd->bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,SELF); - - switch (bl->type) - { - case BL_PC: - { - TBL_PC* tsd = (TBL_PC*)bl; - clif_getareachar_pc(sd, tsd); - if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris] - clif_specialeffect_single(bl,423,sd->fd); - else if(tsd->state.size==SZ_MEDIUM) - clif_specialeffect_single(bl,421,sd->fd); - if( tsd->bg_id && map[tsd->bl.m].flag.battleground ) - clif_sendbgemblem_single(sd->fd,tsd); - if( tsd->sc.data[SC_CAMOUFLAGE] ) - clif_status_load(bl,SI_CAMOUFLAGE,1); - } - break; - case BL_MER: // Devotion Effects - if( ((TBL_MER*)bl)->devotion_flag ) - clif_devotion(bl, sd); - break; - case BL_NPC: - { - TBL_NPC* nd = (TBL_NPC*)bl; - if( nd->chat_id ) - clif_dispchat((struct chat_data*)map_id2bl(nd->chat_id),sd->fd); - if( nd->size == SZ_BIG ) - clif_specialeffect_single(bl,423,sd->fd); - else if( nd->size == SZ_MEDIUM ) - clif_specialeffect_single(bl,421,sd->fd); - } - break; - case BL_MOB: - { - TBL_MOB* md = (TBL_MOB*)bl; - if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] - clif_specialeffect_single(bl,423,sd->fd); - else if(md->special_state.size==SZ_MEDIUM) - clif_specialeffect_single(bl,421,sd->fd); -#if PACKETVER >= 20120404 - if( !(md->status.mode&MD_BOSS) ){ - int i; - for(i = 0; i < DAMAGELOG_SIZE; i++)// must show hp bar to all char who already hit the mob. - if( md->dmglog[i].id == sd->status.char_id ) - clif_monster_hp_bar(md, sd->fd); + clif->refreshlook(&sd->bl,bl->id,LOOK_CLOTHES_COLOR,vd->cloth_color,SELF); + switch (bl->type) { + case BL_PC: + { + TBL_PC* tsd = (TBL_PC*)bl; + clif->getareachar_pc(sd, tsd); + if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris] + clif->specialeffect_single(bl,423,sd->fd); + else if(tsd->state.size==SZ_MEDIUM) + clif->specialeffect_single(bl,421,sd->fd); + if( tsd->bg_id && map[tsd->bl.m].flag.battleground ) + clif->sendbgemblem_single(sd->fd,tsd); + if ( tsd->status.robe ) + clif->refreshlook(&sd->bl,bl->id,LOOK_ROBE,tsd->status.robe,SELF); } + break; + case BL_MER: // Devotion Effects + if( ((TBL_MER*)bl)->devotion_flag ) + clif->devotion(bl, sd); + break; + case BL_NPC: + { + TBL_NPC* nd = (TBL_NPC*)bl; + if( nd->chat_id ) + clif->dispchat((struct chat_data*)map_id2bl(nd->chat_id),sd->fd); + if( nd->size == SZ_BIG ) + clif->specialeffect_single(bl,423,sd->fd); + else if( nd->size == SZ_MEDIUM ) + clif->specialeffect_single(bl,421,sd->fd); + } + break; + case BL_MOB: + { + TBL_MOB* md = (TBL_MOB*)bl; + if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris] + clif->specialeffect_single(bl,423,sd->fd); + else if(md->special_state.size==SZ_MEDIUM) + clif->specialeffect_single(bl,421,sd->fd); +#if PACKETVER >= 20120404 + if( !(md->status.mode&MD_BOSS) ){ + int i; + for(i = 0; i < DAMAGELOG_SIZE; i++) {// must show hp bar to all char who already hit the mob. + if( md->dmglog[i].id == sd->status.char_id ) { + clif->monster_hp_bar(md, sd); + break; + } + } + } #endif - } - break; - case BL_PET: - if (vd->head_bottom) - clif_pet_equip(sd, (TBL_PET*)bl); // needed to display pet equip properly - break; + } + break; + case BL_PET: + if (vd->head_bottom) + clif->send_petdata(NULL, (TBL_PET*)bl, 3, vd->head_bottom); // needed to display pet equip properly + break; } } @@ -4162,8 +4420,7 @@ static inline int clif_calc_delay(int type, int div, int damage, int delay) /*========================================== * Estimates walk delay based on the damage criteria. [Skotlex] *------------------------------------------*/ -static int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, int div_) -{ +int clif_calc_walkdelay(struct block_list *bl,int delay, int type, int damage, int div_) { if (type == 4 || type == 9 || damage <=0) return 0; @@ -4248,11 +4505,11 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic WBUFB(buf,28)=type; #endif if(disguised(dst)) { - clif_send(buf,packet_len(cmd),dst,AREA_WOS); + clif->send(buf,packet_len(cmd),dst,AREA_WOS); WBUFL(buf,6) = -dst->id; - clif_send(buf,packet_len(cmd),dst,SELF); + clif->send(buf,packet_len(cmd),dst,SELF); } else - clif_send(buf,packet_len(cmd),dst,AREA); + clif->send(buf,packet_len(cmd),dst,AREA); if(disguised(src)) { WBUFL(buf,2) = -src->id; @@ -4265,14 +4522,14 @@ int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tic if(damage > 0) WBUFL(buf,22) = -1; if(damage2 > 0) WBUFL(buf,29) = -1; #endif - clif_send(buf,packet_len(cmd),src,SELF); + clif->send(buf,packet_len(cmd),src,SELF); } if(src == dst) { unit_setdir(src,unit_getdir(src)); } //Return adjusted can't walk delay for further processing. - return clif_calc_walkdelay(dst,ddelay,type,damage+damage2,div); + return clif->calc_walkdelay(dst,ddelay,type,damage+damage2,div); } /*========================================== @@ -4290,7 +4547,7 @@ void clif_takeitem(struct block_list* src, struct block_list* dst) WBUFL(buf, 2) = src->id; WBUFL(buf, 6) = dst->id; WBUFB(buf,26) = 1; - clif_send(buf, packet_len(0x8a), src, AREA); + clif->send(buf, packet_len(0x8a), src, AREA); } @@ -4305,11 +4562,11 @@ void clif_sitting(struct block_list* bl) WBUFW(buf, 0) = 0x8a; WBUFL(buf, 2) = bl->id; WBUFB(buf,26) = 2; - clif_send(buf, packet_len(0x8a), bl, AREA); + clif->send(buf, packet_len(0x8a), bl, AREA); if(disguised(bl)) { WBUFL(buf, 2) = - bl->id; - clif_send(buf, packet_len(0x8a), bl, SELF); + clif->send(buf, packet_len(0x8a), bl, SELF); } } @@ -4324,11 +4581,11 @@ void clif_standing(struct block_list* bl) WBUFW(buf, 0) = 0x8a; WBUFL(buf, 2) = bl->id; WBUFB(buf,26) = 3; - clif_send(buf, packet_len(0x8a), bl, AREA); + clif->send(buf, packet_len(0x8a), bl, AREA); if(disguised(bl)) { WBUFL(buf, 2) = - bl->id; - clif_send(buf, packet_len(0x8a), bl, SELF); + clif->send(buf, packet_len(0x8a), bl, SELF); } } @@ -4358,15 +4615,14 @@ void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_targe dummy_bl.x = x; dummy_bl.y = y; dummy_bl.m = m; - clif_send(buf,packet_len(0x192),&dummy_bl,target); + clif->send(buf,packet_len(0x192),&dummy_bl,target); } } /// Notifies the client about an item on floor (ZC_ITEM_ENTRY). /// 009d <id>.L <name id>.W <identified>.B <x>.W <y>.W <amount>.W <subX>.B <subY>.B -void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fitem) -{ +void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fitem) { int view,fd; fd=sd->fd; @@ -4390,8 +4646,7 @@ void clif_getareachar_item(struct map_session_data* sd,struct flooritem_data* fi /// Notifies the client of a skill unit. /// 011f <id>.L <creator id>.L <x>.W <y>.W <unit id>.B <visible>.B (ZC_SKILL_ENTRY) /// 01c9 <id>.L <creator id>.L <x>.W <y>.W <unit id>.B <visible>.B <has msg>.B <msg>.80B (ZC_SKILL_ENTRY2) -static void clif_getareachar_skillunit(struct map_session_data *sd, struct skill_unit *unit) -{ +void clif_getareachar_skillunit(struct map_session_data *sd, struct skill_unit *unit) { int fd = sd->fd; if( unit->group->state.guildaura ) @@ -4419,9 +4674,9 @@ static void clif_getareachar_skillunit(struct map_session_data *sd, struct skill WFIFOL(fd, 6)=unit->group->src_id; WFIFOW(fd,10)=unit->bl.x; WFIFOW(fd,12)=unit->bl.y; - if (battle_config.traps_setting&1 && skill_get_inf2(unit->group->skill_id)&INF2_TRAP) + if (battle_config.traps_setting&1 && skill->get_inf2(unit->group->skill_id)&INF2_TRAP) WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. - else if (skill_get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) + else if (skill->get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) WFIFOB(fd,14)=UNT_DUMMYSKILL; //Use invisible unit id for traps. else WFIFOB(fd,14)=unit->group->unit_id; @@ -4429,15 +4684,14 @@ static void clif_getareachar_skillunit(struct map_session_data *sd, struct skill WFIFOSET(fd,packet_len(0x11f)); if(unit->group->skill_id == WZ_ICEWALL) - clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,5,SELF); + clif->changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,5,SELF); } /*========================================== * Server tells client to remove unit of id 'unit->bl.id' *------------------------------------------*/ -static void clif_clearchar_skillunit(struct skill_unit *unit, int fd) -{ +void clif_clearchar_skillunit(struct skill_unit *unit, int fd) { nullpo_retv(unit); WFIFOHEAD(fd,packet_len(0x120)); @@ -4446,7 +4700,7 @@ static void clif_clearchar_skillunit(struct skill_unit *unit, int fd) WFIFOSET(fd,packet_len(0x120)); if(unit->group && unit->group->skill_id == WZ_ICEWALL) - clif_changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,SELF); + clif->changemapcell(fd,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,SELF); } @@ -4460,7 +4714,7 @@ void clif_skill_delunit(struct skill_unit *unit) WBUFW(buf, 0)=0x120; WBUFL(buf, 2)=unit->bl.id; - clif_send(buf,packet_len(0x120),&unit->bl,AREA); + clif->send(buf,packet_len(0x120),&unit->bl,AREA); } @@ -4475,15 +4729,14 @@ void clif_skillunit_update(struct block_list* bl) WBUFW(buf,0) = 0x1ac; WBUFL(buf,2) = bl->id; - clif_send(buf,packet_len(0x1ac),bl,AREA); + clif->send(buf,packet_len(0x1ac),bl,AREA); } /*========================================== * *------------------------------------------*/ -static int clif_getareachar(struct block_list* bl,va_list ap) -{ +int clif_getareachar(struct block_list* bl,va_list ap) { struct map_session_data *sd; nullpo_ret(bl); @@ -4494,17 +4747,17 @@ static int clif_getareachar(struct block_list* bl,va_list ap) return 0; switch(bl->type){ - case BL_ITEM: - clif_getareachar_item(sd,(struct flooritem_data*) bl); - break; - case BL_SKILL: - clif_getareachar_skillunit(sd,(TBL_SKILL*)bl); - break; - default: - if(&sd->bl == bl) + case BL_ITEM: + clif->getareachar_item(sd,(struct flooritem_data*) bl); + break; + case BL_SKILL: + clif->getareachar_skillunit(sd,(TBL_SKILL*)bl); + break; + default: + if(&sd->bl == bl) + break; + clif->getareachar_unit(sd,bl); break; - clif_getareachar_unit(sd,bl); - break; } return 0; } @@ -4522,44 +4775,42 @@ int clif_outsight(struct block_list *bl,va_list ap) sd = BL_CAST(BL_PC, bl); tsd = BL_CAST(BL_PC, tbl); - if (tsd && tsd->fd) - { //tsd has lost sight of the bl object. + if (tsd && tsd->fd) { //tsd has lost sight of the bl object. switch(bl->type){ - case BL_PC: - if (sd->vd.class_ != INVISIBLE_CLASS) - clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); - if(sd->chatID){ - struct chat_data *cd; - cd=(struct chat_data*)map_id2bl(sd->chatID); - if(cd->usersd[0]==sd) - clif_dispchat(cd,tsd->fd); + case BL_PC: + if (sd->vd.class_ != INVISIBLE_CLASS) + clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); + if(sd->chatID){ + struct chat_data *cd; + cd=(struct chat_data*)map_id2bl(sd->chatID); + if(cd->usersd[0]==sd) + clif->dispchat(cd,tsd->fd); + } + if( sd->state.vending ) + clif->closevendingboard(bl,tsd->fd); + if( sd->state.buyingstore ) + clif->buyingstore_disappear_entry_single(tsd, sd); + break; + case BL_ITEM: + clif->clearflooritem((struct flooritem_data*)bl,tsd->fd); + break; + case BL_SKILL: + clif->clearchar_skillunit((struct skill_unit *)bl,tsd->fd); + break; + case BL_NPC: + if( !(((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE) ) + clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); + break; + default: + if ((vd=status_get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS) + clif->clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); + break; } - if( sd->state.vending ) - clif_closevendingboard(bl,tsd->fd); - if( sd->state.buyingstore ) - clif_buyingstore_disappear_entry_single(tsd, sd); - break; - case BL_ITEM: - clif_clearflooritem((struct flooritem_data*)bl,tsd->fd); - break; - case BL_SKILL: - clif_clearchar_skillunit((struct skill_unit *)bl,tsd->fd); - break; - case BL_NPC: - if( !(((TBL_NPC*)bl)->sc.option&OPTION_INVISIBLE) ) - clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); - break; - default: - if ((vd=status_get_viewdata(bl)) && vd->class_ != INVISIBLE_CLASS) - clif_clearunit_single(bl->id,CLR_OUTSIGHT,tsd->fd); - break; - } } - if (sd && sd->fd) - { //sd is watching tbl go out of view. + if (sd && sd->fd) { //sd is watching tbl go out of view. if (((vd=status_get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) && !(tbl->type == BL_NPC && (((TBL_NPC*)tbl)->sc.option&OPTION_INVISIBLE))) - clif_clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd); + clif->clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd); } return 0; } @@ -4578,23 +4829,21 @@ int clif_insight(struct block_list *bl,va_list ap) sd = BL_CAST(BL_PC, bl); tsd = BL_CAST(BL_PC, tbl); - if (tsd && tsd->fd) - { //Tell tsd that bl entered into his view + if (tsd && tsd->fd) { //Tell tsd that bl entered into his view switch(bl->type){ - case BL_ITEM: - clif_getareachar_item(tsd,(struct flooritem_data*)bl); - break; - case BL_SKILL: - clif_getareachar_skillunit(tsd,(TBL_SKILL*)bl); - break; - default: - clif_getareachar_unit(tsd,bl); - break; + case BL_ITEM: + clif->getareachar_item(tsd,(struct flooritem_data*)bl); + break; + case BL_SKILL: + clif->getareachar_skillunit(tsd,(TBL_SKILL*)bl); + break; + default: + clif->getareachar_unit(tsd,bl); + break; } } - if (sd && sd->fd) - { //Tell sd that tbl walked into his view - clif_getareachar_unit(sd,tbl); + if (sd && sd->fd) { //Tell sd that tbl walked into his view + clif->getareachar_unit(sd,tbl); } return 0; } @@ -4614,22 +4863,20 @@ void clif_skillinfoblock(struct map_session_data *sd) WFIFOHEAD(fd, MAX_SKILL * 37 + 4); WFIFOW(fd,0) = 0x10f; - for ( i = 0, len = 4; i < MAX_SKILL; i++) - { - if( (id = sd->status.skill[i].id) != 0 ) - { + for ( i = 0, len = 4; i < MAX_SKILL; i++) { + if( (id = sd->status.skill[i].id) != 0 ) { // workaround for bugreport:5348 if (len + 37 > 8192) break; WFIFOW(fd,len) = id; - WFIFOL(fd,len+2) = skill_get_inf(id); + WFIFOL(fd,len+2) = skill->get_inf(id); WFIFOW(fd,len+6) = sd->status.skill[i].lv; - WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv); - WFIFOW(fd,len+10)= skill_get_range2(&sd->bl, id,sd->status.skill[i].lv); - safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); + WFIFOW(fd,len+8) = skill->get_sp(id,sd->status.skill[i].lv); + WFIFOW(fd,len+10)= skill->get_range2(&sd->bl, id,sd->status.skill[i].lv); + safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) - WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; + WFIFOB(fd,len+36) = (sd->status.skill[i].lv < skill->tree_get_max(id, sd->status.class_))? 1:0; else WFIFOB(fd,len+36) = 0; len += 37; @@ -4639,12 +4886,10 @@ void clif_skillinfoblock(struct map_session_data *sd) WFIFOSET(fd,len); // workaround for bugreport:5348; send the remaining skills one by one to bypass packet size limit - for ( ; i < MAX_SKILL; i++) - { - if( (id = sd->status.skill[i].id) != 0 ) - { - clif_addskill(sd, id); - clif_skillinfo(sd, id, 0); + for ( ; i < MAX_SKILL; i++) { + if( (id = sd->status.skill[i].id) != 0 ) { + clif->addskill(sd, id); + clif->skillinfo(sd, id, 0); } } } @@ -4656,26 +4901,26 @@ void clif_skillinfoblock(struct map_session_data *sd) /// 0111 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <skill name>.24B <upgradable>.B void clif_addskill(struct map_session_data *sd, int id) { - int fd; + int fd, idx = skill->get_index(id); nullpo_retv(sd); fd = sd->fd; if (!fd) return; - if( sd->status.skill[id].id <= 0 ) + if( sd->status.skill[idx].id <= 0 ) return; WFIFOHEAD(fd, packet_len(0x111)); WFIFOW(fd,0) = 0x111; WFIFOW(fd,2) = id; - WFIFOL(fd,4) = skill_get_inf(id); - WFIFOW(fd,8) = sd->status.skill[id].lv; - WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv); - WFIFOW(fd,12)= skill_get_range2(&sd->bl, id,sd->status.skill[id].lv); - safestrncpy((char*)WFIFOP(fd,14), skill_get_name(id), NAME_LENGTH); - if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,38) = (sd->status.skill[id].lv < skill_tree_get_max(id, sd->status.class_))? 1:0; + WFIFOL(fd,4) = skill->get_inf(id); + WFIFOW(fd,8) = sd->status.skill[idx].lv; + WFIFOW(fd,10) = skill->get_sp(id,sd->status.skill[idx].lv); + WFIFOW(fd,12)= skill->get_range2(&sd->bl, id,sd->status.skill[idx].lv); + safestrncpy((char*)WFIFOP(fd,14), skill->get_name(id), NAME_LENGTH); + if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) + WFIFOB(fd,38) = (sd->status.skill[id].lv < skill->tree_get_max(id, sd->status.class_))? 1:0; else WFIFOB(fd,38) = 0; WFIFOSET(fd,packet_len(0x111)); @@ -4698,15 +4943,14 @@ void clif_deleteskill(struct map_session_data *sd, int id) WFIFOW(fd,2) = id; WFIFOSET(fd,packet_len(0x441)); #endif - clif_skillinfoblock(sd); + clif->skillinfoblock(sd); } /// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE). /// 010e <skill id>.W <level>.W <sp cost>.W <attack range>.W <upgradable>.B -void clif_skillup(struct map_session_data *sd,uint16 skill_id) -{ - int fd; +void clif_skillup(struct map_session_data *sd,uint16 skill_id) { + int fd, idx = skill->get_index(skill_id); nullpo_retv(sd); @@ -4714,29 +4958,30 @@ void clif_skillup(struct map_session_data *sd,uint16 skill_id) WFIFOHEAD(fd,packet_len(0x10e)); WFIFOW(fd,0) = 0x10e; WFIFOW(fd,2) = skill_id; - WFIFOW(fd,4) = sd->status.skill[skill_id].lv; - WFIFOW(fd,6) = skill_get_sp(skill_id,sd->status.skill[skill_id].lv); - WFIFOW(fd,8) = skill_get_range2(&sd->bl,skill_id,sd->status.skill[skill_id].lv); - WFIFOB(fd,10) = (sd->status.skill[skill_id].lv < skill_tree_get_max(sd->status.skill[skill_id].id, sd->status.class_)) ? 1 : 0; + WFIFOW(fd,4) = sd->status.skill[idx].lv; + WFIFOW(fd,6) = skill->get_sp(skill_id,sd->status.skill[idx].lv); + WFIFOW(fd,8) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv); + WFIFOB(fd,10) = (sd->status.skill[idx].lv < skill->tree_get_max(sd->status.skill[idx].id, sd->status.class_)) ? 1 : 0; WFIFOSET(fd,packet_len(0x10e)); } /// Updates a skill in the skill tree (ZC_SKILLINFO_UPDATE2). /// 07e1 <skill id>.W <type>.L <level>.W <sp cost>.W <attack range>.W <upgradable>.B -void clif_skillinfo(struct map_session_data *sd,int skill, int inf) +void clif_skillinfo(struct map_session_data *sd,int skill_id, int inf) { const int fd = sd->fd; + int idx = skill->get_index(skill_id); WFIFOHEAD(fd,packet_len(0x7e1)); WFIFOW(fd,0) = 0x7e1; - WFIFOW(fd,2) = skill; - WFIFOL(fd,4) = inf?inf:skill_get_inf(skill); - WFIFOW(fd,8) = sd->status.skill[skill].lv; - WFIFOW(fd,10) = skill_get_sp(skill,sd->status.skill[skill].lv); - WFIFOW(fd,12) = skill_get_range2(&sd->bl,skill,sd->status.skill[skill].lv); - if( sd->status.skill[skill].flag == SKILL_FLAG_PERMANENT ) - WFIFOB(fd,14) = (sd->status.skill[skill].lv < skill_tree_get_max(skill, sd->status.class_))? 1:0; + WFIFOW(fd,2) = skill_id; + WFIFOL(fd,4) = inf?inf:skill->get_inf(skill_id); + WFIFOW(fd,8) = sd->status.skill[idx].lv; + WFIFOW(fd,10) = skill->get_sp(skill_id,sd->status.skill[idx].lv); + WFIFOW(fd,12) = skill->get_range2(&sd->bl,skill_id,sd->status.skill[idx].lv); + if( sd->status.skill[idx].flag == SKILL_FLAG_PERMANENT ) + WFIFOB(fd,14) = (sd->status.skill[idx].lv < skill->tree_get_max(skill_id, sd->status.class_))? 1:0; else WFIFOB(fd,14) = 0; WFIFOSET(fd,packet_len(0x7e1)); @@ -4780,11 +5025,11 @@ void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, #endif if (disguised(bl)) { - clif_send(buf,packet_len(cmd), bl, AREA_WOS); + clif->send(buf,packet_len(cmd), bl, AREA_WOS); WBUFL(buf,2) = -src_id; - clif_send(buf,packet_len(cmd), bl, SELF); + clif->send(buf,packet_len(cmd), bl, SELF); } else - clif_send(buf,packet_len(cmd), bl, AREA); + clif->send(buf,packet_len(cmd), bl, AREA); } @@ -4798,7 +5043,7 @@ void clif_skillcastcancel(struct block_list* bl) WBUFW(buf,0) = 0x1b9; WBUFL(buf,2) = bl->id; - clif_send(buf,packet_len(0x1b9), bl, AREA); + clif->send(buf,packet_len(0x1b9), bl, AREA); } @@ -4913,11 +5158,11 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFW(buf,28)=div; WBUFB(buf,30)=type; if (disguised(dst)) { - clif_send(buf,packet_len(0x114),dst,AREA_WOS); + clif->send(buf,packet_len(0x114),dst,AREA_WOS); WBUFL(buf,8)=-dst->id; - clif_send(buf,packet_len(0x114),dst,SELF); + clif->send(buf,packet_len(0x114),dst,SELF); } else - clif_send(buf,packet_len(0x114),dst,AREA); + clif->send(buf,packet_len(0x114),dst,AREA); if(disguised(src)) { WBUFL(buf,4)=-src->id; @@ -4925,7 +5170,7 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFL(buf,8)=dst->id; if(damage > 0) WBUFW(buf,24)=-1; - clif_send(buf,packet_len(0x114),src,SELF); + clif->send(buf,packet_len(0x114),src,SELF); } #else WBUFW(buf,0)=0x1de; @@ -4944,11 +5189,11 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFW(buf,30)=div; WBUFB(buf,32)=type; if (disguised(dst)) { - clif_send(buf,packet_len(0x1de),dst,AREA_WOS); + clif->send(buf,packet_len(0x1de),dst,AREA_WOS); WBUFL(buf,8)=-dst->id; - clif_send(buf,packet_len(0x1de),dst,SELF); + clif->send(buf,packet_len(0x1de),dst,SELF); } else - clif_send(buf,packet_len(0x1de),dst,AREA); + clif->send(buf,packet_len(0x1de),dst,AREA); if(disguised(src)) { WBUFL(buf,4)=-src->id; @@ -4956,12 +5201,12 @@ int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int WBUFL(buf,8)=dst->id; if(damage > 0) WBUFL(buf,24)=-1; - clif_send(buf,packet_len(0x1de),src,SELF); + clif->send(buf,packet_len(0x1de),src,SELF); } #endif //Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex] - return clif_calc_walkdelay(dst,ddelay,type,damage,div); + return clif->calc_walkdelay(dst,ddelay,type,damage,div); } @@ -5002,12 +5247,12 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in WBUFW(buf,30)=skill_lv; WBUFW(buf,32)=div; WBUFB(buf,34)=type; - clif_send(buf,packet_len(0x115),src,AREA); + clif->send(buf,packet_len(0x115),src,AREA); if(disguised(src)) { WBUFL(buf,4)=-src->id; if(damage > 0) WBUFW(buf,28)=-1; - clif_send(buf,packet_len(0x115),src,SELF); + clif->send(buf,packet_len(0x115),src,SELF); } if (disguised(dst)) { WBUFL(buf,8)=-dst->id; @@ -5015,7 +5260,7 @@ int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned in WBUFL(buf,4)=src->id; else if(damage > 0) WBUFW(buf,28)=-1; - clif_send(buf,packet_len(0x115),dst,SELF); + clif->send(buf,packet_len(0x115),dst,SELF); } //Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex] @@ -5040,17 +5285,17 @@ int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 ski WBUFB(buf,14)=fail; if (disguised(dst)) { - clif_send(buf,packet_len(0x11a),dst,AREA_WOS); + clif->send(buf,packet_len(0x11a),dst,AREA_WOS); WBUFL(buf,6)=-dst->id; - clif_send(buf,packet_len(0x11a),dst,SELF); + clif->send(buf,packet_len(0x11a),dst,SELF); } else - clif_send(buf,packet_len(0x11a),dst,AREA); + clif->send(buf,packet_len(0x11a),dst,AREA); if(src && disguised(src)) { WBUFL(buf,10)=-src->id; if (disguised(dst)) WBUFL(buf,6)=dst->id; - clif_send(buf,packet_len(0x11a),src,SELF); + clif->send(buf,packet_len(0x11a),src,SELF); } return fail; @@ -5073,11 +5318,11 @@ void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,i WBUFW(buf,12)=y; WBUFL(buf,14)=tick; if(disguised(src)) { - clif_send(buf,packet_len(0x117),src,AREA_WOS); + clif->send(buf,packet_len(0x117),src,AREA_WOS); WBUFL(buf,4)=-src->id; - clif_send(buf,packet_len(0x117),src,SELF); + clif->send(buf,packet_len(0x117),src,SELF); } else - clif_send(buf,packet_len(0x117),src,AREA); + clif->send(buf,packet_len(0x117),src,AREA); } @@ -5105,7 +5350,7 @@ void clif_skill_setunit(struct skill_unit *unit) WBUFB(buf,15)=1; WBUFB(buf,16)=1; safestrncpy((char*)WBUFP(buf,17),unit->group->valstr,MESSAGE_SIZE); - clif_send(buf,packet_len(0x1c9),&unit->bl,AREA); + clif->send(buf,packet_len(0x1c9),&unit->bl,AREA); return; } #endif @@ -5116,12 +5361,12 @@ void clif_skill_setunit(struct skill_unit *unit) WBUFW(buf,12)=unit->bl.y; if (unit->group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) WBUFB(buf,14)=unit->val2&UF_SONG?UNT_DISSONANCE:UNT_UGLYDANCE; - else if (skill_get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) + else if (skill->get_unit_flag(unit->group->skill_id) & UF_RANGEDSINGLEUNIT && !(unit->val2 & UF_RANGEDSINGLEUNIT)) WBUFB(buf, 14) = UNT_DUMMYSKILL; // Only display the unit at center. else WBUFB(buf,14)=unit->group->unit_id; WBUFB(buf,15)=1; // ignored by client (always gets set to 1) - clif_send(buf,packet_len(0x11f),&unit->bl,AREA); + clif->send(buf,packet_len(0x11f),&unit->bl,AREA); } @@ -5227,11 +5472,11 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) +(battle_config.estimation_type&2?status->mdef2:0); WBUFW(buf,18)= status->def_ele; for(i=0;i<9;i++) - WBUFB(buf,20+i)= (unsigned char)battle_attr_ratio(i+1,status->def_ele, status->ele_lv); + WBUFB(buf,20+i)= (unsigned char)battle->attr_ratio(i+1,status->def_ele, status->ele_lv); // The following caps negative attributes to 0 since the client displays them as 255-fix. [Skotlex] // WBUFB(buf,20+i)= (unsigned char)((fix=battle_attr_ratio(i+1,status->def_ele, status->ele_lv))<0?0:fix); - clif_send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF); + clif->send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF); } @@ -5254,7 +5499,7 @@ void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id , int WFIFOW(fd, 0)=0x18d; for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){ - if( skill_can_produce_mix(sd,skill_produce_db[i].nameid, trigger, 1) && + if( skill->can_produce_mix(sd,skill_produce_db[i].nameid, trigger, 1) && ( ( skill_id > 0 && skill_produce_db[i].req_skill == skill_id ) || skill_id < 0 ) ){ if((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0) @@ -5301,7 +5546,7 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id c = 0; for( i = 0; i < MAX_SKILL_PRODUCE_DB; i++ ) { - if( !skill_can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty) ) + if( !skill->can_produce_mix(sd,skill_produce_db[i].nameid,trigger, qty) ) continue; if( (view = itemdb_viewid(skill_produce_db[i].nameid)) > 0 ) @@ -5330,7 +5575,7 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id if( skill_id != AM_PHARMACY ) { // AM_PHARMACY is used to Cooking. // It fails. #if PACKETVER >= 20090922 - clif_msg_skill(sd,skill_id,0x625); + clif->msg_skill(sd,skill_id,0x625); #else WFIFOW(fd,2) = 6 + 2 * c; WFIFOSET(fd,WFIFOW(fd,2)); @@ -5339,13 +5584,36 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id } } +void clif_status_change_notick(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) { + struct packet_sc_notick p; + struct map_session_data *sd; + + nullpo_retv(bl); + + if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client + return; + + if (type == SI_BLANK) //It shows nothing on the client... + return; + + sd = BL_CAST(BL_PC, bl); + + p.PacketType = sc_notickType; + p.index = type; + p.AID = bl->id; + p.state = (unsigned char)flag; + + clif->send(&p,packet_len(p.PacketType), bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); +} /// Notifies clients of a status change. /// 0196 <index>.W <id>.L <state>.B (ZC_MSG_STATE_CHANGE) [used for ending status changes and starting them on non-pc units (when needed)] /// 043f <index>.W <id>.L <state>.B <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE2) [used exclusively for starting statuses on pcs] -void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) -{ - unsigned char buf[32]; +/// 08ff <id>.L <index>.W <remain msec>.L { <val>.L }*3 (PACKETVER >= 20111108) +/// 0983 <index>.W <id>.L <state>.B <total msec>.L <remain msec>.L { <val>.L }*3 (PACKETVER >= 20120618) +/// 0984 <id>.L <index>.W <total msec>.L <remain msec>.L { <val>.L }*3 (PACKETVER >= 20120618) +void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3) { + struct packet_status_change p; struct map_session_data *sd; if (type == SI_BLANK) //It shows nothing on the client... @@ -5353,63 +5621,77 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val nullpo_retv(bl); - sd = BL_CAST(BL_PC, bl); - if (!(status_type2relevant_bl_types(type)&bl->type)) // only send status changes that actually matter to the client return; -#if PACKETVER >= 20090121 - if(flag && battle_config.display_status_timers && sd) - WBUFW(buf,0)=0x43f; - else + sd = BL_CAST(BL_PC, bl); + + p.PacketType = status_changeType; + p.index = type; + p.AID = bl->id; + p.state = (unsigned char)flag; +#if PACKETVER >= 20120618 + p.Total = tick; /* at this stage remain and total are the same value I believe */ #endif - WBUFW(buf,0)=0x196; - WBUFW(buf,2)=type; - WBUFL(buf,4)=bl->id; - WBUFB(buf,8)=flag; #if PACKETVER >= 20090121 - if(flag && battle_config.display_status_timers && sd) - { - if (tick <= 0) - tick = 9999; // this is indeed what official servers do - - WBUFL(buf,9) = tick; - WBUFL(buf,13) = val1; - WBUFL(buf,17) = val2; - WBUFL(buf,21) = val3; - } + p.Left = tick; + p.val1 = val1; + p.val2 = val2; + p.val3 = val3; #endif - clif_send(buf,packet_len(WBUFW(buf,0)),bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); + clif->send(&p,sizeof(p), bl, (sd && sd->status.option&OPTION_INVISIBLE) ? SELF : AREA); } /// Send message (modified by [Yor]) (ZC_NOTIFY_PLAYERCHAT). /// 008e <packet len>.W <message>.?B -void clif_displaymessage(const int fd, const char* mes) -{ +void clif_displaymessage(const int fd, const char* mes) { nullpo_retv(mes); + if( fd == -2 ) { + ShowInfo("HCP: %s\n",mes); + } else if ( fd > 0 ) { + int len; + + if ( ( len = strnlen(mes, 255) ) > 0 ) { // don't send a void message (it's not displaying on the client chat). @help can send void line. + WFIFOHEAD(fd, 5 + len); + WFIFOW(fd,0) = 0x8e; + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + safestrncpy((char *)WFIFOP(fd,4), mes, len + 1); + WFIFOSET(fd, 5 + len); + } + } +} +void clif_displaymessage2(const int fd, const char* mes) { + // invalid pointer? + nullpo_retv(mes); + //Scrapped, as these are shared by disconnected players =X [Skotlex] if (fd == 0) ; else { + // Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client) char *message, *line; - + message = aStrdup(mes); line = strtok(message, "\n"); while(line != NULL) { // Limit message to 255+1 characters (otherwise it causes a buffer overflow in the client) int len = strnlen(line, 255); - + if (len > 0) { // don't send a void message (it's not displaying on the client chat). @help can send void line. - WFIFOHEAD(fd, 5 + len); - WFIFOW(fd,0) = 0x8e; - WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate - safestrncpy((char *)WFIFOP(fd,4), line, len + 1); - WFIFOSET(fd, 5 + len); + if( fd == -2 ) { + ShowInfo("HCP: %s\n",line); + } else { + WFIFOHEAD(fd, 5 + len); + WFIFOW(fd,0) = 0x8e; + WFIFOW(fd,2) = 5 + len; // 4 + len + NULL teminate + safestrncpy((char *)WFIFOP(fd,4), line, len + 1); + WFIFOSET(fd, 5 + len); + } } line = strtok(NULL, "\n"); } - aFree(message); + aFree(message); } } @@ -5427,7 +5709,7 @@ void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, e else if (type == 0x20) // bc_woe WBUFL(buf,4) = 0x73737373; //If there's "ssss", game client will recognize message as 'WoE broadcast'. memcpy(WBUFP(buf, 4 + lp), mes, len); - clif_send(buf, WBUFW(buf,2), bl, target); + clif->send(buf, WBUFW(buf,2), bl, target); if (buf) aFree(buf); @@ -5456,30 +5738,8 @@ void clif_GlobalMessage(struct block_list* bl, const char* message) { WBUFW(buf,2)=len+8; WBUFL(buf,4)=bl->id; safestrncpy((char *) WBUFP(buf,8),message,len); - clif_send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); - -} - -/*========================================== - * Send main chat message [LuzZza] - *------------------------------------------*/ -void clif_MainChatMessage(const char* message) { - uint8 buf[200]; - int len; + clif->send((unsigned char *) buf,WBUFW(buf,2),bl,ALL_CLIENT); - if(!message) - return; - - len = strlen(message)+1; - if (len+8 > sizeof(buf)) { - ShowDebug("clif_MainChatMessage: Received message too long (len %d): %s\n", len, message); - len = sizeof(buf)-8; - } - WBUFW(buf,0)=0x8d; - WBUFW(buf,2)=len+8; - WBUFL(buf,4)=0; - safestrncpy((char *) WBUFP(buf,8),message,len); - clif_send(buf,WBUFW(buf,2),NULL,CHAT_MAINCHAT); } /// Send broadcast message with font formatting (ZC_BROADCAST2). @@ -5496,7 +5756,7 @@ void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned l WBUFW(buf,12) = fontAlign; WBUFW(buf,14) = fontY; memcpy(WBUFP(buf,16), mes, len); - clif_send(buf, WBUFW(buf,2), bl, target); + clif->send(buf, WBUFW(buf,2), bl, target); if (buf) aFree(buf); @@ -5528,14 +5788,19 @@ void clif_resurrection(struct block_list *bl,int type) unsigned char buf[16]; nullpo_retv(bl); - + WBUFW(buf,0)=0x148; WBUFL(buf,2)=bl->id; WBUFW(buf,6)=0; - clif_send(buf,packet_len(0x148),bl,type==1 ? AREA : AREA_WOS); - if (disguised(bl)) - clif_spawn(bl); + clif->send(buf,packet_len(0x148),bl, type == 1 ? AREA : AREA_WOS); + if (disguised(bl)) { + if( ((TBL_PC*)bl)->fontcolor ) { + WBUFL(buf,2)=-bl->id; + clif->send(buf,packet_len(0x148),bl, SELF); + } else + clif->spawn(bl); + } } @@ -5546,7 +5811,7 @@ void clif_map_property(struct map_session_data* sd, enum map_property property) int fd; nullpo_retv(sd); - + fd=sd->fd; WFIFOHEAD(fd,packet_len(0x199)); WFIFOW(fd,0)=0x199; @@ -5557,8 +5822,7 @@ void clif_map_property(struct map_session_data* sd, enum map_property property) /// Set the map type (ZC_NOTIFY_MAPPROPERTY2). /// 01d6 <type>.W -void clif_map_type(struct map_session_data* sd, enum map_type type) -{ +void clif_map_type(struct map_session_data* sd, enum map_type type) { int fd; nullpo_retv(sd); @@ -5592,12 +5856,12 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type) else WBUFL(buf,6) = pvprank; WBUFL(buf,10) = pvpnum; - if(sd->sc.option&OPTION_INVISIBLE || sd->disguise) //Causes crashes when a 'mob' with pvp info dies. - clif_send(buf,packet_len(0x19a),&sd->bl,SELF); + if(sd->sc.option&OPTION_INVISIBLE || sd->disguise != -1) //Causes crashes when a 'mob' with pvp info dies. + clif->send(buf,packet_len(0x19a),&sd->bl,SELF); else if(!type) - clif_send(buf,packet_len(0x19a),&sd->bl,AREA); + clif->send(buf,packet_len(0x19a),&sd->bl,AREA); else - clif_send(buf,packet_len(0x19a),&sd->bl,ALL_SAMEMAP); + clif->send(buf,packet_len(0x19a),&sd->bl,ALL_SAMEMAP); } } @@ -5609,13 +5873,13 @@ void clif_map_property_mapall(int map, enum map_property property) { struct block_list bl; unsigned char buf[16]; - + bl.id = 0; bl.type = BL_NUL; bl.m = map; WBUFW(buf,0)=0x199; WBUFW(buf,2)=property; - clif_send(buf,packet_len(0x199),&bl,ALL_SAMEMAP); + clif->send(buf,packet_len(0x199),&bl,ALL_SAMEMAP); } @@ -5841,7 +6105,7 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data * WFIFOW(fd,c*13+4) = i; WFIFOW(fd,c*13+6) = nameid; WFIFOB(fd,c*13+8) = dstsd->status.inventory[i].refine; - clif_addcards(WFIFOP(fd,c*13+9), &dstsd->status.inventory[i]); + clif->addcards(WFIFOP(fd,c*13+9), &dstsd->status.inventory[i]); c++; } } @@ -5852,7 +6116,7 @@ void clif_item_repair_list(struct map_session_data *sd,struct map_session_data * sd->menuskill_val = dstsd->bl.id; sd->menuskill_val2 = lv; }else - clif_skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); } @@ -5924,7 +6188,7 @@ void clif_item_refine_list(struct map_session_data *sd) WFIFOW(fd,c*13+ 4)=i+2; WFIFOW(fd,c*13+ 6)=sd->status.inventory[i].nameid; WFIFOB(fd,c*13+ 8)=sd->status.inventory[i].refine; - clif_addcards(WFIFOP(fd,c*13+9), &sd->status.inventory[i]); + clif->addcards(WFIFOP(fd,c*13+9), &sd->status.inventory[i]); c++; } } @@ -5949,12 +6213,12 @@ void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv WFIFOHEAD(fd,packet_len(0x147)); WFIFOW(fd, 0)=0x147; WFIFOW(fd, 2)=skill_id; - WFIFOW(fd, 4)=skill_get_inf(skill_id); + WFIFOW(fd, 4)=skill->get_inf(skill_id); WFIFOW(fd, 6)=0; WFIFOW(fd, 8)=skill_lv; - WFIFOW(fd,10)=skill_get_sp(skill_id,skill_lv); - WFIFOW(fd,12)=skill_get_range2(&sd->bl, skill_id,skill_lv); - safestrncpy((char*)WFIFOP(fd,14),skill_get_name(skill_id),NAME_LENGTH); + WFIFOW(fd,10)=skill->get_sp(skill_id,skill_lv); + WFIFOW(fd,12)=skill->get_range2(&sd->bl, skill_id,skill_lv); + safestrncpy((char*)WFIFOP(fd,14),skill->get_name(skill_id),NAME_LENGTH); WFIFOB(fd,38)=0; WFIFOSET(fd,packet_len(0x147)); } @@ -5987,7 +6251,7 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) WBUFB(buf,10)=sd->status.cart[n].identify; WBUFB(buf,11)=sd->status.cart[n].attribute; WBUFB(buf,12)=sd->status.cart[n].refine; - clif_addcards(WBUFP(buf,13), &sd->status.cart[n]); + clif->addcards(WBUFP(buf,13), &sd->status.cart[n]); WFIFOSET(fd,packet_len(0x124)); #else WFIFOHEAD(fd,packet_len(0x1c5)); @@ -6003,7 +6267,7 @@ void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail) WBUFB(buf,11)=sd->status.cart[n].identify; WBUFB(buf,12)=sd->status.cart[n].attribute; WBUFB(buf,13)=sd->status.cart[n].refine; - clif_addcards(WBUFP(buf,14), &sd->status.cart[n]); + clif->addcards(WBUFP(buf,14), &sd->status.cart[n]); WFIFOSET(fd,packet_len(0x1c5)); #endif } @@ -6062,7 +6326,7 @@ void clif_showvendingboard(struct block_list* bl, const char* message, int fd) memcpy(WFIFOP(fd,0),buf,packet_len(0x131)); WFIFOSET(fd,packet_len(0x131)); } else { - clif_send(buf,packet_len(0x131),bl,AREA_WOS); + clif->send(buf,packet_len(0x131),bl,AREA_WOS); } } @@ -6082,7 +6346,7 @@ void clif_closevendingboard(struct block_list* bl, int fd) memcpy(WFIFOP(fd,0),buf,packet_len(0x132)); WFIFOSET(fd,packet_len(0x132)); } else { - clif_send(buf,packet_len(0x132),bl,AREA_WOS); + clif->send(buf,packet_len(0x132),bl,AREA_WOS); } } @@ -6090,7 +6354,7 @@ void clif_closevendingboard(struct block_list* bl, int fd) /// Sends a list of items in a shop. /// R 0133 <packet len>.W <owner id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC) /// R 0800 <packet len>.W <owner id>.L <unique id>.L { <price>.L <amount>.W <index>.W <type>.B <name id>.W <identified>.B <damaged>.B <refine>.B <card1>.W <card2>.W <card3>.W <card4>.W }* (ZC_PC_PURCHASE_ITEMLIST_FROMMC2) -void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* vending) +void clif_vendinglist(struct map_session_data* sd, unsigned int id, struct s_vending* vending) { int i,fd; int count; @@ -6130,7 +6394,7 @@ void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* ven WFIFOB(fd,offset+11+i*22) = vsd->status.cart[index].identify; WFIFOB(fd,offset+12+i*22) = vsd->status.cart[index].attribute; WFIFOB(fd,offset+13+i*22) = vsd->status.cart[index].refine; - clif_addcards(WFIFOP(fd,offset+14+i*22), &vsd->status.cart[index]); + clif->addcards(WFIFOP(fd,offset+14+i*22), &vsd->status.cart[index]); } WFIFOSET(fd,WFIFOW(fd,2)); } @@ -6178,8 +6442,7 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven WFIFOW(fd,0) = 0x136; WFIFOW(fd,2) = 8+count*22; WFIFOL(fd,4) = id; - for( i = 0; i < count; i++ ) - { + for( i = 0; i < count; i++ ) { int index = vending[i].index; struct item_data* data = itemdb_search(sd->status.cart[index].nameid); WFIFOL(fd, 8+i*22) = vending[i].value; @@ -6190,7 +6453,7 @@ void clif_openvending(struct map_session_data* sd, int id, struct s_vending* ven WFIFOB(fd,19+i*22) = sd->status.cart[index].identify; WFIFOB(fd,20+i*22) = sd->status.cart[index].attribute; WFIFOB(fd,21+i*22) = sd->status.cart[index].refine; - clif_addcards(WFIFOP(fd,22+i*22), &sd->status.cart[index]); + clif->addcards(WFIFOP(fd,22+i*22), &sd->status.cart[index]); } WFIFOSET(fd,WFIFOW(fd,2)); } @@ -6268,7 +6531,7 @@ void clif_party_member_info(struct party_data *p, struct map_session_data *sd) mapindex_getmapname_ext(map[sd->bl.m].name, (char*)WBUFP(buf,63)); WBUFB(buf,79) = (p->party.item&1)?1:0; WBUFB(buf,80) = (p->party.item&2)?1:0; - clif_send(buf,packet_len(0x1e9),&sd->bl,PARTY); + clif->send(buf,packet_len(0x1e9),&sd->bl,PARTY); } @@ -6307,9 +6570,9 @@ void clif_party_info(struct party_data* p, struct map_session_data *sd) WBUFW(buf,2) = 28+c*46; if(sd) { // send only to self - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + clif->send(buf, WBUFW(buf,2), &sd->bl, SELF); } else if (party_sd) { // send to whole party - clif_send(buf, WBUFW(buf,2), &party_sd->bl, PARTY); + clif->send(buf, WBUFW(buf,2), &party_sd->bl, PARTY); } } @@ -6327,7 +6590,7 @@ void clif_partyinvitationstate(struct map_session_data* sd) WFIFOHEAD(fd, packet_len(0x2c9)); WFIFOW(fd, 0) = 0x2c9; - WFIFOB(fd, 2) = 0; // not implemented + WFIFOB(fd, 2) = sd->status.allow_party ? 1 : 0; WFIFOSET(fd, packet_len(0x2c9)); } @@ -6381,7 +6644,7 @@ void clif_party_inviteack(struct map_session_data* sd, const char* nick, int res #if PACKETVER < 20070904 if( result == 7 ) { - clif_displaymessage(fd, msg_txt(3)); + clif->message(fd, msg_txt(3)); return; } #endif @@ -6426,7 +6689,8 @@ void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag if(!sd && flag==0){ int i; - for(i=0;i<MAX_PARTY && !p->data[i].sd;i++); + for(i=0;i<MAX_PARTY && !p->data[i].sd;i++) + ; if (i < MAX_PARTY) sd = p->data[i].sd; } @@ -6438,9 +6702,9 @@ void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag WBUFB(buf,7)=(p->party.item&2)?1:0; #endif if(flag==0) - clif_send(buf,packet_len(cmd),&sd->bl,PARTY); + clif->send(buf,packet_len(cmd),&sd->bl,PARTY); else - clif_send(buf,packet_len(cmd),&sd->bl,SELF); + clif->send(buf,packet_len(cmd),&sd->bl,SELF); } @@ -6453,13 +6717,14 @@ void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag) { unsigned char buf[64]; - int i; nullpo_retv(p); if(!sd && (flag&0xf0)==0) { - for(i=0;i<MAX_PARTY && !p->data[i].sd;i++); + int i; + for(i=0;i<MAX_PARTY && !p->data[i].sd;i++) + ; if (i < MAX_PARTY) sd = p->data[i].sd; } @@ -6471,9 +6736,9 @@ void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int memcpy(WBUFP(buf,6),name,NAME_LENGTH); WBUFB(buf,30)=flag&0x0f; if((flag&0xf0)==0) - clif_send(buf,packet_len(0x105),&sd->bl,PARTY); + clif->send(buf,packet_len(0x105),&sd->bl,PARTY); else - clif_send(buf,packet_len(0x105),&sd->bl,SELF); + clif->send(buf,packet_len(0x105),&sd->bl,SELF); } @@ -6501,7 +6766,7 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i WBUFW(buf,2)=len+8; WBUFL(buf,4)=account_id; safestrncpy((char *)WBUFP(buf,8), mes, len); - clif_send(buf,len+8,&sd->bl,PARTY); + clif->send(buf,len+8,&sd->bl,PARTY); } } @@ -6518,7 +6783,7 @@ void clif_party_xy(struct map_session_data *sd) WBUFL(buf,2)=sd->status.account_id; WBUFW(buf,6)=sd->bl.x; WBUFW(buf,8)=sd->bl.y; - clif_send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); + clif->send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); } @@ -6564,7 +6829,7 @@ void clif_party_hp(struct map_session_data *sd) WBUFL(buf,6) = sd->battle_status.hp; WBUFL(buf,10) = sd->battle_status.max_hp; #endif - clif_send(buf,packet_len(cmd),&sd->bl,PARTY_AREA_WOS); + clif->send(buf,packet_len(cmd),&sd->bl,PARTY_AREA_WOS); } @@ -6633,7 +6898,7 @@ void clif_produceeffect(struct map_session_data* sd,int flag,int nameid) nullpo_retv(sd); fd = sd->fd; - clif_solved_charname(fd, sd->status.char_id, sd->status.name); + clif->solved_charname(fd, sd->status.char_id, sd->status.name); WFIFOHEAD(fd,packet_len(0x18f)); WFIFOW(fd, 0)=0x18f; WFIFOW(fd, 2)=flag; @@ -6687,9 +6952,8 @@ void clif_sendegg(struct map_session_data *sd) nullpo_retv(sd); fd=sd->fd; - if (battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m)) - { //Disable pet hatching in GvG grounds during Guild Wars [Skotlex] - clif_displaymessage(fd, msg_txt(666)); + if (battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m)) { //Disable pet hatching in GvG grounds during Guild Wars [Skotlex] + clif->message(fd, msg_txt(666)); return; } WFIFOHEAD(fd, MAX_INVENTORY * 2 + 4); @@ -6731,9 +6995,9 @@ void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int typ WBUFL(buf,3) = pd->bl.id; WBUFL(buf,7) = param; if (sd) - clif_send(buf, packet_len(0x1a4), &sd->bl, SELF); + clif->send(buf, packet_len(0x1a4), &sd->bl, SELF); else - clif_send(buf, packet_len(0x1a4), &pd->bl, AREA); + clif->send(buf, packet_len(0x1a4), &pd->bl, AREA); } @@ -6789,7 +7053,7 @@ void clif_pet_emotion(struct pet_data *pd,int param) } WBUFL(buf,6)=param; - clif_send(buf,packet_len(0x1aa),&pd->bl,AREA); + clif->send(buf,packet_len(0x1aa),&pd->bl,AREA); } @@ -6865,7 +7129,6 @@ void clif_autospell(struct map_session_data *sd,uint16 skill_lv) void clif_devotion(struct block_list *src, struct map_session_data *tsd) { unsigned char buf[56]; - int i; nullpo_retv(src); memset(buf,0,packet_len(0x1cf)); @@ -6878,23 +7141,24 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd) if( md && md->master && md->devotion_flag ) WBUFL(buf,6) = md->master->bl.id; - WBUFW(buf,26) = skill_get_range2(src, ML_DEVOTION, mercenary_checkskill(md, ML_DEVOTION)); + WBUFW(buf,26) = skill->get_range2(src, ML_DEVOTION, mercenary_checkskill(md, ML_DEVOTION)); } else { + int i; struct map_session_data *sd = BL_CAST(BL_PC,src); if( sd == NULL ) return; for( i = 0; i < 5; i++ ) WBUFL(buf,6+4*i) = sd->devotion[i]; - WBUFW(buf,26) = skill_get_range2(src, CR_DEVOTION, pc_checkskill(sd, CR_DEVOTION)); + WBUFW(buf,26) = skill->get_range2(src, CR_DEVOTION, pc_checkskill(sd, CR_DEVOTION)); } if( tsd ) - clif_send(buf, packet_len(0x1cf), &tsd->bl, SELF); + clif->send(buf, packet_len(0x1cf), &tsd->bl, SELF); else - clif_send(buf, packet_len(0x1cf), src, AREA); + clif->send(buf, packet_len(0x1cf), src, AREA); } /*========================================== @@ -6917,7 +7181,7 @@ void clif_spiritball(struct block_list *bl) { case BL_PC: WBUFW(buf, 6) = sd->spiritball; break; case BL_HOM: WBUFW(buf, 6) = hd->homunculus.spiritball; break; } - clif_send(buf, packet_len(0x1d0), bl, AREA); + clif->send(buf, packet_len(0x1d0), bl, AREA); } @@ -6932,7 +7196,7 @@ void clif_combo_delay(struct block_list *bl,int wait) WBUFW(buf,0)=0x1d2; WBUFL(buf,2)=bl->id; WBUFL(buf,6)=wait; - clif_send(buf,packet_len(0x1d2),bl,AREA); + clif->send(buf,packet_len(0x1d2),bl,AREA); } @@ -6952,7 +7216,7 @@ void clif_bladestop(struct block_list *src, int dst_id, int active) WBUFL(buf,6)=dst_id; WBUFL(buf,10)=active; - clif_send(buf,packet_len(0x1d1),src,AREA); + clif->send(buf,packet_len(0x1d1),src,AREA); } @@ -6966,7 +7230,7 @@ void clif_mvp_effect(struct map_session_data *sd) WBUFW(buf,0)=0x10c; WBUFL(buf,2)=sd->bl.id; - clif_send(buf,packet_len(0x10c),&sd->bl,AREA); + clif->send(buf,packet_len(0x10c),&sd->bl,AREA); } @@ -7053,7 +7317,7 @@ void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g) nullpo_retv(g); fd=sd->fd; - ps=guild_getposition(g,sd); + ps=guild->getposition(g,sd); WFIFOHEAD(fd,packet_len(0x16c)); WFIFOW(fd,0)=0x16c; WFIFOL(fd,2)=g->guild_id; @@ -7089,14 +7353,14 @@ void clif_guild_memberlogin_notice(struct guild *g,int idx,int flag) WBUFW(buf,14) = sd->status.sex; WBUFW(buf,16) = sd->status.hair; WBUFW(buf,18) = sd->status.hair_color; - clif_send(buf,packet_len(0x1f2),&sd->bl,GUILD_WOS); + clif->send(buf,packet_len(0x1f2),&sd->bl,GUILD_WOS); } - else if( ( sd = guild_getavailablesd(g) ) != NULL ) + else if( ( sd = guild->getavailablesd(g) ) != NULL ) { WBUFW(buf,14) = 0; WBUFW(buf,16) = 0; WBUFW(buf,18) = 0; - clif_send(buf,packet_len(0x1f2),&sd->bl,GUILD); + clif->send(buf,packet_len(0x1f2),&sd->bl,GUILD); } } @@ -7119,7 +7383,7 @@ void clif_guild_send_onlineinfo(struct map_session_data *sd) p_len = packet_len(0x16d); - if(!(g = guild_search(sd->status.guild_id))) + if(!(g = sd->guild)) return; for(i=0; i<g->max_member; i++) { @@ -7135,7 +7399,7 @@ void clif_guild_send_onlineinfo(struct map_session_data *sd) } } - clif_send(buf, p_len*count, &sd->bl, SELF); + clif->send(buf, p_len*count, &sd->bl, SELF); } @@ -7173,7 +7437,7 @@ void clif_guild_basicinfo(struct map_session_data *sd) { nullpo_retv(sd); fd = sd->fd; - if( (g = guild_search(sd->status.guild_id)) == NULL ) + if( (g = sd->guild) == NULL ) return; WFIFOHEAD(fd,packet_len(0x1b6)); @@ -7192,7 +7456,7 @@ void clif_guild_basicinfo(struct map_session_data *sd) { memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH); memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH); - safestrncpy((char*)WFIFOP(fd,94),msg_txt(300+guild_checkcastles(g)),16); // "'N' castles" + safestrncpy((char*)WFIFOP(fd,94),msg_txt(300+guild->checkcastles(g)),16); // "'N' castles" WFIFOL(fd,110) = 0; // zeny WFIFOSET(fd,packet_len(0x1b6)); @@ -7207,7 +7471,7 @@ void clif_guild_allianceinfo(struct map_session_data *sd) struct guild *g; nullpo_retv(sd); - if( (g = guild_search(sd->status.guild_id)) == NULL ) + if( (g = sd->guild) == NULL ) return; fd = sd->fd; @@ -7243,7 +7507,7 @@ void clif_guild_memberlist(struct map_session_data *sd) if( (fd = sd->fd) == 0 ) return; - if( (g = guild_search(sd->status.guild_id)) == NULL ) + if( (g = sd->guild) == NULL ) return; WFIFOHEAD(fd, g->max_member * 104 + 4); @@ -7273,13 +7537,12 @@ void clif_guild_memberlist(struct map_session_data *sd) /// Guild position name information (ZC_POSITION_ID_NAME_INFO). /// 0166 <packet len>.W { <position id>.L <position name>.24B }* -void clif_guild_positionnamelist(struct map_session_data *sd) -{ +void clif_guild_positionnamelist(struct map_session_data *sd) { int i,fd; struct guild *g; nullpo_retv(sd); - if( (g = guild_search(sd->status.guild_id)) == NULL ) + if( (g = sd->guild) == NULL ) return; fd = sd->fd; @@ -7301,13 +7564,12 @@ void clif_guild_positionnamelist(struct map_session_data *sd) /// &0x10 = allow expel /// ranking: /// TODO -void clif_guild_positioninfolist(struct map_session_data *sd) -{ +void clif_guild_positioninfolist(struct map_session_data *sd) { int i,fd; struct guild *g; nullpo_retv(sd); - if( (g = guild_search(sd->status.guild_id)) == NULL ) + if( (g = sd->guild) == NULL ) return; fd = sd->fd; @@ -7351,8 +7613,8 @@ void clif_guild_positionchanged(struct guild *g,int idx) WBUFL(buf,16)=g->position[idx].exp_mode; memcpy(WBUFP(buf,20),g->position[idx].name,NAME_LENGTH); // }* - if( (sd=guild_getavailablesd(g))!=NULL ) - clif_send(buf,WBUFW(buf,2),&sd->bl,GUILD); + if( (sd=guild->getavailablesd(g))!=NULL ) + clif->send(buf,WBUFW(buf,2),&sd->bl,GUILD); } @@ -7375,8 +7637,8 @@ void clif_guild_memberpositionchanged(struct guild *g,int idx) WBUFL(buf, 8)=g->member[idx].char_id; WBUFL(buf,12)=g->member[idx].position; // }* - if( (sd=guild_getavailablesd(g))!=NULL ) - clif_send(buf,WBUFW(buf,2),&sd->bl,GUILD); + if( (sd=guild->getavailablesd(g))!=NULL ) + clif->send(buf,WBUFW(buf,2),&sd->bl,GUILD); } @@ -7416,7 +7678,7 @@ void clif_guild_emblem_area(struct block_list* bl) WBUFL(buf,2) = bl->id; WBUFL(buf,6) = status_get_guild_id(bl); WBUFW(buf,10) = status_get_emblem_id(bl); - clif_send(buf, 12, bl, AREA_WOS); + clif->send(buf, 12, bl, AREA_WOS); } @@ -7429,26 +7691,24 @@ void clif_guild_skillinfo(struct map_session_data* sd) int i,c; nullpo_retv(sd); - if( (g = guild_search(sd->status.guild_id)) == NULL ) + if( (g = sd->guild) == NULL ) return; fd = sd->fd; WFIFOHEAD(fd, 6 + MAX_GUILDSKILL*37); WFIFOW(fd,0) = 0x0162; WFIFOW(fd,4) = g->skill_point; - for(i = 0, c = 0; i < MAX_GUILDSKILL; i++) - { - if(g->skill[i].id > 0 && guild_check_skill_require(g, g->skill[i].id)) - { + for(i = 0, c = 0; i < MAX_GUILDSKILL; i++) { + if(g->skill[i].id > 0 && guild->check_skill_require(g, g->skill[i].id)) { int id = g->skill[i].id; int p = 6 + c*37; WFIFOW(fd,p+0) = id; - WFIFOL(fd,p+2) = skill_get_inf(id); + WFIFOL(fd,p+2) = skill->get_inf(id); WFIFOW(fd,p+6) = g->skill[i].lv; - WFIFOW(fd,p+8) = skill_get_sp(id, g->skill[i].lv); - WFIFOW(fd,p+10) = skill_get_range(id, g->skill[i].lv); - safestrncpy((char*)WFIFOP(fd,p+12), skill_get_name(id), NAME_LENGTH); - WFIFOB(fd,p+36)= (g->skill[i].lv < guild_skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; + WFIFOW(fd,p+8) = skill->get_sp(id, g->skill[i].lv); + WFIFOW(fd,p+10) = skill->get_range(id, g->skill[i].lv); + safestrncpy((char*)WFIFOP(fd,p+12), skill->get_name(id), NAME_LENGTH); + WFIFOB(fd,p+36)= (g->skill[i].lv < guild->skill_get_max(id) && sd == g->member[0].sd) ? 1 : 0; c++; } } @@ -7532,7 +7792,7 @@ void clif_guild_leave(struct map_session_data *sd,const char *name,const char *m WBUFW(buf, 0)=0x15a; memcpy(WBUFP(buf, 2),name,NAME_LENGTH); memcpy(WBUFP(buf,26),mes,40); - clif_send(buf,packet_len(0x15a),&sd->bl,GUILD_NOBG); + clif->send(buf,packet_len(0x15a),&sd->bl,GUILD_NOBG); } @@ -7556,15 +7816,14 @@ void clif_guild_expulsion(struct map_session_data* sd, const char* name, const c #if PACKETVER < 20100803 memset(WBUFP(buf,66), 0, NAME_LENGTH); // account name (not used for security reasons) #endif - clif_send(buf, packet_len(cmd), &sd->bl, GUILD_NOBG); + clif->send(buf, packet_len(cmd), &sd->bl, GUILD_NOBG); } /// Guild expulsion list (ZC_BAN_LIST). /// 0163 <packet len>.W { <char name>.24B <account name>.24B <reason>.40B }* /// 0163 <packet len>.W { <char name>.24B <reason>.40B }* (PACKETVER >= 20100803) -void clif_guild_expulsionlist(struct map_session_data* sd) -{ +void clif_guild_expulsionlist(struct map_session_data* sd) { #if PACKETVER < 20100803 const int offset = NAME_LENGTH*2+40; #else @@ -7575,7 +7834,7 @@ void clif_guild_expulsionlist(struct map_session_data* sd) nullpo_retv(sd); - if( (g = guild_search(sd->status.guild_id)) == NULL ) + if( (g = sd->guild) == NULL ) return; fd = sd->fd; @@ -7625,8 +7884,8 @@ void clif_guild_message(struct guild *g,int account_id,const char *mes,int len) WBUFW(buf, 2) = len + 5; safestrncpy((char*)WBUFP(buf,4), mes, len+1); - if ((sd = guild_getavailablesd(g)) != NULL) - clif_send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG); + if ((sd = guild->getavailablesd(g)) != NULL) + clif->send(buf, WBUFW(buf,2), &sd->bl, GUILD_NOBG); } @@ -7644,8 +7903,8 @@ int clif_guild_skillup(struct map_session_data *sd,uint16 skill_id,int lv) WFIFOW(fd,0) = 0x10e; WFIFOW(fd,2) = skill_id; WFIFOW(fd,4) = lv; - WFIFOW(fd,6) = skill_get_sp(skill_id,lv); - WFIFOW(fd,8) = skill_get_range(skill_id,lv); + WFIFOW(fd,6) = skill->get_sp(skill_id,lv); + WFIFOW(fd,8) = skill->get_range(skill_id,lv); WFIFOB(fd,10) = 1; WFIFOSET(fd,11); return 0; @@ -7745,7 +8004,7 @@ void clif_guild_allianceadded(struct guild *g,int idx) WBUFL(buf,2)=g->alliance[idx].opposition; WBUFL(buf,6)=g->alliance[idx].guild_id; memcpy(WBUFP(buf,10),g->alliance[idx].name,NAME_LENGTH); - clif_send(buf,packet_len(0x185),guild_getavailablesd(g),GUILD); + clif->send(buf,packet_len(0x185),guild->getavailablesd(g),GUILD); } */ @@ -7782,7 +8041,7 @@ void clif_emotion(struct block_list *bl,int type) WBUFW(buf,0)=0xc0; WBUFL(buf,2)=bl->id; WBUFB(buf,6)=type; - clif_send(buf,packet_len(0xc0),bl,AREA); + clif->send(buf,packet_len(0xc0),bl,AREA); } @@ -7796,7 +8055,7 @@ void clif_talkiebox(struct block_list* bl, const char* talkie) WBUFW(buf,0) = 0x191; WBUFL(buf,2) = bl->id; safestrncpy((char*)WBUFP(buf,6),talkie,MESSAGE_SIZE); - clif_send(buf,packet_len(0x191),bl,AREA); + clif->send(buf,packet_len(0x191),bl,AREA); } @@ -7810,7 +8069,7 @@ void clif_wedding_effect(struct block_list *bl) WBUFW(buf,0) = 0x1ea; WBUFL(buf,2) = bl->id; - clif_send(buf, packet_len(0x1ea), bl, AREA); + clif->send(buf, packet_len(0x1ea), bl, AREA); } @@ -7819,7 +8078,6 @@ void clif_wedding_effect(struct block_list *bl) void clif_callpartner(struct map_session_data *sd) { unsigned char buf[26]; - const char *p; nullpo_retv(sd); @@ -7827,6 +8085,7 @@ void clif_callpartner(struct map_session_data *sd) if( sd->status.partner_id ) { + const char *p; if( ( p = map_charid2nick(sd->status.partner_id) ) != NULL ) { memcpy(WBUFP(buf,2), p, NAME_LENGTH); @@ -7841,7 +8100,7 @@ void clif_callpartner(struct map_session_data *sd) WBUFB(buf,2) = 0; } - clif_send(buf, packet_len(0x1e6), &sd->bl, AREA); + clif->send(buf, packet_len(0x1e6), &sd->bl, AREA); } @@ -7898,9 +8157,8 @@ void clif_marriage_proposal(int fd, struct map_session_data *sd, struct map_sess /*========================================== * *------------------------------------------*/ -void clif_disp_onlyself(struct map_session_data *sd, const char *mes, int len) -{ - clif_disp_message(&sd->bl, mes, len, SELF); +void clif_disp_onlyself(struct map_session_data *sd, const char *mes, int len) { + clif->disp_message(&sd->bl, mes, len, SELF); } /*========================================== @@ -7910,12 +8168,9 @@ void clif_disp_message(struct block_list* src, const char* mes, int len, enum se { unsigned char buf[256]; - if( len == 0 ) - { + if( len == 0 ) { return; - } - else if( len > sizeof(buf)-5 ) - { + } else if( len > sizeof(buf)-5 ) { ShowWarning("clif_disp_message: Truncated message '%s' (len=%d, max=%d, aid=%d).\n", mes, len, sizeof(buf)-5, src->id); len = sizeof(buf)-5; } @@ -7923,7 +8178,7 @@ void clif_disp_message(struct block_list* src, const char* mes, int len, enum se WBUFW(buf, 0) = 0x17f; WBUFW(buf, 2) = len + 5; safestrncpy((char*)WBUFP(buf,4), mes, len+1); - clif_send(buf, WBUFW(buf,2), src, target); + clif->send(buf, WBUFW(buf,2), src, target); } @@ -7952,12 +8207,12 @@ void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd) int fd = tsd->fd; if( fd > 0 ) - clif_authfail_fd(fd, 15); + clif->authfail_fd(fd, 15); else map_quit(tsd); if( sd ) - clif_GM_kickack(sd,tsd->status.account_id); + clif->GM_kickack(sd,tsd->status.account_id); } @@ -8012,8 +8267,7 @@ void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, /// 0 = success /// 1 = failure /// 2 = too many blocks -void clif_wisexin(struct map_session_data *sd,int type,int flag) -{ +void clif_wisexin(struct map_session_data *sd,int type,int flag) { int fd; nullpo_retv(sd); @@ -8034,8 +8288,7 @@ void clif_wisexin(struct map_session_data *sd,int type,int flag) /// result: /// 0 = success /// 1 = failure -void clif_wisall(struct map_session_data *sd,int type,int flag) -{ +void clif_wisall(struct map_session_data *sd,int type,int flag) { int fd; nullpo_retv(sd); @@ -8106,7 +8359,7 @@ void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum WBUFB(buf,26) = type; WBUFL(buf,27) = 0; WBUFL(buf,31) = bl->id; - clif_send(buf, packet_len(0x1d3), bl, coverage); + clif->send(buf, packet_len(0x1d3), bl, coverage); } @@ -8126,16 +8379,15 @@ void clif_specialeffect(struct block_list* bl, int type, enum send_target target WBUFL(buf,2) = bl->id; WBUFL(buf,6) = type; - clif_send(buf, packet_len(0x1f3), bl, target); + clif->send(buf, packet_len(0x1f3), bl, target); if (disguised(bl)) { WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x1f3), bl, SELF); + clif->send(buf, packet_len(0x1f3), bl, SELF); } } -void clif_specialeffect_single(struct block_list* bl, int type, int fd) -{ +void clif_specialeffect_single(struct block_list* bl, int type, int fd) { WFIFOHEAD(fd,10); WFIFOW(fd,0) = 0x1f3; WFIFOL(fd,2) = bl->id; @@ -8159,26 +8411,26 @@ void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, sen WBUFL(buf,6) = effect_id; WBUFL(buf,10) = num; - clif_send(buf, packet_len(0x284), bl, target); + clif->send(buf, packet_len(0x284), bl, target); if( disguised(bl) ) { WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x284), bl, SELF); + clif->send(buf, packet_len(0x284), bl, SELF); } } // Modification of clif_messagecolor to send colored messages to players to chat log only (doesn't display overhead) /// 02c1 <packet len>.W <id>.L <color>.L <message>.?B -int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg) { +int clif_colormes(int fd, enum clif_colors color, const char* msg) { unsigned short msg_len = strlen(msg) + 1; - WFIFOHEAD(sd->fd,msg_len + 12); - WFIFOW(sd->fd,0) = 0x2C1; - WFIFOW(sd->fd,2) = msg_len + 12; - WFIFOL(sd->fd,4) = 0; - WFIFOL(sd->fd,8) = color_table[color]; - safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); - clif_send(WFIFOP(sd->fd,0), WFIFOW(sd->fd,2), &sd->bl, SELF); + WFIFOHEAD(fd,msg_len + 12); + WFIFOW(fd,0) = 0x2C1; + WFIFOW(fd,2) = msg_len + 12; + WFIFOL(fd,4) = 0; + WFIFOL(fd,8) = color_table[color]; + safestrncpy((char*)WFIFOP(fd,12), msg, msg_len); + WFIFOSET(fd, msg_len + 12); return 0; } @@ -8192,8 +8444,7 @@ void clif_messagecolor(struct block_list* bl, unsigned long color, const char* m nullpo_retv(bl); - if( msg_len > sizeof(buf)-12 ) - { + if( msg_len > sizeof(buf)-12 ) { ShowWarning("clif_messagecolor: Truncating too long message '%s' (len=%u).\n", msg, msg_len); msg_len = sizeof(buf)-12; } @@ -8204,7 +8455,7 @@ void clif_messagecolor(struct block_list* bl, unsigned long color, const char* m WBUFL(buf,8) = color; memcpy(WBUFP(buf,12), msg, msg_len); - clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); + clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); } /// Public chat message [Valaris] (ZC_NOTIFY_CHAT). @@ -8224,7 +8475,7 @@ void clif_message(struct block_list* bl, const char* msg) { WBUFL(buf,4) = bl->id; safestrncpy((char*)WBUFP(buf,8), msg, msg_len); - clif_send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); + clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); } // refresh the client's screen, getting rid of any effects @@ -8233,53 +8484,60 @@ void clif_refresh(struct map_session_data *sd) int i; nullpo_retv(sd); - clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); - clif_inventorylist(sd); + clif->changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); + clif->inventorylist(sd); if(pc_iscarton(sd)) { - clif_cartlist(sd); - clif_updatestatus(sd,SP_CARTINFO); - } - clif_updatestatus(sd,SP_WEIGHT); - clif_updatestatus(sd,SP_MAXWEIGHT); - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); + clif->cartlist(sd); + clif->updatestatus(sd,SP_CARTINFO); + } + clif->updatestatus(sd,SP_WEIGHT); + clif->updatestatus(sd,SP_MAXWEIGHT); + clif->updatestatus(sd,SP_STR); + clif->updatestatus(sd,SP_AGI); + clif->updatestatus(sd,SP_VIT); + clif->updatestatus(sd,SP_INT); + clif->updatestatus(sd,SP_DEX); + clif->updatestatus(sd,SP_LUK); if (sd->spiritball) - clif_spiritball_single(sd->fd, sd); + clif->spiritball_single(sd->fd, sd); for(i = 1; i < 5; i++){ if( sd->talisman[i] > 0 ) - clif_talisman_single(sd->fd, sd, i); + clif->talisman_single(sd->fd, sd, i); } if (sd->vd.cloth_color) - clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); - if(merc_is_hom_active(sd->hd)) - clif_send_homdata(sd,SP_ACK,0); + clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); + if(homun_alive(sd->hd)) + clif->send_homdata(sd,SP_ACK,0); if( sd->md ) { - clif_mercenary_info(sd); - clif_mercenary_skillblock(sd); + clif->mercenary_info(sd); + clif->mercenary_skillblock(sd); } if( sd->ed ) - clif_elemental_info(sd); - map_foreachinrange(clif_getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); - clif_weather_check(sd); + clif->elemental_info(sd); + map_foreachinrange(clif->getareachar,&sd->bl,AREA_SIZE,BL_ALL,sd); + clif->weather_check(sd); if( sd->chatID ) chat_leavechat(sd,0); if( sd->state.vending ) - clif_openvending(sd, sd->bl.id, sd->vending); + clif->openvending(sd, sd->bl.id, sd->vending); if( pc_issit(sd) ) - clif_sitting(&sd->bl); // FIXME: just send to self, not area + clif->sitting(&sd->bl); // FIXME: just send to self, not area if( pc_isdead(sd) ) // When you refresh, resend the death packet. - clif_clearunit_single(sd->bl.id,CLR_DEAD,sd->fd); + clif->clearunit_single(sd->bl.id,CLR_DEAD,sd->fd); else - clif_changed_dir(&sd->bl, SELF); + clif->changed_dir(&sd->bl, SELF); // unlike vending, resuming buyingstore crashes the client. - buyingstore_close(sd); + buyingstore->close(sd); mail_clear(sd); + + if( disguised(&sd->bl) ) {/* refresh-da */ + short disguise = sd->disguise; + pc_disguise(sd, -1); + pc_disguise(sd, disguise); + } + } @@ -8296,127 +8554,121 @@ void clif_charnameack (int fd, struct block_list *bl) WBUFW(buf,0) = cmd; WBUFL(buf,2) = bl->id; - switch( bl->type ) - { - case BL_PC: - { - struct map_session_data *ssd = (struct map_session_data *)bl; - struct party_data *p = NULL; - struct guild *g = NULL; - - //Requesting your own "shadow" name. [Skotlex] - if (ssd->fd == fd && ssd->disguise) - WBUFL(buf,2) = -bl->id; - - if( ssd->fakename[0] ) - { - WBUFW(buf, 0) = cmd = 0x195; - memcpy(WBUFP(buf,6), ssd->fakename, NAME_LENGTH); - WBUFB(buf,30) = WBUFB(buf,54) = WBUFB(buf,78) = 0; - break; - } - memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH); - - if( ssd->status.party_id ) - { - p = party_search(ssd->status.party_id); - } - if( ssd->status.guild_id ) + switch( bl->type ) { + case BL_PC: { - if( ( g = guild_search(ssd->status.guild_id) ) != NULL ) - { - ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id); - if( i < g->max_member ) ps = g->member[i].position; + struct map_session_data *ssd = (struct map_session_data *)bl; + struct party_data *p = NULL; + struct guild *g = NULL; + + //Requesting your own "shadow" name. [Skotlex] + if (ssd->fd == fd && ssd->disguise != -1) + WBUFL(buf,2) = -bl->id; + + if( ssd->fakename[0] ) { + WBUFW(buf, 0) = cmd = 0x195; + memcpy(WBUFP(buf,6), ssd->fakename, NAME_LENGTH); + WBUFB(buf,30) = WBUFB(buf,54) = WBUFB(buf,78) = 0; + break; } - } + memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH); - if( !battle_config.display_party_name && g == NULL ) - {// do not display party unless the player is also in a guild - p = NULL; - } - - if (p == NULL && g == NULL) - break; + if( ssd->status.party_id ) { + p = party_search(ssd->status.party_id); + } + if( ssd->status.guild_id ) { + if( ( g = ssd->guild ) != NULL ) { + ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id); + if( i < g->max_member ) ps = g->member[i].position; + } + } - WBUFW(buf, 0) = cmd = 0x195; - if (p) - memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH); - else - WBUFB(buf,30) = 0; + if( !battle_config.display_party_name && g == NULL ) {// do not display party unless the player is also in a guild + p = NULL; + } - if (g && ps >= 0 && ps < MAX_GUILDPOSITION) - { - memcpy(WBUFP(buf,54), g->name,NAME_LENGTH); - memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH); - } else { //Assume no guild. - WBUFB(buf,54) = 0; - WBUFB(buf,78) = 0; - } - } - break; - //[blackhole89] - case BL_HOM: - memcpy(WBUFP(buf,6), ((TBL_HOM*)bl)->homunculus.name, NAME_LENGTH); - break; - case BL_MER: - memcpy(WBUFP(buf,6), ((TBL_MER*)bl)->db->name, NAME_LENGTH); - break; - case BL_PET: - memcpy(WBUFP(buf,6), ((TBL_PET*)bl)->pet.name, NAME_LENGTH); - break; - case BL_NPC: - memcpy(WBUFP(buf,6), ((TBL_NPC*)bl)->name, NAME_LENGTH); - break; - case BL_MOB: - { - struct mob_data *md = (struct mob_data *)bl; - nullpo_retv(md); + if (p == NULL && g == NULL) + break; - memcpy(WBUFP(buf,6), md->name, NAME_LENGTH); - if( md->guardian_data && md->guardian_data->guild_id ) - { - WBUFW(buf, 0) = cmd = 0x195; - WBUFB(buf,30) = 0; - memcpy(WBUFP(buf,54), md->guardian_data->guild_name, NAME_LENGTH); - memcpy(WBUFP(buf,78), md->guardian_data->castle->castle_name, NAME_LENGTH); - } - else if( battle_config.show_mob_info ) - { - char mobhp[50], *str_p = mobhp; WBUFW(buf, 0) = cmd = 0x195; - if( battle_config.show_mob_info&4 ) - str_p += sprintf(str_p, "Lv. %d | ", md->level); - if( battle_config.show_mob_info&1 ) - str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp); - if( battle_config.show_mob_info&2 ) - str_p += sprintf(str_p, "HP: %d%% | ", get_percentage(md->status.hp, md->status.max_hp)); - //Even thought mobhp ain't a name, we send it as one so the client - //can parse it. [Skotlex] - if( str_p != mobhp ) + if (p) + memcpy(WBUFP(buf,30), p->party.name, NAME_LENGTH); + else + WBUFB(buf,30) = 0; + + if (g && ps >= 0 && ps < MAX_GUILDPOSITION) { - *(str_p-3) = '\0'; //Remove trailing space + pipe. - memcpy(WBUFP(buf,30), mobhp, NAME_LENGTH); + memcpy(WBUFP(buf,54), g->name,NAME_LENGTH); + memcpy(WBUFP(buf,78), g->position[ps].name, NAME_LENGTH); + } else { //Assume no guild. WBUFB(buf,54) = 0; WBUFB(buf,78) = 0; } } - } - break; - case BL_CHAT: //FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex] -// memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH); -// break; - return; - case BL_ELEM: - memcpy(WBUFP(buf,6), ((TBL_ELEM*)bl)->db->name, NAME_LENGTH); - break; - default: - ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id); - return; + break; + //[blackhole89] + case BL_HOM: + memcpy(WBUFP(buf,6), ((TBL_HOM*)bl)->homunculus.name, NAME_LENGTH); + break; + case BL_MER: + memcpy(WBUFP(buf,6), ((TBL_MER*)bl)->db->name, NAME_LENGTH); + break; + case BL_PET: + memcpy(WBUFP(buf,6), ((TBL_PET*)bl)->pet.name, NAME_LENGTH); + break; + case BL_NPC: + memcpy(WBUFP(buf,6), ((TBL_NPC*)bl)->name, NAME_LENGTH); + break; + case BL_MOB: + { + struct mob_data *md = (struct mob_data *)bl; + nullpo_retv(md); + + memcpy(WBUFP(buf,6), md->name, NAME_LENGTH); + if( md->guardian_data && md->guardian_data->guild_id ) + { + WBUFW(buf, 0) = cmd = 0x195; + WBUFB(buf,30) = 0; + memcpy(WBUFP(buf,54), md->guardian_data->guild_name, NAME_LENGTH); + memcpy(WBUFP(buf,78), md->guardian_data->castle->castle_name, NAME_LENGTH); + } + else if( battle_config.show_mob_info ) + { + char mobhp[50], *str_p = mobhp; + WBUFW(buf, 0) = cmd = 0x195; + if( battle_config.show_mob_info&4 ) + str_p += sprintf(str_p, "Lv. %d | ", md->level); + if( battle_config.show_mob_info&1 ) + str_p += sprintf(str_p, "HP: %u/%u | ", md->status.hp, md->status.max_hp); + if( battle_config.show_mob_info&2 ) + str_p += sprintf(str_p, "HP: %d%% | ", get_percentage(md->status.hp, md->status.max_hp)); + //Even thought mobhp ain't a name, we send it as one so the client + //can parse it. [Skotlex] + if( str_p != mobhp ) + { + *(str_p-3) = '\0'; //Remove trailing space + pipe. + memcpy(WBUFP(buf,30), mobhp, NAME_LENGTH); + WBUFB(buf,54) = 0; + WBUFB(buf,78) = 0; + } + } + } + break; + case BL_CHAT: //FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex] + // memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH); + // break; + return; + case BL_ELEM: + memcpy(WBUFP(buf,6), ((TBL_ELEM*)bl)->db->name, NAME_LENGTH); + break; + default: + ShowError("clif_charnameack: bad type %d(%d)\n", bl->type, bl->id); + return; } // if no receipient specified just update nearby clients if (fd == 0) - clif_send(buf, packet_len(cmd), bl, AREA); + clif->send(buf, packet_len(cmd), bl, AREA); else { WFIFOHEAD(fd, packet_len(cmd)); memcpy(WFIFOP(fd, 0), buf, packet_len(cmd)); @@ -8430,7 +8682,7 @@ void clif_charnameack (int fd, struct block_list *bl) void clif_charnameupdate (struct map_session_data *ssd) { unsigned char buf[103]; - int cmd = 0x195, ps = -1, i; + int cmd = 0x195, ps = -1; struct party_data *p = NULL; struct guild *g = NULL; @@ -8445,15 +8697,16 @@ void clif_charnameupdate (struct map_session_data *ssd) memcpy(WBUFP(buf,6), ssd->status.name, NAME_LENGTH); if (!battle_config.display_party_name) { - if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL) + if (ssd->status.party_id > 0 && ssd->status.guild_id > 0 && (g = ssd->guild) != NULL) p = party_search(ssd->status.party_id); }else{ if (ssd->status.party_id > 0) p = party_search(ssd->status.party_id); } - if( ssd->status.guild_id > 0 && (g = guild_search(ssd->status.guild_id)) != NULL ) + if( ssd->status.guild_id > 0 && (g = ssd->guild) != NULL ) { + int i; ARR_FIND(0, g->max_member, i, g->member[i].account_id == ssd->status.account_id && g->member[i].char_id == ssd->status.char_id); if( i < g->max_member ) ps = g->member[i].position; } @@ -8475,7 +8728,7 @@ void clif_charnameupdate (struct map_session_data *ssd) } // Update nearby clients - clif_send(buf, packet_len(cmd), &ssd->bl, AREA); + clif->send(buf, packet_len(cmd), &ssd->bl, AREA); } @@ -8494,20 +8747,19 @@ void clif_slide(struct block_list *bl, int x, int y) WBUFL(buf, 2) = bl->id; WBUFW(buf, 6) = x; WBUFW(buf, 8) = y; - clif_send(buf, packet_len(0x1ff), bl, AREA); + clif->send(buf, packet_len(0x1ff), bl, AREA); if( disguised(bl) ) { WBUFL(buf,2) = -bl->id; - clif_send(buf, packet_len(0x1ff), bl, SELF); + clif->send(buf, packet_len(0x1ff), bl, SELF); } } -/*------------------------------------------ - * @me command by lordalfa, rewritten implementation by Skotlex - *------------------------------------------*/ -void clif_disp_overhead(struct map_session_data *sd, const char* mes) +/// Public chat message (ZC_NOTIFY_CHAT). lordalfa/Skotlex - used by @me as well +/// 008d <packet len>.W <id>.L <message>.?B +void clif_disp_overhead(struct block_list *bl, const char* mes) { unsigned char buf[256]; //This should be more than sufficient, the theorical max is CHAT_SIZE + 8 (pads and extra inserted crap) int len_mes = strlen(mes)+1; //Account for \0 @@ -8519,15 +8771,18 @@ void clif_disp_overhead(struct map_session_data *sd, const char* mes) // send message to others WBUFW(buf,0) = 0x8d; WBUFW(buf,2) = len_mes + 8; // len of message + 8 (command+len+id) - WBUFL(buf,4) = sd->bl.id; + WBUFL(buf,4) = bl->id; safestrncpy((char*)WBUFP(buf,8), mes, len_mes); - clif_send(buf, WBUFW(buf,2), &sd->bl, AREA_CHAT_WOC); + clif->send(buf, WBUFW(buf,2), bl, AREA_CHAT_WOC); // send back message to the speaker - WBUFW(buf,0) = 0x8e; - WBUFW(buf, 2) = len_mes + 4; - safestrncpy((char*)WBUFP(buf,4), mes, len_mes); - clif_send(buf, WBUFW(buf,2), &sd->bl, SELF); + if( bl->type == BL_PC ) { + WBUFW(buf,0) = 0x8e; + WBUFW(buf, 2) = len_mes + 4; + safestrncpy((char*)WBUFP(buf,4), mes, len_mes); + clif->send(buf, WBUFW(buf,2), bl, SELF); + } + } /*========================== @@ -8542,7 +8797,7 @@ void clif_party_xy_remove(struct map_session_data *sd) WBUFL(buf,2)=sd->status.account_id; WBUFW(buf,6)=-1; WBUFW(buf,8)=-1; - clif_send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); + clif->send(buf,packet_len(0x107),&sd->bl,PARTY_SAMEMAP_WOS); } @@ -8622,7 +8877,7 @@ void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsig char mapname[MAP_NAME_LENGTH_EXT]; mapindex_getmapname_ext(mapindex_id2name(sd->feel_map[feel_level].index), mapname); - clif_starskill(sd, mapname, 0, feel_level, type ? 1 : 0); + clif->starskill(sd, mapname, 0, feel_level, type ? 1 : 0); } /*========================================== @@ -8631,16 +8886,11 @@ void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsig *------------------------------------------*/ void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type) { - if( pcdb_checkid(class_) ) - { - clif_starskill(sd, job_name(class_), class_, hate_level, type ? 10 : 11); - } - else if( mobdb_checkid(class_) ) - { - clif_starskill(sd, mob_db(class_)->jname, class_, hate_level, type ? 10 : 11); - } - else - { + if( pcdb_checkid(class_) ) { + clif->starskill(sd, job_name(class_), class_, hate_level, type ? 10 : 11); + } else if( mobdb_checkid(class_) ) { + clif->starskill(sd, mob_db(class_)->jname, class_, hate_level, type ? 10 : 11); + } else { ShowWarning("clif_hate_info: Received invalid class %d for this packet (char_id=%d, hate_level=%u, type=%u).\n", class_, sd->status.char_id, (unsigned int)hate_level, (unsigned int)type); } } @@ -8650,7 +8900,7 @@ void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int cl *------------------------------------------*/ void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char progress) { - clif_starskill(sd, mob_db(mob_id)->jname, mob_id, progress, 20); + clif->starskill(sd, mob_db(mob_id)->jname, mob_id, progress, 20); } /*========================================== @@ -8658,7 +8908,7 @@ void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char pr *------------------------------------------*/ void clif_feel_hate_reset(struct map_session_data *sd) { - clif_starskill(sd, "", 0, 0, 30); + clif->starskill(sd, "", 0, 0, 30); } @@ -8752,9 +9002,9 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts // Inventory position WBUFW(buf, n*s+43) = i + 2; // Add refine, identify flag, element, etc. - clif_item_sub(WBUFP(buf,0), n*s+45, &tsd->status.inventory[i], tsd->inventory_data[i], pc_equippoint(tsd, i)); + clif->item_sub(WBUFP(buf,0), n*s+45, &tsd->status.inventory[i], tsd->inventory_data[i], pc_equippoint(tsd, i)); // Add cards - clif_addcards(WBUFP(buf, n*s+55), &tsd->status.inventory[i]); + clif->addcards(WBUFP(buf, n*s+55), &tsd->status.inventory[i]); // Expiration date stuff, if all of those are set to 0 then the client doesn't show anything related (6 bytes) WBUFL(buf, n*s+63) = tsd->status.inventory[i].expire_time; WBUFW(buf, n*s+67) = 0; @@ -8829,8 +9079,7 @@ void clif_viewequip_fail(struct map_session_data* sd) /// Returns true if the packet was parsed successfully. /// Formats: 0 - <packet id>.w <packet len>.w (<name> : <message>).?B 00 /// 1 - <packet id>.w <packet len>.w <name>.24B <message>.?B 00 -static bool clif_process_message(struct map_session_data* sd, int format, char** name_, int* namelen_, char** message_, int* messagelen_) -{ +bool clif_process_message(struct map_session_data* sd, int format, char** name_, int* namelen_, char** message_, int* messagelen_) { char *text, *name, *message; unsigned int packetlen, textlen, namelen, messagelen; int fd = sd->fd; @@ -8920,79 +9169,50 @@ static bool clif_process_message(struct map_session_data* sd, int format, char** return true; } -// --------------------- -// clif_guess_PacketVer -// --------------------- -// Parses a WantToConnection packet to try to identify which is the packet version used. [Skotlex] -// error codes: -// 0 - Success -// 1 - Unknown packet_ver -// 2 - Invalid account_id -// 3 - Invalid char_id -// 4 - Invalid login_id1 (reserved) -// 5 - Invalid client_tick (reserved) -// 6 - Invalid sex -// Only the first 'invalid' error that appears is used. -static int clif_guess_PacketVer(int fd, int get_previous, int *error) -{ - static int err = 1; - static int packet_ver = -1; - int cmd, packet_len, value; //Value is used to temporarily store account/char_id/sex - - if (get_previous) - {//For quick reruns, since the normal code flow is to fetch this once to identify the packet version, then again in the wanttoconnect function. [Skotlex] - if( error ) - *error = err; - return packet_ver; - } - - //By default, start searching on the default one. - err = 1; - packet_ver = clif_config.packet_db_ver; - cmd = RFIFOW(fd,0); - packet_len = RFIFOREST(fd); - -#define SET_ERROR(n) \ - if( err == 1 )\ - err = n;\ -//define SET_ERROR - - // FIXME: If the packet is not received at once, this will FAIL. - // Figure out, when it happens, that only part of the packet is - // received, or fix the function to be able to deal with that - // case. -#define CHECK_PACKET_VER() \ - if( cmd != clif_config.connect_cmd[packet_ver] || packet_len != packet_db[packet_ver][cmd].len )\ - ;/* not wanttoconnection or wrong length */\ - else if( (value=(int)RFIFOL(fd, packet_db[packet_ver][cmd].pos[0])) < START_ACCOUNT_NUM || value > END_ACCOUNT_NUM )\ - { SET_ERROR(2); }/* invalid account_id */\ - else if( (value=(int)RFIFOL(fd, packet_db[packet_ver][cmd].pos[1])) <= 0 )\ - { SET_ERROR(3); }/* invalid char_id */\ - /* RFIFOL(fd, packet_db[packet_ver][cmd].pos[2]) - don't care about login_id1 */\ - /* RFIFOL(fd, packet_db[packet_ver][cmd].pos[3]) - don't care about client_tick */\ - else if( (value=(int)RFIFOB(fd, packet_db[packet_ver][cmd].pos[4])) != 0 && value != 1 )\ - { SET_ERROR(6); }/* invalid sex */\ - else\ - {\ - err = 0;\ - if( error )\ - *error = 0;\ - return packet_ver;\ - }\ -//define CHECK_PACKET_VER - - CHECK_PACKET_VER();//Default packet version found. - - for (packet_ver = MAX_PACKET_VER; packet_ver > 0; packet_ver--) - { //Start guessing the version, giving priority to the newer ones. [Skotlex] - CHECK_PACKET_VER(); - } - if( error ) - *error = err; - packet_ver = -1; - return -1; -#undef SET_ERROR -#undef CHECK_PACKET_VER +void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *sd, char *msg) { + DBIterator *iter = db_iterator(channel->users); + struct map_session_data *user; + unsigned short msg_len = strlen(msg) + 1; + + WFIFOHEAD(sd->fd,msg_len + 12); + WFIFOW(sd->fd,0) = 0x2C1; + WFIFOW(sd->fd,2) = msg_len + 12; + WFIFOL(sd->fd,4) = 0; + WFIFOL(sd->fd,8) = hChSys.colors[channel->color]; + safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len); + + for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) { + if( user->fd == sd->fd ) + continue; + WFIFOHEAD(user->fd,msg_len + 12); + memcpy(WFIFOP(user->fd,0), WFIFOP(sd->fd,0), msg_len + 12); + WFIFOSET(user->fd, msg_len + 12); + } + + WFIFOSET(sd->fd, msg_len + 12); + + dbi_destroy(iter); +} + +void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) { + DBIterator *iter = db_iterator(channel->users); + struct map_session_data *user; + unsigned char buf[210]; + unsigned short msg_len = strlen(msg) + 1; + + WBUFW(buf,0) = 0x2C1; + WBUFW(buf,2) = msg_len + 12; + WBUFL(buf,4) = 0; + WBUFL(buf,8) = hChSys.colors[channel->color]; + safestrncpy((char*)WBUFP(buf,12), msg, msg_len); + + for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) { + WFIFOHEAD(user->fd,msg_len + 12); + memcpy(WFIFOP(user->fd,0), WBUFP(buf,0), msg_len + 12); + WFIFOSET(user->fd, msg_len + 12); + } + + dbi_destroy(iter); } // ------------ @@ -9005,13 +9225,11 @@ static int clif_guess_PacketVer(int fd, int get_previous, int *error) /// 0072 <account id>.L <char id>.L <auth code>.L <client time>.L <gender>.B (CZ_ENTER) /// 0436 <account id>.L <char id>.L <auth code>.L <client time>.L <gender>.B (CZ_ENTER2) /// There are various variants of this packet, some of them have padding between fields. -void clif_parse_WantToConnection(int fd, TBL_PC* sd) -{ +void clif_parse_WantToConnection(int fd, struct map_session_data* sd) { struct block_list* bl; struct auth_node* node; int cmd, account_id, char_id, login_id1, sex; unsigned int client_tick; //The client tick is a tick, therefore it needs be unsigned. [Skotlex] - int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 (by [Yor]) if (sd) { ShowError("clif_parse_WantToConnection : invalid request (character already logged in)\n"); @@ -9019,31 +9237,16 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd) } // Only valid packet version get here - packet_ver = clif_guess_PacketVer(fd, 1, NULL); cmd = RFIFOW(fd,0); - account_id = RFIFOL(fd, packet_db[packet_ver][cmd].pos[0]); - char_id = RFIFOL(fd, packet_db[packet_ver][cmd].pos[1]); - login_id1 = RFIFOL(fd, packet_db[packet_ver][cmd].pos[2]); - client_tick = RFIFOL(fd, packet_db[packet_ver][cmd].pos[3]); - sex = RFIFOB(fd, packet_db[packet_ver][cmd].pos[4]); - - if( packet_ver < 5 || // reject really old client versions - (packet_ver <= 9 && (battle_config.packet_ver_flag & 1) == 0) || // older than 6sept04 - (packet_ver > 9 && (battle_config.packet_ver_flag & 1<<(packet_ver-9)) == 0)) // version not allowed - {// packet version rejected - ShowInfo("Rejected connection attempt, forbidden packet version (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"', Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%s"CL_RESET"').\n", account_id, char_id, packet_ver, ip2str(session[fd]->client_addr, NULL)); - WFIFOHEAD(fd,packet_len(0x6a)); - WFIFOW(fd,0) = 0x6a; - WFIFOB(fd,2) = 5; // Your Game's EXE file is not the latest version - WFIFOSET(fd,packet_len(0x6a)); - set_eof(fd); - return; - } + account_id = RFIFOL(fd, packet_db[cmd].pos[0]); + char_id = RFIFOL(fd, packet_db[cmd].pos[1]); + login_id1 = RFIFOL(fd, packet_db[cmd].pos[2]); + client_tick = RFIFOL(fd, packet_db[cmd].pos[3]); + sex = RFIFOB(fd, packet_db[cmd].pos[4]); - if( runflag != MAPSERVER_ST_RUNNING ) - {// not allowed - clif_authfail_fd(fd,1);// server closed + if( runflag != MAPSERVER_ST_RUNNING ) { // not allowed + clif->authfail_fd(fd,1);// server closed return; } @@ -9063,13 +9266,12 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd) ((node=chrif_search(account_id)) && //An already existing node is valid only if it is for this login. !(node->account_id == account_id && node->char_id == char_id && node->state == ST_LOGIN))) { - clif_authfail_fd(fd, 8); //Still recognizes last connection + clif->authfail_fd(fd, 8); //Still recognizes last connection return; } CREATE(sd, TBL_PC, 1); sd->fd = fd; - sd->packet_ver = packet_ver; session[fd]->session_data = sd; pc_setnewpc(sd, account_id, char_id, login_id1, client_tick, sex, fd); @@ -9087,7 +9289,28 @@ void clif_parse_WantToConnection(int fd, TBL_PC* sd) chrif_authreq(sd); } - +void clif_hercules_chsys_mjoin(struct map_session_data *sd) { + if( !map[sd->bl.m].channel ) { + CREATE(map[sd->bl.m].channel, struct hChSysCh , 1); + safestrncpy(map[sd->bl.m].channel->name, hChSys.local_name, HCHSYS_NAME_LENGTH); + map[sd->bl.m].channel->type = hChSys_MAP; + map[sd->bl.m].channel->m = sd->bl.m; + + clif->chsys_create(map[sd->bl.m].channel,NULL,NULL,hChSys.local_color); + } + + if( map[sd->bl.m].channel->banned && idb_exists(map[sd->bl.m].channel->banned, sd->status.account_id) ) { + return; + } + + clif->chsys_join(map[sd->bl.m].channel,sd); + + if( !( map[sd->bl.m].channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) { + char mout[60]; + sprintf(mout, msg_txt(1435),hChSys.local_name,map[sd->bl.m].name); // You're now in the '#%s' channel for '%s' + clif->colormes(sd->fd, COLOR_DEFAULT, mout); + } +} /// Notification from the client, that it has finished map loading and is about to display player's character (CZ_NOTIFY_ACTORINIT). /// 007d @@ -9096,17 +9319,15 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(sd->bl.prev != NULL) return; - if (!sd->state.active) - { //Character loading is not complete yet! + if (!sd->state.active) { //Character loading is not complete yet! //Let pc_reg_received reinvoke this when ready. sd->state.connect_new = 0; return; } - if (sd->state.rewarp) - { //Rewarp player. + if (sd->state.rewarp) { //Rewarp player. sd->state.rewarp = 0; - clif_changemap(sd, sd->mapindex, sd->bl.x, sd->bl.y); + clif->changemap(sd, sd->mapindex, sd->bl.x, sd->bl.y); return; } @@ -9114,49 +9335,43 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) // look #if PACKETVER < 4 - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); + clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); #else - clif_changelook(&sd->bl,LOOK_WEAPON,0); + clif->changelook(&sd->bl,LOOK_WEAPON,0); #endif if(sd->vd.cloth_color) - clif_refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); - + clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF); // item - clif_inventorylist(sd); // inventory list first, otherwise deleted items in pc_checkitem show up as 'unknown item' + clif->inventorylist(sd); // inventory list first, otherwise deleted items in pc_checkitem show up as 'unknown item' pc_checkitem(sd); // cart if(pc_iscarton(sd)) { - clif_cartlist(sd); - clif_updatestatus(sd,SP_CARTINFO); + clif->cartlist(sd); + clif->updatestatus(sd,SP_CARTINFO); } // weight - clif_updatestatus(sd,SP_WEIGHT); - clif_updatestatus(sd,SP_MAXWEIGHT); + clif->updatestatus(sd,SP_WEIGHT); + clif->updatestatus(sd,SP_MAXWEIGHT); // guild // (needs to go before clif_spawn() to show guild emblems correctly) if(sd->status.guild_id) - guild_send_memberinfoshort(sd,1); + guild->send_memberinfoshort(sd,1); if(battle_config.pc_invincible_time > 0) { - if(map_flag_gvg(sd->bl.m)) - pc_setinvincibletimer(sd,battle_config.pc_invincible_time<<1); - else - pc_setinvincibletimer(sd,battle_config.pc_invincible_time); + pc_setinvincibletimer(sd,battle_config.pc_invincible_time); } if( map[sd->bl.m].users++ == 0 && battle_config.dynamic_mobs ) map_spawnmobs(sd->bl.m); - if( !(sd->sc.option&OPTION_INVISIBLE) ) - {// increment the number of pvp players on the map + if( !(sd->sc.option&OPTION_INVISIBLE) ) { // increment the number of pvp players on the map map[sd->bl.m].users_pvp++; } - if( map[sd->bl.m].instance_id ) - { + if( map[sd->bl.m].instance_id ) { instance[map[sd->bl.m].instance_id].users++; instance_check_idle(map[sd->bl.m].instance_id); } @@ -9166,16 +9381,16 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) sd->state.callshop = 0; map_addblock(&sd->bl); - clif_spawn(&sd->bl); + clif->spawn(&sd->bl); // Party // (needs to go after clif_spawn() to show hp bars correctly) if(sd->status.party_id) { party_send_movemap(sd); - clif_party_hp(sd); // Show hp after displacement [LuzZza] + clif->party_hp(sd); // Show hp after displacement [LuzZza] } - if( sd->bg_id ) clif_bg_hp(sd); // BattleGround System + if( sd->bg_id ) clif->bg_hp(sd); // BattleGround System if(map[sd->bl.m].flag.pvp && !(sd->sc.option&OPTION_INVISIBLE)) { if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris] @@ -9187,92 +9402,85 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) sd->pvp_won = 0; sd->pvp_lost = 0; } - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); } else // set flag, if it's a duel [LuzZza] if(sd->duel_group) - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); if (map[sd->bl.m].flag.gvg_dungeon) - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here. + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); //TODO: Figure out the real packet to send here. if( map_flag_gvg(sd->bl.m) ) - clif_map_property(sd, MAPPROPERTY_AGITZONE); - + clif->map_property(sd, MAPPROPERTY_AGITZONE); // info about nearby objects // must use foreachinarea (CIRCULAR_AREA interferes with foreachinrange) - map_foreachinarea(clif_getareachar, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_ALL, sd); + map_foreachinarea(clif->getareachar, sd->bl.m, sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE, sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_ALL, sd); // pet - if( sd->pd ) - { - if( battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m) ) - { //Return the pet to egg. [Skotlex] - clif_displaymessage(sd->fd, msg_txt(666)); + if( sd->pd ) { + if( battle_config.pet_no_gvg && map_flag_gvg(sd->bl.m) ) { //Return the pet to egg. [Skotlex] + clif->message(sd->fd, msg_txt(666)); pet_menu(sd, 3); //Option 3 is return to egg. - } - else - { + } else { map_addblock(&sd->pd->bl); - clif_spawn(&sd->pd->bl); - clif_send_petdata(sd,sd->pd,0,0); - clif_send_petstatus(sd); -// skill_unit_move(&sd->pd->bl,gettick(),1); + clif->spawn(&sd->pd->bl); + clif->send_petdata(sd,sd->pd,0,0); + clif->send_petstatus(sd); +// skill->unit_move(&sd->pd->bl,gettick(),1); } } //homunculus [blackhole89] - if( merc_is_hom_active(sd->hd) ) - { + if( homun_alive(sd->hd) ) { map_addblock(&sd->hd->bl); - clif_spawn(&sd->hd->bl); - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,sd->hd,1); - clif_hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice - clif_homskillinfoblock(sd); + clif->spawn(&sd->hd->bl); + clif->send_homdata(sd,SP_ACK,0); + clif->hominfo(sd,sd->hd,1); + clif->hominfo(sd,sd->hd,0); //for some reason, at least older clients want this sent twice + clif->homskillinfoblock(sd); if( battle_config.hom_setting&0x8 ) status_calc_bl(&sd->hd->bl, SCB_SPEED); //Homunc mimic their master's speed on each map change if( !(battle_config.hom_setting&0x2) ) - skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately + skill->unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately } if( sd->md ) { map_addblock(&sd->md->bl); - clif_spawn(&sd->md->bl); - clif_mercenary_info(sd); - clif_mercenary_skillblock(sd); + clif->spawn(&sd->md->bl); + clif->mercenary_info(sd); + clif->mercenary_skillblock(sd); status_calc_bl(&sd->md->bl, SCB_SPEED); // Mercenary mimic their master's speed on each map change } if( sd->ed ) { map_addblock(&sd->ed->bl); - clif_spawn(&sd->ed->bl); - clif_elemental_info(sd); - clif_elemental_updatestatus(sd,SP_HP); - clif_hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.max_hp); - clif_elemental_updatestatus(sd,SP_SP); + clif->spawn(&sd->ed->bl); + clif->elemental_info(sd); + clif->elemental_updatestatus(sd,SP_HP); + clif->hpmeter_single(sd->fd,sd->ed->bl.id,sd->ed->battle_status.hp,sd->ed->battle_status.max_hp); + clif->elemental_updatestatus(sd,SP_SP); status_calc_bl(&sd->ed->bl, SCB_SPEED); //Elemental mimic their master's speed on each map change } if(sd->state.connect_new) { int lv; sd->state.connect_new = 0; - clif_skillinfoblock(sd); - clif_hotkeys_send(sd); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_NEXTBASEEXP); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); - clif_updatestatus(sd,SP_SKILLPOINT); - clif_initialstatus(sd); + clif->skillinfoblock(sd); + clif->hotkeys(sd); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_NEXTBASEEXP); + clif->updatestatus(sd,SP_JOBEXP); + clif->updatestatus(sd,SP_NEXTJOBEXP); + clif->updatestatus(sd,SP_SKILLPOINT); + clif->initialstatus(sd); if (sd->sc.option&OPTION_FALCON) - clif_status_load(&sd->bl, SI_FALCON, 1); - + clif->status_change(&sd->bl, SI_FALCON, 1, 0, 0, 0, 0); if (sd->sc.option&OPTION_RIDING) - clif_status_load(&sd->bl, SI_RIDING, 1); + clif->status_change(&sd->bl, SI_RIDING, 1, 0, 0, 0, 0); else if (sd->sc.option&OPTION_WUGRIDER) - clif_status_load(&sd->bl, SI_WUGRIDER, 1); + clif->status_change(&sd->bl, SI_WUGRIDER, 1, 0, 0, 0, 0); if(sd->status.manner < 0) sc_start(&sd->bl,SC_NOCHAT,100,0,0); @@ -9282,33 +9490,33 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) if(sd->bl.m == sd->feel_map[0].m || sd->bl.m == sd->feel_map[1].m || sd->bl.m == sd->feel_map[2].m) - sc_start(&sd->bl, SC_KNOWLEDGE, 100, lv, skill_get_time(SG_KNOWLEDGE, lv)); + sc_start(&sd->bl, SC_KNOWLEDGE, 100, lv, skill->get_time(SG_KNOWLEDGE, lv)); } if(sd->pd && sd->pd->pet.intimate > 900) - clif_pet_emotion(sd->pd,(sd->pd->pet.class_ - 100)*100 + 50 + pet_hungry_val(sd->pd)); + clif->pet_emotion(sd->pd,(sd->pd->pet.class_ - 100)*100 + 50 + pet_hungry_val(sd->pd)); - if(merc_is_hom_active(sd->hd)) - merc_hom_init_timers(sd->hd); + if(homun_alive(sd->hd)) + homun->init_timers(sd->hd); if (night_flag && map[sd->bl.m].flag.nightenabled) { sd->state.night = 1; - clif_status_load(&sd->bl, SI_NIGHT, 1); + clif->status_change(&sd->bl, SI_NIGHT, 1, 0, 0, 0, 0); } // Notify everyone that this char logged in [Skotlex]. - map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1); + map_foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 1); //Login Event npc_script_event(sd, NPCE_LOGIN); } else { //For some reason the client "loses" these on warp/map-change. - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); + clif->updatestatus(sd,SP_STR); + clif->updatestatus(sd,SP_AGI); + clif->updatestatus(sd,SP_VIT); + clif->updatestatus(sd,SP_INT); + clif->updatestatus(sd,SP_DEX); + clif->updatestatus(sd,SP_LUK); // abort currently running script sd->state.using_fake_npc = 0; @@ -9319,73 +9527,73 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) npc_event_dequeue(sd); } - if( sd->state.changemap ) - {// restore information that gets lost on map-change + if( sd->state.changemap ) {// restore information that gets lost on map-change #if PACKETVER >= 20070918 - clif_partyinvitationstate(sd); - clif_equipcheckbox(sd); + clif->partyinvitationstate(sd); + clif->equipcheckbox(sd); #endif if( (battle_config.bg_flee_penalty != 100 || battle_config.gvg_flee_penalty != 100) && (map_flag_gvg(sd->state.pmap) || map_flag_gvg(sd->bl.m) || map[sd->state.pmap].flag.battleground || map[sd->bl.m].flag.battleground) ) status_calc_bl(&sd->bl, SCB_FLEE); //Refresh flee penalty - if( night_flag && map[sd->bl.m].flag.nightenabled ) - { //Display night. - if( !sd->state.night ) - { + if( night_flag && map[sd->bl.m].flag.nightenabled ) { //Display night. + if( !sd->state.night ) { sd->state.night = 1; - clif_status_load(&sd->bl, SI_NIGHT, 1); + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_NIGHT); } - } - else if( sd->state.night ) - { //Clear night display. + } else if( sd->state.night ) { //Clear night display. sd->state.night = 0; - clif_status_load(&sd->bl, SI_NIGHT, 0); + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_NIGHT); } - if( map[sd->bl.m].flag.battleground ) - { - clif_map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode + if( map[sd->bl.m].flag.battleground ) { + clif->map_type(sd, MAPTYPE_BATTLEFIELD); // Battleground Mode if( map[sd->bl.m].flag.battleground == 2 ) - clif_bg_updatescore_single(sd); + clif->bg_updatescore_single(sd); } - if( map[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) - { + if( map[sd->bl.m].flag.allowks && !map_flag_ks(sd->bl.m) ) { char output[128]; sprintf(output, "[ Kill Steal Protection Disable. KS is allowed in this map ]"); - clif_broadcast(&sd->bl, output, strlen(output) + 1, 0x10, SELF); + clif->broadcast(&sd->bl, output, strlen(output) + 1, 0x10, SELF); } map_iwall_get(sd); // Updates Walls Info on this Map to Client + status_calc_pc(sd, false);/* some conditions are map-dependent so we must recalculate */ sd->state.changemap = false; + + if( hChSys.local && hChSys.local_autojoin && !map[sd->bl.m].flag.chsysnolocalaj ) { + clif->chsys_mjoin(sd); + } } mail_clear(sd); + clif->maptypeproperty2(&sd->bl,SELF); + /* Guild Aura Init */ if( sd->state.gmaster_flag ) { - guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); - guild_guildaura_refresh(sd,GD_GLORYWOUNDS,guild_checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); - guild_guildaura_refresh(sd,GD_SOULCOLD,guild_checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); - guild_guildaura_refresh(sd,GD_HAWKEYES,guild_checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); + guild->aura_refresh(sd,GD_LEADERSHIP,guild->checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); + guild->aura_refresh(sd,GD_GLORYWOUNDS,guild->checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); + guild->aura_refresh(sd,GD_SOULCOLD,guild->checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); + guild->aura_refresh(sd,GD_HAWKEYES,guild->checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); } if( sd->state.vending ) { /* show we have a vending */ - clif_openvending(sd,sd->bl.id,sd->vending); - clif_showvendingboard(&sd->bl,sd->message,0); + clif->openvending(sd,sd->bl.id,sd->vending); + clif->showvendingboard(&sd->bl,sd->message,0); } if(map[sd->bl.m].flag.loadevent) // Lance npc_script_event(sd, NPCE_LOADMAP); - if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) - clif_status_load(&sd->bl, SI_DEVIL, 1); //blindness [Komurka] + if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) //blindness [Komurka] + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL); if (sd->sc.opt2) //Client loses these on warp. - clif_changeoption(&sd->bl); + clif->changeoption(&sd->bl); - clif_weather_check(sd); + clif->weather_check(sd); // For automatic triggering of NPCs after map loading (so you don't need to walk 1 step first) if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC)) @@ -9399,22 +9607,21 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) // If player is dead, and is spawned (such as @refresh) send death packet. [Valaris] if(pc_isdead(sd)) - clif_clearunit_area(&sd->bl, CLR_DEAD); + clif->clearunit_area(&sd->bl, CLR_DEAD); else { - skill_usave_trigger(sd); - clif_changed_dir(&sd->bl, SELF); + skill->usave_trigger(sd); + clif->changed_dir(&sd->bl, SELF); } // Trigger skill effects if you appear standing on them if(!battle_config.pc_invincible_time) - skill_unit_move(&sd->bl,gettick(),1); + skill->unit_move(&sd->bl,gettick(),1); } /// Server's tick (ZC_NOTIFY_TIME). /// 007f <time>.L -void clif_notify_time(struct map_session_data* sd, unsigned long time) -{ +void clif_notify_time(struct map_session_data* sd, unsigned long time) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0x7f)); @@ -9430,9 +9637,9 @@ void clif_notify_time(struct map_session_data* sd, unsigned long time) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_TickSend(int fd, struct map_session_data *sd) { - sd->client_tick = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + sd->client_tick = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); - clif_notify_time(sd, gettick()); + clif->notify_time(sd, gettick()); } @@ -9470,12 +9677,12 @@ void clif_parse_Hotkey(int fd, struct map_session_data *sd) { int cmd; cmd = RFIFOW(fd, 0); - idx = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[0]); + idx = RFIFOW(fd, packet_db[cmd].pos[0]); if (idx >= MAX_HOTKEYS) return; - sd->status.hotkeys[idx].type = RFIFOB(fd, packet_db[sd->packet_ver][cmd].pos[1]); - sd->status.hotkeys[idx].id = RFIFOL(fd, packet_db[sd->packet_ver][cmd].pos[2]); - sd->status.hotkeys[idx].lv = RFIFOW(fd, packet_db[sd->packet_ver][cmd].pos[3]); + sd->status.hotkeys[idx].type = RFIFOB(fd, packet_db[cmd].pos[1]); + sd->status.hotkeys[idx].id = RFIFOL(fd, packet_db[cmd].pos[2]); + sd->status.hotkeys[idx].lv = RFIFOW(fd, packet_db[cmd].pos[3]); #endif } @@ -9516,7 +9723,7 @@ void clif_parse_progressbar(int fd, struct map_session_data * sd) sd->st->state = END; sd->progressbar.npc_id = sd->progressbar.timeout = 0; - npc_scriptcont(sd, npc_id); + npc_scriptcont(sd, npc_id, false); } @@ -9529,14 +9736,14 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) short x, y; if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); + clif->clearunit_area(&sd->bl, CLR_DEAD); return; } if (sd->sc.opt1 && ( sd->sc.opt1 == OPT1_STONEWAIT || sd->sc.opt1 == OPT1_BURNING )) ; //You CAN walk on this OPT1 value. else if( sd->progressbar.npc_id ) - clif_progressbar_abort(sd); + clif->progressbar_abort(sd); else if (pc_cant_act(sd)) return; @@ -9545,7 +9752,7 @@ void clif_parse_WalkToXY(int fd, struct map_session_data *sd) pc_delinvincibletimer(sd); - RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0], &x, &y, NULL); + RFIFOPOS(fd, packet_db[RFIFOW(fd,0)].pos[0], &x, &y, NULL); //Set last idle time... [Skotlex] sd->idletime = last_tick; @@ -9582,9 +9789,9 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) { set_eof(fd); - clif_disconnect_ack(sd, 0); + clif->disconnect_ack(sd, 0); } else { - clif_disconnect_ack(sd, 1); + clif->disconnect_ack(sd, 1); } } @@ -9595,7 +9802,7 @@ void clif_parse_QuitGame(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { - int id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + int id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); struct block_list* bl; //struct status_change *sc; @@ -9625,9 +9832,16 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) } */ - clif_charnameack(fd, bl); + clif->charnameack(fd, bl); +} +int clif_undisguise_timer(int tid, unsigned int tick, int id, intptr_t data) { + struct map_session_data * sd; + if( (sd = map_id2sd(id)) && sd->fontcolor && sd->disguise == sd->status.class_ ) { + pc_disguise(sd,-1); + } + sd->fontcolor_tid = INVALID_TIMER; + return 0; } - /// Validates and processes global messages /// 008c <packet len>.W <text>.?B (<name> : <message>) 00 (CZ_REQUEST_CHAT) @@ -9643,21 +9857,54 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) bool is_fake; // validate packet and retrieve name and message - if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; - if( battle_config.min_chat_delay ) - { //[Skotlex] + if( battle_config.min_chat_delay ) { //[Skotlex] if (DIFF_TICK(sd->cantalk_tick, gettick()) > 0) return; sd->cantalk_tick = gettick() + battle_config.min_chat_delay; } + + if( sd->gcbind ) { + clif->chsys_send(sd->gcbind,sd,message); + return; + } else if ( sd->fontcolor && !sd->chatID ) { + char mout[200]; + unsigned char mylen = 1; + + if( sd->disguise == -1 ) { + pc_disguise(sd,sd->status.class_); + if( pc_isdead(sd) ) + clif_clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd); + sd->fontcolor_tid = add_timer(gettick()+5000, clif->undisguise_timer, sd->bl.id, 0); + } else if ( sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER ) { + const struct TimerData *timer; + if( (timer = get_timer(sd->fontcolor_tid)) ) { + settick_timer(sd->fontcolor_tid, timer->tick+5000); + } + } + + mylen += snprintf(mout, 200, "%s : %s",sd->fakename[0]?sd->fakename:sd->status.name,message); + + WFIFOHEAD(fd,mylen + 12); + WFIFOW(fd,0) = 0x2C1; + WFIFOW(fd,2) = mylen + 12; + WFIFOL(fd,4) = sd->bl.id; + WFIFOL(fd,8) = hChSys.colors[sd->fontcolor - 1]; + safestrncpy((char*)WFIFOP(fd,12), mout, mylen); + clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS); + WFIFOL(fd,4) = -sd->bl.id; + WFIFOSET(fd, mylen + 12); + return; + } + /** * Fake Name Design by FatalEror (bug report #9) **/ @@ -9675,7 +9922,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) WFIFOL(fd,4) = sd->bl.id; safestrncpy((char*)WFIFOP(fd,8), is_fake ? fakename : text, textlen); //FIXME: chat has range of 9 only - clif_send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC); + clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, sd->chatID ? CHAT_WOS : AREA_CHAT_WOC); // send back message to the speaker if( is_fake ) { @@ -9694,7 +9941,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd) #endif // Chat logging type 'O' / Global Chat - log_chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); + logs->chat(LOG_CHAT_GLOBAL, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message); } @@ -9708,8 +9955,8 @@ void clif_parse_MapMove(int fd, struct map_session_data *sd) map_name = (char*)RFIFOP(fd,2); map_name[MAP_NAME_LENGTH_EXT-1]='\0'; - sprintf(command, "%cmapmove %s %d %d", atcommand_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cmapmove %s %d %d", atcommand->at_symbol, map_name, RFIFOW(fd,18), RFIFOW(fd,20)); + atcommand->parse(fd, sd, command, 1); } @@ -9737,12 +9984,12 @@ void clif_changed_dir(struct block_list *bl, enum send_target target) WBUFW(buf,6) = bl->type==BL_PC?((TBL_PC*)bl)->head_dir:0; WBUFB(buf,8) = unit_getdir(bl); - clif_send(buf, packet_len(0x9c), bl, target); + clif->send(buf, packet_len(0x9c), bl, target); if (disguised(bl)) { WBUFL(buf,2) = -bl->id; WBUFW(buf,6) = 0; - clif_send(buf, packet_len(0x9c), bl, SELF); + clif->send(buf, packet_len(0x9c), bl, SELF); } } @@ -9755,11 +10002,11 @@ void clif_parse_ChangeDir(int fd, struct map_session_data *sd) { unsigned char headdir, dir; - headdir = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - dir = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + headdir = RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[0]); + dir = RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[1]); pc_setdir(sd, dir, headdir); - clif_changed_dir(&sd->bl, AREA_WOS); + clif->changed_dir(&sd->bl, AREA_WOS); } @@ -9769,36 +10016,34 @@ void clif_parse_ChangeDir(int fd, struct map_session_data *sd) /// @see enum emotion_type void clif_parse_Emotion(int fd, struct map_session_data *sd) { - int emoticon = RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + int emoticon = RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[0]); if (battle_config.basic_skill_check == 0 || pc_checkskill(sd, NV_BASIC) >= 2) { if (emoticon == E_MUTE) {// prevent use of the mute emote [Valaris] - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); + clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); return; } // fix flood of emotion icon (ro-proxy): flood only the hacker player if (sd->emotionlasttime + 1 >= time(NULL)) { // not more than 1 per second sd->emotionlasttime = time(NULL); - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); + clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); return; } sd->emotionlasttime = time(NULL); - if(battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) - {// re-roll dice + if(battle_config.client_reshuffle_dice && emoticon>=E_DICE1 && emoticon<=E_DICE6) {// re-roll dice emoticon = rnd()%6+E_DICE1; } - clif_emotion(&sd->bl, emoticon); + clif->emotion(&sd->bl, emoticon); } else - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); + clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 1); } /// Amount of currently online players, reply to /w /who (ZC_USER_COUNT). /// 00c2 <count>.L -void clif_user_count(struct map_session_data* sd, int count) -{ +void clif_user_count(struct map_session_data* sd, int count) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0xc2)); @@ -9813,14 +10058,14 @@ void clif_user_count(struct map_session_data* sd, int count) /// 00c1 void clif_parse_HowManyConnections(int fd, struct map_session_data *sd) { - clif_user_count(sd, map_getusers()); + clif->user_count(sd, map_getusers()); } void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, unsigned int tick) { if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); + clif->clearunit_area(&sd->bl, CLR_DEAD); return; } @@ -9839,69 +10084,179 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris] target_id = sd->bl.id; - switch(action_type) - { - case 0x00: // once attack - case 0x07: // continuous attack + switch(action_type) { + case 0x00: // once attack + case 0x07: // continuous attack - if( pc_cant_act(sd) || sd->sc.option&OPTION_HIDE ) - return; + if( pc_cant_act(sd) || sd->sc.option&OPTION_HIDE ) + return; - if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) - return; + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) + return; - if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] ) - return; + if( sd->sc.data[SC_BASILICA] || sd->sc.data[SC__SHADOWFORM] ) + return; + + if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) { + if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { + clif->skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0); + return; + } + } + + pc_delinvincibletimer(sd); + sd->idletime = last_tick; + unit_attack(&sd->bl, target_id, action_type != 0); + break; + case 0x02: // sitdown + if (battle_config.basic_skill_check && pc_checkskill(sd, NV_BASIC) < 3) { + clif->skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 2); + break; + } - if (!battle_config.sdelay_attack_enable && pc_checkskill(sd, SA_FREECAST) <= 0) { - if (DIFF_TICK(tick, sd->ud.canact_tick) < 0) { - clif_skill_fail(sd, 1, USESKILL_FAIL_SKILLINTERVAL, 0); + if(pc_issit(sd)) { + //Bugged client? Just refresh them. + clif->sitting(&sd->bl); return; } - } - pc_delinvincibletimer(sd); - sd->idletime = last_tick; - unit_attack(&sd->bl, target_id, action_type != 0); - break; - case 0x02: // sitdown - if (battle_config.basic_skill_check && pc_checkskill(sd, NV_BASIC) < 3) { - clif_skill_fail(sd, 1, USESKILL_FAIL_LEVEL, 2); - break; - } + if (sd->ud.skilltimer != INVALID_TIMER || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING )) + break; - if(pc_issit(sd)) { - //Bugged client? Just refresh them. - clif_sitting(&sd->bl); - return; - } + if (sd->sc.count && ( + sd->sc.data[SC_DANCING] || + (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) + )) //No sitting during these states either. + break; - if (sd->ud.skilltimer != INVALID_TIMER || (sd->sc.opt1 && sd->sc.opt1 != OPT1_BURNING )) - break; + pc_setsit(sd); + skill->sit(sd,1); + clif->sitting(&sd->bl); + break; + case 0x03: // standup + if (!pc_issit(sd)) { + //Bugged client? Just refresh them. + clif->standing(&sd->bl); + return; + } + pc_setstand(sd); + skill->sit(sd,0); + clif->standing(&sd->bl); + break; + } +} - if (sd->sc.count && ( - sd->sc.data[SC_DANCING] || - (sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF) - )) //No sitting during these states either. +void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data *sd) { + unsigned char i; + + if ( !idb_remove(channel->users,sd->status.char_id) ) + return; + + if( channel == sd->gcbind ) + sd->gcbind = NULL; + + if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) { + clif->chsys_delete(channel); + } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) { + char message[60]; + sprintf(message, "#%s '%s' left",channel->name,sd->status.name); + clif->chsys_msg(channel,sd,message); + } + + for( i = 0; i < sd->channel_count; i++ ) { + if( sd->channels[i] == channel ) { + sd->channels[i] = NULL; break; - - pc_setsit(sd); - skill_sit(sd,1); - clif_sitting(&sd->bl); - break; - case 0x03: // standup - if (!pc_issit(sd)) { - //Bugged client? Just refresh them. - clif_standing(&sd->bl); - return; } - pc_setstand(sd); - skill_sit(sd,0); - clif_standing(&sd->bl); - break; } + + if( i < sd->channel_count ) { + unsigned char cursor = 0; + for( i = 0; i < sd->channel_count; i++ ) { + if( sd->channels[i] == NULL ) + continue; + if( cursor != i ) { + sd->channels[cursor] = sd->channels[i]; + } + cursor++; + } + if ( !(sd->channel_count = cursor) ) { + aFree(sd->channels); + sd->channels = NULL; + } + } + } +void clif_hercules_chsys_quitg(struct map_session_data *sd) { + unsigned char i; + struct hChSysCh *channel = NULL; + + for( i = 0; i < sd->channel_count; i++ ) { + if( (channel = sd->channels[i] ) != NULL && channel->type == hChSys_ALLY ) { + + if ( !idb_remove(channel->users,sd->status.char_id) ) + continue; + + if( channel == sd->gcbind ) + sd->gcbind = NULL; + + if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) { + clif->chsys_delete(channel); + } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) { + char message[60]; + sprintf(message, "#%s '%s' left",channel->name,sd->status.name); + clif->chsys_msg(channel,sd,message); + } + sd->channels[i] = NULL; + } + } + + if( i < sd->channel_count ) { + unsigned char cursor = 0; + for( i = 0; i < sd->channel_count; i++ ) { + if( sd->channels[i] == NULL ) + continue; + if( cursor != i ) { + sd->channels[cursor] = sd->channels[i]; + } + cursor++; + } + if ( !(sd->channel_count = cursor) ) { + aFree(sd->channels); + sd->channels = NULL; + } + } + +} + + +void clif_hercules_chsys_quit(struct map_session_data *sd) { + unsigned char i; + struct hChSysCh *channel = NULL; + + for( i = 0; i < sd->channel_count; i++ ) { + if( (channel = sd->channels[i] ) != NULL ) { + idb_remove(channel->users,sd->status.char_id); + + if( channel == sd->gcbind ) + sd->gcbind = NULL; + + if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) { + clif->chsys_delete(channel); + } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) { + char message[60]; + sprintf(message, "#%s '%s' left",channel->name,sd->status.name); + clif->chsys_msg(channel,sd,message); + } + + } + } + + sd->channel_count = 0; + aFree(sd->channels); + sd->channels = NULL; +} /// Request for an action. /// 0089 <target id>.L <action>.B (CZ_REQUEST_ACT) @@ -9916,9 +10271,9 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, /// There are various variants of this packet, some of them have padding between fields. void clif_parse_ActionRequest(int fd, struct map_session_data *sd) { - clif_parse_ActionRequest_sub(sd, - RFIFOB(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), - RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), + clif->pActionRequest_sub(sd, + RFIFOB(fd,packet_db[RFIFOW(fd,0)].pos[1]), + RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]), gettick() ); } @@ -9929,22 +10284,21 @@ void clif_parse_ActionRequest(int fd, struct map_session_data *sd) /// type: /// 0 = restart (respawn) /// 1 = char-select (disconnect) -void clif_parse_Restart(int fd, struct map_session_data *sd) -{ +void clif_parse_Restart(int fd, struct map_session_data *sd) { switch(RFIFOB(fd,2)) { - case 0x00: - pc_respawn(sd,CLR_RESPAWN); - break; - case 0x01: - /* Rovert's Prevent logout option - Fixed [Valaris] */ - if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && - (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) - { //Send to char-server for character selection. - chrif_charselectreq(sd, session[fd]->client_addr); - } else { - clif_disconnect_ack(sd, 1); - } - break; + case 0x00: + pc_respawn(sd,CLR_RESPAWN); + break; + case 0x01: + /* Rovert's Prevent logout option - Fixed [Valaris] */ + if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && + (!battle_config.prevent_logout || DIFF_TICK(gettick(), sd->canlog_tick) > battle_config.prevent_logout) ) + { //Send to char-server for character selection. + chrif_charselectreq(sd, session[fd]->client_addr); + } else { + clif->disconnect_ack(sd, 1); + } + break; } } @@ -9960,10 +10314,10 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) int namelen, messagelen; // validate packet and retrieve name and message - if( !clif_process_message(sd, 1, &target, &namelen, &message, &messagelen) ) + if( !clif->process_message(sd, 1, &target, &namelen, &message, &messagelen) ) return; - if ( is_atcommand(fd, sd, message, 1) ) + if ( atcommand->parse(fd, sd, message, 1) ) return; if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)) @@ -9977,13 +10331,12 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) } // Chat logging type 'W' / Whisper - log_chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message); + logs->chat(LOG_CHAT_WHISPER, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, target, message); //-------------------------------------------------------// // Lordalfa - Paperboy - To whisper NPC commands // //-------------------------------------------------------// - if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) - { + if (target[0] && (strncasecmp(target,"NPC:",4) == 0) && (strlen(target) > 4)) { char* str = target+4; //Skip the NPC: string part. struct npc_data* npc; if ((npc = npc_name2id(str))) { @@ -10018,15 +10371,48 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) return; } - } else if(strcmpi(target, main_chat_nick) == 0) { // Main chat [LuzZza] - if(!sd->state.mainchat) - clif_displaymessage(fd, msg_txt(388)); // You should enable main chat with "@main on" command. - else { - // send the main message using inter-server system - intif_main_message( sd, message ); + } else if( target[0] == '#' ) { + struct hChSysCh *channel = NULL; + char* chname = target; + + chname++; + + if( hChSys.local && strcmpi(chname, hChSys.local_name) == 0 ) { + if( !map[sd->bl.m].channel ) { + clif->chsys_mjoin(sd); + } + channel = map[sd->bl.m].channel; + } else if( hChSys.ally && sd->status.guild_id && strcmpi(chname, hChSys.ally_name) == 0 ) { + struct guild *g = sd->guild; + if( !g ) return; + channel = (struct hChSysCh *)g->channel; + } + if( channel || (channel = strdb_get(clif->channel_db,chname)) ) { + unsigned char k; + for( k = 0; k < sd->channel_count; k++ ) { + if( sd->channels[k] == channel ) + break; + } + if( k < sd->channel_count ) { + clif->chsys_send(channel,sd,message); + } else if( channel->pass[0] == '\0' && !(channel->banned && idb_exists(channel->banned, sd->status.account_id)) ) { + if( channel->type == hChSys_ALLY ) { + struct guild *g = sd->guild, *sg = NULL; + int k; + for (k = 0; k < MAX_GUILDALLIANCE; k++) { + if( g->alliance[k].opposition == 0 && g->alliance[k].guild_id && (sg = guild->search(g->alliance[k].guild_id) ) ) { + if( !(((struct hChSysCh*)sg->channel)->banned && idb_exists(((struct hChSysCh*)sg->channel)->banned, sd->status.account_id))) + clif->chsys_join((struct hChSysCh *)sg->channel,sd); + } + } + } + clif->chsys_join(channel,sd); + clif->chsys_send(channel,sd,message); + } else { + clif->message(fd, msg_txt(1402)); + } + return; } - - return; } // searching destination character @@ -10045,9 +10431,9 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) // if player ignores everyone if (dstsd->state.ignoreAll) { if (dstsd->sc.option & OPTION_INVISIBLE && pc_get_group_level(sd) < pc_get_group_level(dstsd)) - clif_wis_end(fd, 1); // 1: target character is not loged in + clif->wis_end(fd, 1); // 1: target character is not loged in else - clif_wis_end(fd, 3); // 3: everyone ignored by target + clif->wis_end(fd, 3); // 3: everyone ignored by target return; } @@ -10055,22 +10441,22 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd) if( dstsd->state.autotrade == 1 ) { char output[256]; sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name); - clif_wis_message(fd, wisp_server_name, output, strlen(output) + 1); + clif->wis_message(fd, wisp_server_name, output, strlen(output) + 1); return; } // if player ignores the source character ARR_FIND(0, MAX_IGNORE_LIST, i, dstsd->ignore[i].name[0] == '\0' || strcmp(dstsd->ignore[i].name, sd->status.name) == 0); if(i < MAX_IGNORE_LIST && dstsd->ignore[i].name[0] != '\0') { // source char present in ignore list - clif_wis_end(fd, 2); // 2: ignored by target + clif->wis_end(fd, 2); // 2: ignored by target return; } // notify sender of success - clif_wis_end(fd, 0); // 0: success to send wisper + clif->wis_end(fd, 0); // 0: success to send wisper // Normal message - clif_wis_message(dstsd->fd, sd->status.name, message, messagelen); + clif->wis_message(dstsd->fd, sd->status.name, message, messagelen); } @@ -10085,8 +10471,8 @@ void clif_parse_Broadcast(int fd, struct map_session_data* sd) { // as the length varies depending on the command used, just block unreasonably long strings mes_len_check(msg, len, CHAT_SIZE_MAX); - sprintf(command, "%ckami %s", atcommand_symbol, msg); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%ckami %s", atcommand->at_symbol, msg); + atcommand->parse(fd, sd, command, 1); } @@ -10099,20 +10485,27 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) struct flooritem_data *fitem; int map_object_id; - map_object_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + map_object_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); fitem = (struct flooritem_data*)map_id2bl(map_object_id); do { if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); + clif->clearunit_area(&sd->bl, CLR_DEAD); break; } if (fitem == NULL || fitem->bl.type != BL_ITEM || fitem->bl.m != sd->bl.m) break; - if( sd->sc.cant.pickup ) + if( sd->sc.count && ( + sd->sc.data[SC_HIDING] || + sd->sc.data[SC_CLOAKING] || + sd->sc.data[SC_TRICKDEAD] || + sd->sc.data[SC_BLADESTOP] || + sd->sc.data[SC_CLOAKINGEXCEED] || + (sd->sc.data[SC_NOCHAT] &&sd->sc.data[SC_NOCHAT]->val1&MANNER_NOITEM) + ) ) break; if (pc_cant_act(sd)) @@ -10124,7 +10517,7 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) return; } while (0); // Client REQUIRES a fail packet or you can no longer pick items. - clif_additem(sd,0,0,6); + clif->additem(sd,0,0,6); } @@ -10134,14 +10527,14 @@ void clif_parse_TakeItem(int fd, struct map_session_data *sd) /// There are various variants of this packet, some of them have padding between fields. void clif_parse_DropItem(int fd, struct map_session_data *sd) { - int item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; - int item_amount = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + int item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2; + int item_amount = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]); for(;;) { if (pc_isdead(sd)) break; - if (pc_cant_act(sd)) + if ( pc_cant_act2(sd) ) break; if (sd->sc.count && ( @@ -10158,7 +10551,7 @@ void clif_parse_DropItem(int fd, struct map_session_data *sd) } //Because the client does not like being ignored. - clif_dropitem(sd, item_index,0); + clif->dropitem(sd, item_index,0); } @@ -10171,26 +10564,21 @@ void clif_parse_UseItem(int fd, struct map_session_data *sd) int n; if (pc_isdead(sd)) { - clif_clearunit_area(&sd->bl, CLR_DEAD); + clif->clearunit_area(&sd->bl, CLR_DEAD); return; } - //This flag enables you to use items while in an NPC. [Skotlex] - if (sd->npc_id) { - if (sd->npc_id != sd->npc_item_flag) - return; - } - else if (pc_istrading(sd)) + if ( (!sd->npc_id && pc_istrading(sd)) || sd->chatID ) return; //Whether the item is used or not is irrelevant, the char ain't idle. [Skotlex] sd->idletime = last_tick; - n = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; + n = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2; if(n <0 || n >= MAX_INVENTORY) return; if (!pc_useitem(sd,n)) - clif_useitemack(sd,n,0,false); //Send an empty ack packet or the client gets stuck. + clif->useitemack(sd,n,0,false); //Send an empty ack packet or the client gets stuck. } @@ -10201,23 +10589,23 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) int index; if(pc_isdead(sd)) { - clif_clearunit_area(&sd->bl,CLR_DEAD); + clif->clearunit_area(&sd->bl,CLR_DEAD); return; } index = RFIFOW(fd,2)-2; if (index < 0 || index >= MAX_INVENTORY) return; //Out of bounds check. - if(sd->npc_id) { - if (sd->npc_id != sd->npc_item_flag) + if( sd->npc_id ) { + if ( !sd->npc_item_flag ) return; - } else if (sd->state.storage_flag || sd->sc.opt1) + } else if ( sd->state.storage_flag || sd->sc.opt1 ) ; //You can equip/unequip stuff while storage is open/under status changes - else if (pc_cant_act(sd)) + else if ( pc_cant_act2(sd) ) return; if(!sd->status.inventory[index].identify) { - clif_equipitemack(sd,index,0,0); // fail + clif->equipitemack(sd,index,0,0); // fail return; } @@ -10236,6 +10624,94 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) pc_equipitem(sd,index,RFIFOW(fd,4)); } +void clif_hercules_chsys_delete(struct hChSysCh *channel) { + if( db_size(channel->users) && !hChSys.closing ) { + DBIterator *iter; + struct map_session_data *sd; + unsigned char i; + iter = db_iterator(channel->users); + for( sd = dbi_first(iter); dbi_exists(iter); sd = dbi_next(iter) ) { + for( i = 0; i < sd->channel_count; i++ ) { + if( sd->channels[i] == channel ) { + sd->channels[i] = NULL; + break; + } + } + if( i < sd->channel_count ) { + unsigned char cursor = 0; + for( i = 0; i < sd->channel_count; i++ ) { + if( sd->channels[i] == NULL ) + continue; + if( cursor != i ) { + sd->channels[cursor] = sd->channels[i]; + } + cursor++; + } + if ( !(sd->channel_count = cursor) ) { + aFree(sd->channels); + sd->channels = NULL; + } + } + } + dbi_destroy(iter); + } + if( channel->banned ) { + db_destroy(channel->banned); + channel->banned = NULL; + } + db_destroy(channel->users); + if( channel->m ) { + map[channel->m].channel = NULL; + aFree(channel); + } else if ( channel->type == hChSys_ALLY ) + aFree(channel); + else if( !hChSys.closing ) + strdb_remove(clif->channel_db, channel->name); +} +void clif_hercules_chsys_gjoin(struct guild *g1,struct guild *g2) { + struct map_session_data *sd; + struct hChSysCh *channel; + int j; + + if( (channel = (struct hChSysCh*)g1->channel) ) { + for(j = 0; j < g2->max_member; j++) { + if( (sd = g2->member[j].sd) != NULL ) { + if( !(((struct hChSysCh*)g1->channel)->banned && idb_exists(((struct hChSysCh*)g1->channel)->banned, sd->status.account_id))) + clif->chsys_join(channel,sd); + } + } + } + + if( (channel = (struct hChSysCh*)g2->channel) ) { + for(j = 0; j < g1->max_member; j++) { + if( (sd = g1->member[j].sd) != NULL ) { + if( !(((struct hChSysCh*)g2->channel)->banned && idb_exists(((struct hChSysCh*)g2->channel)->banned, sd->status.account_id))) + clif->chsys_join(channel,sd); + } + } + } +} +void clif_hercules_chsys_gleave(struct guild *g1,struct guild *g2) { + struct map_session_data *sd; + struct hChSysCh *channel; + int j; + + if( (channel = (struct hChSysCh*)g1->channel) ) { + for(j = 0; j < g2->max_member; j++) { + if( (sd = g2->member[j].sd) != NULL ) { + clif->chsys_left(channel,sd); + } + } + } + + if( (channel = (struct hChSysCh*)g2->channel) ) { + for(j = 0; j < g1->max_member; j++) { + if( (sd = g1->member[j].sd) != NULL ) { + clif->chsys_left(channel,sd); + } + } + } +} /// Request to take off an equip (CZ_REQ_TAKEOFF_EQUIP). /// 00ab <index>.W @@ -10244,13 +10720,16 @@ void clif_parse_UnequipItem(int fd,struct map_session_data *sd) int index; if(pc_isdead(sd)) { - clif_clearunit_area(&sd->bl,CLR_DEAD); + clif->clearunit_area(&sd->bl,CLR_DEAD); return; } - if (sd->state.storage_flag || sd->sc.opt1) + if( sd->npc_id ) { + if ( !sd->npc_item_flag ) + return; + } else if ( sd->state.storage_flag || sd->sc.opt1 ) ; //You can equip/unequip stuff while storage is open/under status changes - else if (pc_cant_act(sd)) + else if ( pc_cant_act2(sd) ) return; index = RFIFOW(fd,2)-2; @@ -10272,7 +10751,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) return; } - if (pc_cant_act(sd)) + if ( pc_cant_act2(sd) ) return; bl = map_id2bl(RFIFOL(fd,2)); @@ -10280,7 +10759,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd) switch (bl->type) { case BL_MOB: case BL_PC: - clif_parse_ActionRequest_sub(sd, 0x07, bl->id, gettick()); + clif->pActionRequest_sub(sd, 0x07, bl->id, gettick()); break; case BL_NPC: if( bl->m != -1 )// the user can't click floating npcs directly (hack attempt) @@ -10310,8 +10789,7 @@ void clif_parse_NpcBuySellSelected(int fd,struct map_session_data *sd) /// 1 = "You do not have enough zeny." /// 2 = "You are over your Weight Limit." /// 3 = "Out of the maximum capacity, you have too many items." -void clif_npc_buy_result(struct map_session_data* sd, unsigned char result) -{ +void clif_npc_buy_result(struct map_session_data* sd, unsigned char result) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0xca)); @@ -10336,7 +10814,7 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) sd->npc_shopid = 0; //Clear shop data. - clif_npc_buy_result(sd, result); + clif->npc_buy_result(sd, result); } @@ -10345,8 +10823,7 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd) /// result: /// 0 = "The deal has successfully completed." /// 1 = "The deal has failed." -void clif_npc_sell_result(struct map_session_data* sd, unsigned char result) -{ +void clif_npc_sell_result(struct map_session_data* sd, unsigned char result) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0xcb)); @@ -10373,7 +10850,7 @@ void clif_parse_NpcSellListSend(int fd,struct map_session_data *sd) sd->npc_shopid = 0; //Clear shop data. - clif_npc_sell_result(sd, fail); + clif->npc_sell_result(sd, fail); } @@ -10395,7 +10872,15 @@ void clif_parse_CreateChatRoom(int fd, struct map_session_data* sd) if (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM) return; if(battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 4) { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,3); + clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,3); + return; + } + if( npc_isnear(&sd->bl) ) { + // uncomment for more verbose message. + //char output[150]; + //sprintf(output, msg_txt(662), battle_config.min_npc_vendchat_distance); + //clif_displaymessage(sd->fd, output); + clif->skill_fail(sd,1,USESKILL_FAIL_THERE_ARE_NPC_AROUND,0); return; } @@ -10475,16 +10960,15 @@ void clif_parse_ChatLeave(int fd, struct map_session_data* sd) //Handles notifying asker and rejecter of what has just ocurred. //Type is used to determine the correct msg_txt to use: //0: -static void clif_noask_sub(struct map_session_data *src, struct map_session_data *target, int type) -{ +void clif_noask_sub(struct map_session_data *src, struct map_session_data *target, int type) { const char* msg; char output[256]; // Your request has been rejected by autoreject option. msg = msg_txt(392); - clif_disp_onlyself(src, msg, strlen(msg)); + clif->disp_onlyself(src, msg, strlen(msg)); //Notice that a request was rejected. snprintf(output, 256, msg_txt(393+type), src->status.name, 256); - clif_disp_onlyself(target, output, strlen(output)); + clif->disp_onlyself(target, output, strlen(output)); } @@ -10501,13 +10985,12 @@ void clif_parse_TradeRequest(int fd,struct map_session_data *sd) // @noask [LuzZza] if(t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 0); + clif->noask_sub(sd, t_sd, 0); return; } - if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 1) - { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,0); + if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 1) { + clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,0); return; } @@ -10662,36 +11145,34 @@ void clif_parse_SkillUp(int fd,struct map_session_data *sd) pc_skillup(sd,RFIFOW(fd,2)); } -static void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id) +void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id) { int lv; if( !hd ) return; - if( skillnotok_hom(skill_id, hd) ) + if( skill->not_ok_hom(skill_id, hd) ) return; - if( hd->bl.id != target_id && skill_get_inf(skill_id)&INF_SELF_SKILL ) + if( hd->bl.id != target_id && skill->get_inf(skill_id)&INF_SELF_SKILL ) target_id = hd->bl.id; - if( hd->ud.skilltimer != INVALID_TIMER ) - { + if( hd->ud.skilltimer != INVALID_TIMER ) { if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return; - } - else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) + } else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) return; - lv = merc_hom_checkskill(hd, skill_id); + lv = homun->checkskill(hd, skill_id); if( skill_lv > lv ) skill_lv = lv; if( skill_lv ) unit_skilluse_id(&hd->bl, target_id, skill_id, skill_lv); } -static void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) +void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) { int lv; if( !hd ) return; - if( skillnotok_hom(skill_id, hd) ) + if( skill->not_ok_hom(skill_id, hd) ) return; if( hd->ud.skilltimer != INVALID_TIMER ) { if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return; @@ -10700,28 +11181,26 @@ static void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_ses if( hd->sc.data[SC_BASILICA] ) return; - lv = merc_hom_checkskill(hd, skill_id); + lv = homun->checkskill(hd, skill_id); if( skill_lv > lv ) skill_lv = lv; if( skill_lv ) unit_skilluse_pos(&hd->bl, x, y, skill_id, skill_lv); } -static void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id) +void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id) { int lv; if( !md ) return; - if( skillnotok_mercenary(skill_id, md) ) + if( skill->not_ok_mercenary(skill_id, md) ) return; - if( md->bl.id != target_id && skill_get_inf(skill_id)&INF_SELF_SKILL ) + if( md->bl.id != target_id && skill->get_inf(skill_id)&INF_SELF_SKILL ) target_id = md->bl.id; - if( md->ud.skilltimer != INVALID_TIMER ) - { + if( md->ud.skilltimer != INVALID_TIMER ) { if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return; - } - else if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) + } else if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) return; lv = mercenary_checkskill(md, skill_id); @@ -10731,18 +11210,17 @@ static void clif_parse_UseSkillToId_mercenary(struct mercenary_data *md, struct unit_skilluse_id(&md->bl, target_id, skill_id, skill_lv); } -static void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) +void clif_parse_UseSkillToPos_mercenary(struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo) { int lv; if( !md ) return; - if( skillnotok_mercenary(skill_id, md) ) + if( skill->not_ok_mercenary(skill_id, md) ) return; if( md->ud.skilltimer != INVALID_TIMER ) return; - if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) - { - clif_skill_fail(md->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); + if( DIFF_TICK(tick, md->ud.canact_tick) < 0 ) { + clif->skill_fail(md->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return; } @@ -10766,37 +11244,41 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) int tmp, target_id; unsigned int tick = gettick(); - skill_lv = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - skill_id = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); - target_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]); + skill_lv = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0]); + skill_id = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]); + target_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[2]); if( skill_lv < 1 ) skill_lv = 1; //No clue, I have seen the client do this with guild skills :/ [Skotlex] - tmp = skill_get_inf(skill_id); + tmp = skill->get_inf(skill_id); if (tmp&INF_GROUND_SKILL || !tmp) return; //Using a ground/passive skill on a target? WRONG. - if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE + MAX_HOMUNSKILL ) - { - clif_parse_UseSkillToId_homun(sd->hd, sd, tick, skill_id, skill_lv, target_id); + if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE + MAX_HOMUNSKILL ) { + clif->pUseSkillToId_homun(sd->hd, sd, tick, skill_id, skill_lv, target_id); return; } - if( skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL ) - { - clif_parse_UseSkillToId_mercenary(sd->md, sd, tick, skill_id, skill_lv, target_id); + if( skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL ) { + clif->pUseSkillToId_mercenary(sd->md, sd, tick, skill_id, skill_lv, target_id); return; } // Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] sd->idletime = last_tick; + if( sd->npc_id ){ +#ifdef RENEWAL + clif->msg(sd, 0x783); // TODO look for the client date that has this message. +#endif + return; + } if( pc_cant_act(sd) && skill_id != RK_REFRESH && !(skill_id == SR_GENTLETOUCH_CURE && (sd->sc.opt1 == OPT1_STONE || sd->sc.opt1 == OPT1_FREEZE || sd->sc.opt1 == OPT1_STUN)) ) return; if( pc_issit(sd) ) return; - if( skillnotok(skill_id, sd) ) + if( skill->not_ok(skill_id, sd) ) return; if( sd->bl.id != target_id && tmp&INF_SELF_SKILL ) @@ -10805,21 +11287,17 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris] target_id = sd->bl.id; - if( sd->ud.skilltimer != INVALID_TIMER ) - { + if( sd->ud.skilltimer != INVALID_TIMER ) { if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return; - } - else if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) - { - if( sd->skillitem != skill_id ) - { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); + } else if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) { + if( sd->skillitem != skill_id ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return; } } - if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) return; if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) @@ -10844,7 +11322,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) if( skill_id >= GD_SKILLBASE ) { if( sd->state.gmaster_flag ) - skill_lv = guild_checkskill(sd->state.gmaster_flag, skill_id); + skill_lv = guild->checkskill(sd->state.gmaster_flag, skill_id); else skill_lv = 0; } else { @@ -10862,34 +11340,31 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd) /*========================================== * Client tells server he'd like to use AoE skill id 'skill_id' of level 'skill_lv' on 'x','y' location *------------------------------------------*/ -static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo) +void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo) { unsigned int tick = gettick(); - if( !(skill_get_inf(skill_id)&INF_GROUND_SKILL) ) + if( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) ) return; //Using a target skill on the ground? WRONG. if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE + MAX_HOMUNSKILL ) { - clif_parse_UseSkillToPos_homun(sd->hd, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo); + clif->pUseSkillToPos_homun(sd->hd, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo); return; } - if( skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL ) - { - clif_parse_UseSkillToPos_mercenary(sd->md, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo); + if( skill_id >= MC_SKILLBASE && skill_id < MC_SKILLBASE + MAX_MERCSKILL ) { + clif->pUseSkillToPos_mercenary(sd->md, sd, tick, skill_id, skill_lv, x, y, skillmoreinfo); return; } //Whether skill fails or not is irrelevant, the char ain't idle. [Skotlex] sd->idletime = last_tick; - if( skillnotok(skill_id, sd) ) + if( skill->not_ok(skill_id, sd) ) return; - if( skillmoreinfo != -1 ) - { - if( pc_issit(sd) ) - { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + if( skillmoreinfo != -1 ) { + if( pc_issit(sd) ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); return; } //You can't use Graffiti/TalkieBox AND have a vending open, so this is safe. @@ -10901,12 +11376,12 @@ static void clif_parse_UseSkillToPosSub(int fd, struct map_session_data *sd, uin if( DIFF_TICK(tick, sd->ud.canact_tick) < 0 ) { if( sd->skillitem != skill_id ) { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return; } } - if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER) ) + if( sd->sc.option&(OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK) ) return; if( sd->sc.data[SC_BASILICA] && (skill_id != HP_BASILICA || sd->sc.data[SC_BASILICA]->val4 != sd->bl.id) ) @@ -10948,11 +11423,11 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd) if (pc_issit(sd)) return; - clif_parse_UseSkillToPosSub(fd, sd, - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), //skill lv - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), //skill num - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]), //pos x - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[3]), //pos y + clif->pUseSkillToPosSub(fd, sd, + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0]), //skill lv + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]), //skill num + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[2]), //pos x + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[3]), //pos y -1 //Skill more info. ); } @@ -10969,12 +11444,12 @@ void clif_parse_UseSkillToPosMoreInfo(int fd, struct map_session_data *sd) if (pc_issit(sd)) return; - clif_parse_UseSkillToPosSub(fd, sd, - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), //Skill lv - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]), //Skill num - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[2]), //pos x - RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[3]), //pos y - packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[4] //skill more info + clif->pUseSkillToPosSub(fd, sd, + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0]), //Skill lv + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]), //Skill num + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[2]), //pos x + RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[3]), //pos y + packet_db[RFIFOW(fd,0)].pos[4] //skill more info ); } @@ -10996,7 +11471,7 @@ void clif_parse_UseSkillMap(int fd, struct map_session_data* sd) } pc_delinvincibletimer(sd); - skill_castend_map(sd,skill_id,map_name); + skill->castend_map(sd,skill_id,map_name); } @@ -11024,12 +11499,12 @@ void clif_parse_ProduceMix(int fd,struct map_session_data *sd) } if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); clif_menuskill_clear(sd); return; } - if( skill_can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1) ) - skill_produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1); + if( skill->can_produce_mix(sd,RFIFOW(fd,2),sd->menuskill_val, 1) ) + skill->produce_mix(sd,0,RFIFOW(fd,2),RFIFOW(fd,4),RFIFOW(fd,6),RFIFOW(fd,8), 1); clif_menuskill_clear(sd); } @@ -11052,12 +11527,12 @@ void clif_parse_Cooking(int fd,struct map_session_data *sd) { if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); clif_menuskill_clear(sd); return; } - if( skill_can_produce_mix(sd,nameid,sd->menuskill_val, amount) ) - skill_produce_mix(sd,(type>1?sd->menuskill_id:0),nameid,0,0,0,amount); + if( skill->can_produce_mix(sd,nameid,sd->menuskill_val, amount) ) + skill->produce_mix(sd,(type>1?sd->menuskill_id:0),nameid,0,0,0,amount); clif_menuskill_clear(sd); } @@ -11070,11 +11545,11 @@ void clif_parse_RepairItem(int fd, struct map_session_data *sd) return; if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); clif_menuskill_clear(sd); return; } - skill_repairweapon(sd,RFIFOW(fd,2)); + skill->repairweapon(sd,RFIFOW(fd,2)); clif_menuskill_clear(sd); } @@ -11089,12 +11564,12 @@ void clif_parse_WeaponRefine(int fd, struct map_session_data *sd) return; if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); clif_menuskill_clear(sd); return; } - idx = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - skill_weaponrefine(sd, idx-2); + idx = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); + skill->weaponrefine(sd, idx-2); clif_menuskill_clear(sd); } @@ -11111,16 +11586,21 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) int npc_id = RFIFOL(fd,2); uint8 select = RFIFOB(fd,6); - if( (select > sd->npc_menu && select != 0xff) || select == 0 ) - { - TBL_NPC* nd = map_id2nd(npc_id); - ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); - clif_GM_kick(NULL,sd); + if( (select > sd->npc_menu && select != 0xff) || select == 0 ) { +#ifdef SECURE_NPCTIMEOUT + if( sd->npc_idle_timer != INVALID_TIMER ) { +#endif + TBL_NPC* nd = map_id2nd(npc_id); + ShowWarning("Invalid menu selection on npc %d:'%s' - got %d, valid range is [%d..%d] (player AID:%d, CID:%d, name:'%s')!\n", npc_id, (nd)?nd->name:"invalid npc id", select, 1, sd->npc_menu, sd->bl.id, sd->status.char_id, sd->status.name); + clif->GM_kick(NULL,sd); +#ifdef SECURE_NPCTIMEOUT + } +#endif return; } sd->npc_menu = select; - npc_scriptcont(sd,npc_id); + npc_scriptcont(sd,npc_id, false); } @@ -11128,7 +11608,7 @@ void clif_parse_NpcSelectMenu(int fd,struct map_session_data *sd) /// 00b9 <npc id>.L void clif_parse_NpcNextClicked(int fd,struct map_session_data *sd) { - npc_scriptcont(sd,RFIFOL(fd,2)); + npc_scriptcont(sd,RFIFOL(fd,2), false); } @@ -11140,7 +11620,7 @@ void clif_parse_NpcAmountInput(int fd,struct map_session_data *sd) int amount = (int)RFIFOL(fd,6); sd->npc_amount = amount; - npc_scriptcont(sd, npcid); + npc_scriptcont(sd, npcid, false); } @@ -11156,7 +11636,7 @@ void clif_parse_NpcStringInput(int fd, struct map_session_data* sd) return; // invalid input safestrncpy(sd->npc_str, message, min(message_len,CHATBOX_SIZE)); - npc_scriptcont(sd, npcid); + npc_scriptcont(sd, npcid, false); } @@ -11166,7 +11646,7 @@ void clif_parse_NpcCloseClicked(int fd,struct map_session_data *sd) { if (!sd->npc_id) //Avoid parsing anything when the script was done with. [Skotlex] return; - npc_scriptcont(sd,RFIFOL(fd,2)); + npc_scriptcont(sd, RFIFOL(fd,2), true); } @@ -11184,7 +11664,7 @@ void clif_parse_ItemIdentify(int fd,struct map_session_data *sd) clif_menuskill_clear(sd); return; } - skill_identify(sd,idx-2); + skill->identify(sd,idx-2); clif_menuskill_clear(sd); } @@ -11195,25 +11675,25 @@ void clif_parse_SelectArrow(int fd,struct map_session_data *sd) { if (pc_istrading(sd)) { //Make it fail to avoid shop exploits where you sell something different than you see. - clif_skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->ud.skill_id,USESKILL_FAIL_LEVEL,0); clif_menuskill_clear(sd); return; } switch( sd->menuskill_id ) { case AC_MAKINGARROW: - skill_arrow_create(sd,RFIFOW(fd,2)); + skill->arrow_create(sd,RFIFOW(fd,2)); break; case SA_CREATECON: - skill_produce_mix(sd,SA_CREATECON,RFIFOW(fd,2),0,0,0, 1); + skill->produce_mix(sd,SA_CREATECON,RFIFOW(fd,2),0,0,0, 1); break; case WL_READING_SB: - skill_spellbook(sd,RFIFOW(fd,2)); + skill->spellbook(sd,RFIFOW(fd,2)); break; case GC_POISONINGWEAPON: - skill_poisoningweapon(sd,RFIFOW(fd,2)); + skill->poisoningweapon(sd,RFIFOW(fd,2)); break; case NC_MAGICDECOY: - skill_magicdecoy(sd,RFIFOW(fd,2)); + skill->magicdecoy(sd,RFIFOW(fd,2)); break; } @@ -11227,7 +11707,7 @@ void clif_parse_AutoSpell(int fd,struct map_session_data *sd) { if (sd->menuskill_id != SA_AUTOSPELL) return; - skill_autospell(sd,RFIFOL(fd,2)); + skill->autospell(sd,RFIFOL(fd,2)); clif_menuskill_clear(sd); } @@ -11238,7 +11718,7 @@ void clif_parse_UseCard(int fd,struct map_session_data *sd) { if (sd->state.trading != 0) return; - clif_use_card(sd,RFIFOW(fd,2)-2); + clif->use_card(sd,RFIFOW(fd,2)-2); } @@ -11260,7 +11740,7 @@ void clif_parse_SolveCharName(int fd, struct map_session_data *sd) { int charid; - charid = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + charid = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); map_reqnickdb(sd, charid); } @@ -11275,11 +11755,11 @@ void clif_parse_ResetChar(int fd, struct map_session_data *sd) { char cmd[15]; if( RFIFOW(fd,2) ) - sprintf(cmd,"%cresetskill",atcommand_symbol); + sprintf(cmd,"%cresetskill",atcommand->at_symbol); else - sprintf(cmd,"%cresetstat",atcommand_symbol); + sprintf(cmd,"%cresetstat",atcommand->at_symbol); - is_atcommand(fd, sd, cmd, 1); + atcommand->parse(fd, sd, cmd, 1); } @@ -11295,8 +11775,8 @@ void clif_parse_LocalBroadcast(int fd, struct map_session_data* sd) // as the length varies depending on the command used, just block unreasonably long strings mes_len_check(msg, len, CHAT_SIZE_MAX); - sprintf(command, "%clkami %s", atcommand_symbol, msg); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%clkami %s", atcommand->at_symbol, msg); + atcommand->parse(fd, sd, command, 1); } @@ -11311,8 +11791,8 @@ void clif_parse_MoveToKafra(int fd, struct map_session_data *sd) if (pc_istrading(sd)) return; - item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-2; - item_amount = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-2; + item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]); if (item_index < 0 || item_index >= MAX_INVENTORY || item_amount < 1) return; @@ -11332,13 +11812,12 @@ void clif_parse_MoveFromKafra(int fd,struct map_session_data *sd) { int item_index, item_amount; - item_index = RFIFOW(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0])-1; - item_amount = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1]); + item_index = RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[0])-1; + item_amount = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[1]); if (sd->state.storage_flag == 1) storage_storageget(sd, item_index, item_amount); - else - if(sd->state.storage_flag == 2) + else if(sd->state.storage_flag == 2) storage_guild_storageget(sd, item_index, item_amount); } @@ -11383,8 +11862,7 @@ void clif_parse_CloseKafra(int fd, struct map_session_data *sd) { if( sd->state.storage_flag == 1 ) storage_storageclose(sd); - else - if( sd->state.storage_flag == 2 ) + else if( sd->state.storage_flag == 2 ) storage_guild_storageclose(sd); } @@ -11450,14 +11928,12 @@ void clif_parse_CreateParty(int fd, struct map_session_data *sd) char* name = (char*)RFIFOP(fd,2); name[NAME_LENGTH-1] = '\0'; - if( map[sd->bl.m].flag.partylock ) - {// Party locked. - clif_displaymessage(fd, msg_txt(227)); + if( map[sd->bl.m].flag.partylock ) { // Party locked. + clif->message(fd, msg_txt(227)); return; } - if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) - { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); + if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) { + clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); return; } @@ -11471,14 +11947,12 @@ void clif_parse_CreateParty2(int fd, struct map_session_data *sd) int item2 = RFIFOB(fd,27); name[NAME_LENGTH-1] = '\0'; - if( map[sd->bl.m].flag.partylock ) - {// Party locked. - clif_displaymessage(fd, msg_txt(227)); + if( map[sd->bl.m].flag.partylock ) {// Party locked. + clif->message(fd, msg_txt(227)); return; } - if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) - { - clif_skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); + if( battle_config.basic_skill_check && pc_checkskill(sd,NV_BASIC) < 7 ) { + clif->skill_fail(sd,1,USESKILL_FAIL_LEVEL,4); return; } @@ -11493,17 +11967,15 @@ void clif_parse_PartyInvite(int fd, struct map_session_data *sd) { struct map_session_data *t_sd; - if(map[sd->bl.m].flag.partylock) - {// Party locked. - clif_displaymessage(fd, msg_txt(227)); + if(map[sd->bl.m].flag.partylock) {// Party locked. + clif->message(fd, msg_txt(227)); return; } t_sd = map_id2sd(RFIFOL(fd,2)); - if(t_sd && t_sd->state.noask) - {// @noask [LuzZza] - clif_noask_sub(sd, t_sd, 1); + if(t_sd && t_sd->state.noask) {// @noask [LuzZza] + clif->noask_sub(sd, t_sd, 1); return; } @@ -11516,17 +11988,15 @@ void clif_parse_PartyInvite2(int fd, struct map_session_data *sd) char *name = (char*)RFIFOP(fd,2); name[NAME_LENGTH-1] = '\0'; - if(map[sd->bl.m].flag.partylock) - {// Party locked. - clif_displaymessage(fd, msg_txt(227)); + if(map[sd->bl.m].flag.partylock) { // Party locked. + clif->message(fd, msg_txt(227)); return; } t_sd = map_nick2sd(name); - if(t_sd && t_sd->state.noask) - {// @noask [LuzZza] - clif_noask_sub(sd, t_sd, 1); + if(t_sd && t_sd->state.noask) { // @noask [LuzZza] + clif->noask_sub(sd, t_sd, 1); return; } @@ -11555,9 +12025,8 @@ void clif_parse_ReplyPartyInvite2(int fd,struct map_session_data *sd) /// 0100 void clif_parse_LeaveParty(int fd, struct map_session_data *sd) { - if(map[sd->bl.m].flag.partylock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(227)); + if(map[sd->bl.m].flag.partylock) { //Guild locked. + clif->message(fd, msg_txt(227)); return; } party_leave(sd); @@ -11568,9 +12037,8 @@ void clif_parse_LeaveParty(int fd, struct map_session_data *sd) /// 0103 <account id>.L <char name>.24B void clif_parse_RemovePartyMember(int fd, struct map_session_data *sd) { - if(map[sd->bl.m].flag.partylock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(227)); + if(map[sd->bl.m].flag.partylock) { //Guild locked. + clif->message(fd, msg_txt(227)); return; } party_removemember(sd,RFIFOL(fd,2),(char*)RFIFOP(fd,6)); @@ -11619,10 +12087,10 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd) int namelen, messagelen; // validate packet and retrieve name and message - if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) @@ -11731,7 +12199,7 @@ void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, void clif_parse_PartyBookingDeleteReq(int fd, struct map_session_data* sd) { if(party_booking_delete(sd)) - clif_PartyBookingDeleteAck(sd, 0); + clif->PartyBookingDeleteAck(sd, 0); } @@ -11785,7 +12253,7 @@ void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_boo for(i=0; i<PARTY_BOOKING_JOBS; i++) WBUFW(buf,38+i*2) = pb_ad->p_detail.job[i]; - clif_send(buf, packet_len(0x809), &sd->bl, ALL_CLIENT); + clif->send(buf, packet_len(0x809), &sd->bl, ALL_CLIENT); } @@ -11802,7 +12270,7 @@ void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_boo WBUFL(buf,2) = pb_ad->index; for(i=0; i<PARTY_BOOKING_JOBS; i++) WBUFW(buf,6+i*2) = pb_ad->p_detail.job[i]; - clif_send(buf,packet_len(0x80a),&sd->bl,ALL_CLIENT); // Now UPDATE all client. + clif->send(buf,packet_len(0x80a),&sd->bl,ALL_CLIENT); // Now UPDATE all client. } @@ -11815,7 +12283,7 @@ void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) WBUFW(buf,0) = 0x80b; WBUFL(buf,2) = index; - clif_send(buf, packet_len(0x80b), &sd->bl, ALL_CLIENT); // Now UPDATE all client. + clif->send(buf, packet_len(0x80b), &sd->bl, ALL_CLIENT); // Now UPDATE all client. } @@ -11823,7 +12291,7 @@ void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index) /// 012e void clif_parse_CloseVending(int fd, struct map_session_data* sd) { - vending_closevending(sd); + vending->close(sd); } @@ -11831,11 +12299,10 @@ void clif_parse_CloseVending(int fd, struct map_session_data* sd) /// 0130 <account id>.L void clif_parse_VendingListReq(int fd, struct map_session_data* sd) { - if( sd->npc_id ) - {// using an NPC + if( sd->npc_id ) {// using an NPC return; } - vending_vendinglistreq(sd,RFIFOL(fd,2)); + vending->list(sd,RFIFOL(fd,2)); } @@ -11847,7 +12314,7 @@ void clif_parse_PurchaseReq(int fd, struct map_session_data* sd) int id = (int)RFIFOL(fd,4); const uint8* data = (uint8*)RFIFOP(fd,8); - vending_purchasereq(sd, id, sd->vended_id, data, len/4); + vending->purchase(sd, id, sd->vended_id, data, len/4); // whether it fails or not, the buy window is closed sd->vended_id = 0; @@ -11863,7 +12330,7 @@ void clif_parse_PurchaseReq2(int fd, struct map_session_data* sd) int uid = (int)RFIFOL(fd,8); const uint8* data = (uint8*)RFIFOP(fd,12); - vending_purchasereq(sd, aid, uid, data, len/4); + vending->purchase(sd, aid, uid, data, len/4); // whether it fails or not, the buy window is closed sd->vended_id = 0; @@ -11882,33 +12349,27 @@ void clif_parse_OpenVending(int fd, struct map_session_data* sd) const char* message = (char*)RFIFOP(fd,4); bool flag = (bool)RFIFOB(fd,84); const uint8* data = (uint8*)RFIFOP(fd,85); + + if( !flag ) + sd->state.prevend = 0; if( sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOROOM ) return; if( map[sd->bl.m].flag.novending ) { - clif_displaymessage (sd->fd, msg_txt(276)); // "You can't open a shop on this map" + clif->message (sd->fd, msg_txt(276)); // "You can't open a shop on this map" return; } if( map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNOVENDING) ) { - clif_displaymessage (sd->fd, msg_txt(204)); // "You can't open a shop on this cell." - return; - } - - if( vending_checknearnpc(&sd->bl) ) { - char output[150]; - sprintf(output, msg_txt(662), battle_config.min_npc_vending_distance); - clif_displaymessage(sd->fd, output); - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); + clif->message (sd->fd, msg_txt(204)); // "You can't open a shop on this cell." return; } if( message[0] == '\0' ) // invalid input return; - vending_openvending(sd, message, flag, data, len/8); + vending->open(sd, message, data, len/8); } - /// Guild creation request (CZ_REQ_MAKE_GUILD). /// 0165 <char id>.L <guild name>.24B void clif_parse_CreateGuild(int fd,struct map_session_data *sd) @@ -11916,13 +12377,12 @@ void clif_parse_CreateGuild(int fd,struct map_session_data *sd) char* name = (char*)RFIFOP(fd,6); name[NAME_LENGTH-1] = '\0'; - if(map[sd->bl.m].flag.guildlock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if(map[sd->bl.m].flag.guildlock) { //Guild locked. + clif->message(fd, msg_txt(228)); return; } - guild_create(sd, name); + guild->create(sd, name); } @@ -11930,7 +12390,7 @@ void clif_parse_CreateGuild(int fd,struct map_session_data *sd) /// 014d void clif_parse_GuildCheckMaster(int fd, struct map_session_data *sd) { - clif_guild_masterormember(sd); + clif->guild_masterormember(sd); } @@ -11949,29 +12409,28 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd) if( !sd->status.guild_id && !sd->bg_id ) return; - switch( RFIFOL(fd,2) ) - { - case 0: // Basic Information Guild, hostile alliance information - clif_guild_basicinfo(sd); - clif_guild_allianceinfo(sd); - break; - case 1: // Members list, list job title - clif_guild_positionnamelist(sd); - clif_guild_memberlist(sd); - break; - case 2: // List job title, title information list - clif_guild_positionnamelist(sd); - clif_guild_positioninfolist(sd); - break; - case 3: // Skill list - clif_guild_skillinfo(sd); - break; - case 4: // Expulsion list - clif_guild_expulsionlist(sd); - break; - default: - ShowError("clif: guild request info: unknown type %d\n", RFIFOL(fd,2)); - break; + switch( RFIFOL(fd,2) ) { + case 0: // Basic Information Guild, hostile alliance information + clif->guild_basicinfo(sd); + clif->guild_allianceinfo(sd); + break; + case 1: // Members list, list job title + clif->guild_positionnamelist(sd); + clif->guild_memberlist(sd); + break; + case 2: // List job title, title information list + clif->guild_positionnamelist(sd); + clif->guild_positioninfolist(sd); + break; + case 3: // Skill list + clif->guild_skillinfo(sd); + break; + case 4: // Expulsion list + clif->guild_expulsionlist(sd); + break; + default: + ShowError("clif: guild request info: unknown type %d\n", RFIFOL(fd,2)); + break; } } @@ -11986,7 +12445,7 @@ void clif_parse_GuildChangePositionInfo(int fd, struct map_session_data *sd) return; for(i = 4; i < RFIFOW(fd,2); i += 40 ){ - guild_change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char*)RFIFOP(fd,i+16)); + guild->change_position(sd->status.guild_id, RFIFOL(fd,i), RFIFOL(fd,i+4), RFIFOL(fd,i+12), (char*)RFIFOP(fd,i+16)); } } @@ -12001,7 +12460,7 @@ void clif_parse_GuildChangeMemberPosition(int fd, struct map_session_data *sd) return; for(i=4;i<RFIFOW(fd,2);i+=12){ - guild_change_memberposition(sd->status.guild_id, + guild->change_memberposition(sd->status.guild_id, RFIFOL(fd,i),RFIFOL(fd,i+4),RFIFOL(fd,i+8)); } } @@ -12014,14 +12473,13 @@ void clif_parse_GuildRequestEmblem(int fd,struct map_session_data *sd) struct guild* g; int guild_id = RFIFOL(fd,2); - if( (g = guild_search(guild_id)) != NULL ) - clif_guild_emblem(sd,g); + if( (g = guild->search(guild_id)) != NULL ) + clif->guild_emblem(sd,g); } /// Validates data of a guild emblem (compressed bitmap) -static bool clif_validate_emblem(const uint8* emblem, unsigned long emblem_len) -{ +bool clif_validate_emblem(const uint8* emblem, unsigned long emblem_len) { bool success; uint8 buf[1800]; // no well-formed emblem bitmap is larger than 1782 (24 bit) / 1654 (8 bit) bytes unsigned long buf_len = sizeof(buf); @@ -12046,13 +12504,12 @@ void clif_parse_GuildChangeEmblem(int fd,struct map_session_data *sd) if( !emblem_len || !sd->state.gmaster_flag ) return; - if( !clif_validate_emblem(emblem, emblem_len) ) - { + if( !clif->validate_emblem(emblem, emblem_len) ) { ShowWarning("clif_parse_GuildChangeEmblem: Rejected malformed guild emblem (size=%lu, accound_id=%d, char_id=%d, guild_id=%d).\n", emblem_len, sd->status.account_id, sd->status.char_id, sd->status.guild_id); return; } - guild_change_emblem(sd, emblem_len, (const char*)emblem); + guild->change_emblem(sd, emblem_len, (const char*)emblem); } @@ -12072,34 +12529,50 @@ void clif_parse_GuildChangeNotice(int fd, struct map_session_data* sd) if (msg2[0] == '|' && msg2[3] == '|') msg2+= 3; // skip duplicate marker if (msg2[0] == '|') msg2[strnlen(msg2, MAX_GUILDMES2)-1] = '\0'; // delete extra space at the end of string - guild_change_notice(sd, guild_id, msg1, msg2); + guild->change_notice(sd, guild_id, msg1, msg2); } +// Helper function for guild invite functions +int +clif_sub_guild_invite(int fd, struct map_session_data *sd, struct map_session_data *t_sd) { + if (t_sd == NULL) {// not online or does not exist + return 1; + } + + if (map[sd->bl.m].flag.guildlock) { //Guild locked. + clif->message(fd, msg_txt(228)); + return 1; + } + + if (t_sd && t_sd->state.noask) {// @noask [LuzZza] + clif->noask_sub(sd, t_sd, 2); + return 1; + } + + guild->invite(sd,t_sd); + return 0; +} /// Guild invite request (CZ_REQ_JOIN_GUILD). /// 0168 <account id>.L <inviter account id>.L <inviter char id>.L void clif_parse_GuildInvite(int fd,struct map_session_data *sd) { - struct map_session_data *t_sd; + struct map_session_data *t_sd = map_id2sd(RFIFOL(fd,2)); - if(map[sd->bl.m].flag.guildlock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if (clif_sub_guild_invite(fd, sd, t_sd)) return; - } - - t_sd = map_id2sd(RFIFOL(fd,2)); +} - // @noask [LuzZza] - if(t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 2); +/// Guild invite request (/guildinvite) (CZ_REQ_JOIN_GUILD2). +/// 0916 <char name>.24B +void clif_parse_GuildInvite2(int fd, struct map_session_data *sd) +{ + struct map_session_data *t_sd = map_nick2sd((char *)RFIFOP(fd, 2)); + + if (clif_sub_guild_invite(fd, sd, t_sd)) return; - } - - guild_invite(sd,t_sd); } - /// Answer to guild invitation (CZ_JOIN_GUILD). /// 016b <guild id>.L <answer>.L /// answer: @@ -12107,7 +12580,7 @@ void clif_parse_GuildInvite(int fd,struct map_session_data *sd) /// 1 = accept void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) { - guild_reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); + guild->reply_invite(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } @@ -12115,18 +12588,16 @@ void clif_parse_GuildReplyInvite(int fd,struct map_session_data *sd) /// 0159 <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildLeave(int fd,struct map_session_data *sd) { - if(map[sd->bl.m].flag.guildlock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if(map[sd->bl.m].flag.guildlock) { //Guild locked. + clif->message(fd, msg_txt(228)); return; } - if( sd->bg_id ) - { - clif_displaymessage(fd, msg_txt(670)); //"You can't leave battleground guilds." + if( sd->bg_id ) { + clif->message(fd, msg_txt(670)); //"You can't leave battleground guilds." return; } - guild_leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); + guild->leave(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } @@ -12134,12 +12605,11 @@ void clif_parse_GuildLeave(int fd,struct map_session_data *sd) /// 015b <guild id>.L <account id>.L <char id>.L <reason>.40B void clif_parse_GuildExpulsion(int fd,struct map_session_data *sd) { - if( map[sd->bl.m].flag.guildlock || sd->bg_id ) - { // Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if( map[sd->bl.m].flag.guildlock || sd->bg_id ) { // Guild locked. + clif->message(fd, msg_txt(228)); return; } - guild_expulsion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); + guild->expulsion(sd,RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),(char*)RFIFOP(fd,14)); } @@ -12154,10 +12624,10 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) int namelen, messagelen; // validate packet and retrieve name and message - if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) @@ -12173,7 +12643,7 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd) if( sd->bg_id ) bg_send_message(sd, text, textlen); else - guild_send_message(sd, text, textlen); + guild->send_message(sd, text, textlen); } @@ -12186,9 +12656,8 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) if(!sd->state.gmaster_flag) return; - if(map[sd->bl.m].flag.guildlock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if(map[sd->bl.m].flag.guildlock) { //Guild locked. + clif->message(fd, msg_txt(228)); return; } @@ -12196,11 +12665,11 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) // @noask [LuzZza] if(t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 3); + clif->noask_sub(sd, t_sd, 3); return; } - guild_reqalliance(sd,t_sd); + guild->reqalliance(sd,t_sd); } @@ -12211,7 +12680,7 @@ void clif_parse_GuildRequestAlliance(int fd, struct map_session_data *sd) /// 1 = accept void clif_parse_GuildReplyAlliance(int fd, struct map_session_data *sd) { - guild_reply_reqalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); + guild->reply_reqalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } @@ -12225,12 +12694,11 @@ void clif_parse_GuildDelAlliance(int fd, struct map_session_data *sd) if(!sd->state.gmaster_flag) return; - if(map[sd->bl.m].flag.guildlock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if(map[sd->bl.m].flag.guildlock) { //Guild locked. + clif->message(fd, msg_txt(228)); return; } - guild_delalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); + guild->delalliance(sd,RFIFOL(fd,2),RFIFOL(fd,6)); } @@ -12243,9 +12711,8 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) if(!sd->state.gmaster_flag) return; - if(map[sd->bl.m].flag.guildlock) - { //Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if(map[sd->bl.m].flag.guildlock) { //Guild locked. + clif->message(fd, msg_txt(228)); return; } @@ -12253,11 +12720,11 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) // @noask [LuzZza] if(t_sd && t_sd->state.noask) { - clif_noask_sub(sd, t_sd, 4); + clif->noask_sub(sd, t_sd, 4); return; } - guild_opposition(sd,t_sd); + guild->opposition(sd,t_sd); } @@ -12268,12 +12735,11 @@ void clif_parse_GuildOpposition(int fd, struct map_session_data *sd) /// field name and size is same as the one in CH_DELETE_CHAR. void clif_parse_GuildBreak(int fd, struct map_session_data *sd) { - if( map[sd->bl.m].flag.guildlock ) - { //Guild locked. - clif_displaymessage(fd, msg_txt(228)); + if( map[sd->bl.m].flag.guildlock ) { //Guild locked. + clif->message(fd, msg_txt(228)); return; } - guild_break(sd,(char*)RFIFOP(fd,2)); + guild->dobreak(sd,(char*)RFIFOP(fd,2)); } @@ -12306,10 +12772,9 @@ void clif_parse_CatchPet(int fd, struct map_session_data *sd) /// 01a7 <index>.W void clif_parse_SelectEgg(int fd, struct map_session_data *sd) { - if (sd->menuskill_id != SA_TAMINGMONSTER || sd->menuskill_val != -1) - { + if (sd->menuskill_id != SA_TAMINGMONSTER || sd->menuskill_val != -1) { //Forged packet, disconnect them [Kevin] - clif_authfail_fd(fd, 0); + clif->authfail_fd(fd, 0); return; } pet_select_egg(sd,RFIFOW(fd,2)-2); @@ -12344,7 +12809,7 @@ void clif_parse_SelectEgg(int fd, struct map_session_data *sd) void clif_parse_SendEmotion(int fd, struct map_session_data *sd) { if(sd->pd) - clif_pet_emotion(sd->pd,RFIFOL(fd,2)); + clif->pet_emotion(sd->pd,RFIFOL(fd,2)); } @@ -12368,45 +12833,45 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) tid = RFIFOL(fd,2); target = map_id2bl(tid); if (!target) { - clif_GM_kickack(sd, 0); + clif->GM_kickack(sd, 0); return; } switch (target->type) { - case BL_PC: - { - char command[NAME_LENGTH+6]; - sprintf(command, "%ckick %s", atcommand_symbol, status_get_name(target)); - is_atcommand(fd, sd, command, 1); - } - break; + case BL_PC: + { + char command[NAME_LENGTH+6]; + sprintf(command, "%ckick %s", atcommand->at_symbol, status_get_name(target)); + atcommand->parse(fd, sd, command, 1); + } + break; - /** - * This one does not invoke any atcommand, so we need to check for permissions. - */ - case BL_MOB: - { - char command[100]; - if( !pc_can_use_command(sd, "killmonster", COMMAND_ATCOMMAND)) { - clif_GM_kickack(sd, 0); - return; + /** + * This one does not invoke any atcommand, so we need to check for permissions. + */ + case BL_MOB: + { + char command[100]; + if( !pc_can_use_command(sd, "@killmonster")) { + clif->GM_kickack(sd, 0); + return; + } + sprintf(command, "/kick %s (%d)", status_get_name(target), status_get_class(target)); + logs->atcommand(sd, command); + status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' } - sprintf(command, "/kick %s (%d)", status_get_name(target), status_get_class(target)); - log_atcommand(sd, command); - status_percent_damage(&sd->bl, target, 100, 0, true); // can invalidate 'target' - } - break; + break; - case BL_NPC: - { - char command[NAME_LENGTH+11]; - sprintf(command, "%cunloadnpc %s", atcommand_symbol, status_get_name(target)); - is_atcommand(fd, sd, command, 1); - } - break; + case BL_NPC: + { + char command[NAME_LENGTH+11]; + sprintf(command, "%cunloadnpc %s", atcommand->at_symbol, status_get_name(target)); + atcommand->parse(fd, sd, command, 1); + } + break; - default: - clif_GM_kickack(sd, 0); + default: + clif->GM_kickack(sd, 0); } } @@ -12416,8 +12881,8 @@ void clif_parse_GMKick(int fd, struct map_session_data *sd) /// 00ce void clif_parse_GMKickAll(int fd, struct map_session_data* sd) { char cmd[15]; - sprintf(cmd,"%ckickall",atcommand_symbol); - is_atcommand(fd, sd, cmd, 1); + sprintf(cmd,"%ckickall",atcommand->at_symbol); + atcommand->parse(fd, sd, cmd, 1); } @@ -12436,8 +12901,8 @@ void clif_parse_GMShift(int fd, struct map_session_data *sd) player_name = (char*)RFIFOP(fd,2); player_name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%cjumpto %s", atcommand_symbol, player_name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cjumpto %s", atcommand->at_symbol, player_name); + atcommand->parse(fd, sd, command, 1); } @@ -12449,12 +12914,11 @@ void clif_parse_GMRemove2(int fd, struct map_session_data* sd) int account_id; struct map_session_data* pl_sd; - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - if( (pl_sd = map_id2sd(account_id)) != NULL ) - { + account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); + if( (pl_sd = map_id2sd(account_id)) != NULL ) { char command[NAME_LENGTH+8]; - sprintf(command, "%cjumpto %s", atcommand_symbol, pl_sd->status.name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cjumpto %s", atcommand->at_symbol, pl_sd->status.name); + atcommand->parse(fd, sd, command, 1); } } @@ -12474,8 +12938,8 @@ void clif_parse_GMRecall(int fd, struct map_session_data *sd) player_name = (char*)RFIFOP(fd,2); player_name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%crecall %s", atcommand_symbol, player_name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%crecall %s", atcommand->at_symbol, player_name); + atcommand->parse(fd, sd, command, 1); } @@ -12487,12 +12951,11 @@ void clif_parse_GMRecall2(int fd, struct map_session_data* sd) int account_id; struct map_session_data* pl_sd; - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); - if( (pl_sd = map_id2sd(account_id)) != NULL ) - { + account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); + if( (pl_sd = map_id2sd(account_id)) != NULL ) { char command[NAME_LENGTH+8]; - sprintf(command, "%crecall %s", atcommand_symbol, pl_sd->status.name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%crecall %s", atcommand->at_symbol, pl_sd->status.name); + atcommand->parse(fd, sd, command, 1); } } @@ -12511,16 +12974,16 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) // FIXME: Should look for item first, then for monster. // FIXME: /monster takes mob_db Sprite_Name as argument if( mobdb_searchname(monster_item_name) ) { - snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand_symbol, monster_item_name); - is_atcommand(fd, sd, command, 1); + snprintf(command, sizeof(command)-1, "%cmonster %s", atcommand->at_symbol, monster_item_name); + atcommand->parse(fd, sd, command, 1); return; } // FIXME: Stackables have a quantity of 20. // FIXME: Equips are supposed to be unidentified. if( itemdb_searchname(monster_item_name) ) { - snprintf(command, sizeof(command)-1, "%citem %s", atcommand_symbol, monster_item_name); - is_atcommand(fd, sd, command, 1); + snprintf(command, sizeof(command)-1, "%citem %s", atcommand->at_symbol, monster_item_name); + atcommand->parse(fd, sd, command, 1); return; } } @@ -12533,9 +12996,9 @@ void clif_parse_GM_Monster_Item(int fd, struct map_session_data *sd) void clif_parse_GMHide(int fd, struct map_session_data *sd) { char cmd[6]; - sprintf(cmd,"%chide",atcommand_symbol); + sprintf(cmd,"%chide",atcommand->at_symbol); - is_atcommand(fd, sd, cmd, 1); + atcommand->parse(fd, sd, cmd, 1); } @@ -12567,8 +13030,8 @@ void clif_parse_GMReqNoChat(int fd,struct map_session_data *sd) if( dstsd == NULL ) return; - sprintf(command, "%cmute %d %s", atcommand_symbol, value, dstsd->status.name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cmute %d %s", atcommand->at_symbol, value, dstsd->status.name); + atcommand->parse(fd, sd, command, 1); } @@ -12581,15 +13044,14 @@ void clif_parse_GMRc(int fd, struct map_session_data* sd) char *name = (char*)RFIFOP(fd,2); name[NAME_LENGTH-1] = '\0'; - sprintf(command, "%cmute %d %s", atcommand_symbol, 60, name); - is_atcommand(fd, sd, command, 1); + sprintf(command, "%cmute %d %s", atcommand->at_symbol, 60, name); + atcommand->parse(fd, sd, command, 1); } /// Result of request to resolve account name (ZC_ACK_ACCOUNTNAME). /// 01e0 <account id>.L <account name>.24B -void clif_account_name(struct map_session_data* sd, int account_id, const char* accname) -{ +void clif_account_name(struct map_session_data* sd, int account_id, const char* accname) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0x1e0)); @@ -12607,7 +13069,7 @@ void clif_parse_GMReqAccountName(int fd, struct map_session_data *sd) int account_id = RFIFOL(fd,2); //TODO: find out if this works for any player or only for authorized GMs - clif_account_name(sd, account_id, ""); // insert account name here >_< + clif->account_name(sd, account_id, ""); // insert account name here >_< } @@ -12629,7 +13091,7 @@ void clif_parse_GMChangeMapType(int fd, struct map_session_data *sd) type = RFIFOW(fd,6); map_setgatcell(sd->bl.m,x,y,type); - clif_changemapcell(0,sd->bl.m,x,y,type,ALL_SAMEMAP); + clif->changemapcell(0,sd->bl.m,x,y,type,ALL_SAMEMAP); //FIXME: once players leave the map, the client 'forgets' this information. } @@ -12650,37 +13112,31 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd) nick[NAME_LENGTH-1] = '\0'; // to be sure that the player name has at most 23 characters type = RFIFOB(fd,26); - if( type == 0 ) - { // Add name to ignore list (block) + if( type == 0 ) { // Add name to ignore list (block) if (strcmp(wisp_server_name, nick) == 0) { - clif_wisexin(sd, type, 1); // fail + clif->wisexin(sd, type, 1); // fail return; } // try to find a free spot, while checking for duplicates at the same time ARR_FIND( 0, MAX_IGNORE_LIST, i, sd->ignore[i].name[0] == '\0' || strcmp(sd->ignore[i].name, nick) == 0 ); - if( i == MAX_IGNORE_LIST ) - {// no space for new entry - clif_wisexin(sd, type, 2); // too many blocks + if( i == MAX_IGNORE_LIST ) {// no space for new entry + clif->wisexin(sd, type, 2); // too many blocks return; } - if( sd->ignore[i].name[0] != '\0' ) - {// name already exists - clif_wisexin(sd, type, 0); // Aegis reports success. + if( sd->ignore[i].name[0] != '\0' ) { // name already exists + clif->wisexin(sd, type, 0); // Aegis reports success. return; } //Insert in position i safestrncpy(sd->ignore[i].name, nick, NAME_LENGTH); - } - else - { // Remove name from ignore list (unblock) + } else { // Remove name from ignore list (unblock) // find entry ARR_FIND( 0, MAX_IGNORE_LIST, i, sd->ignore[i].name[0] == '\0' || strcmp(sd->ignore[i].name, nick) == 0 ); - if( i == MAX_IGNORE_LIST || sd->ignore[i].name[i] == '\0' ) - { //Not found - clif_wisexin(sd, type, 1); // fail + if( i == MAX_IGNORE_LIST || sd->ignore[i].name[i] == '\0' ) { //Not found + clif->wisexin(sd, type, 1); // fail return; } // move everything one place down to overwrite removed entry @@ -12689,7 +13145,7 @@ void clif_parse_PMIgnore(int fd, struct map_session_data* sd) memset(sd->ignore[MAX_IGNORE_LIST-1].name, 0, sizeof(sd->ignore[0].name)); } - clif_wisexin(sd, type, 0); // success + clif->wisexin(sd, type, 0); // success } @@ -12703,17 +13159,14 @@ void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) { int type = RFIFOB(fd,2), flag; - if( type == 0 ) - {// Deny all + if( type == 0 ) {// Deny all if( sd->state.ignoreAll ) { flag = 1; // fail } else { sd->state.ignoreAll = 1; flag = 0; // success } - } - else - {//Unblock everyone + } else {//Unblock everyone if( sd->state.ignoreAll ) { sd->state.ignoreAll = 0; flag = 0; // success @@ -12728,21 +13181,19 @@ void clif_parse_PMIgnoreAll(int fd, struct map_session_data *sd) } } - clif_wisall(sd, type, flag); + clif->wisall(sd, type, flag); } /// Whisper ignore list (ZC_WHISPER_LIST). /// 00d4 <packet len>.W { <char name>.24B }* -void clif_PMIgnoreList(struct map_session_data* sd) -{ +void clif_PMIgnoreList(struct map_session_data* sd) { int i, fd = sd->fd; WFIFOHEAD(fd,4+ARRAYLENGTH(sd->ignore)*NAME_LENGTH); WFIFOW(fd,0) = 0xd4; - for( i = 0; i < ARRAYLENGTH(sd->ignore) && sd->ignore[i].name[0]; i++ ) - { + for( i = 0; i < ARRAYLENGTH(sd->ignore) && sd->ignore[i].name[0]; i++ ) { memcpy(WFIFOP(fd,4+i*NAME_LENGTH), sd->ignore[i].name, NAME_LENGTH); } @@ -12755,7 +13206,7 @@ void clif_PMIgnoreList(struct map_session_data* sd) /// 00d3 void clif_parse_PMIgnoreList(int fd,struct map_session_data *sd) { - clif_PMIgnoreList(sd); + clif->PMIgnoreList(sd); } @@ -12765,8 +13216,7 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) { if (sd->state.doridori) return; - switch (sd->class_&MAPID_UPPERMASK) - { + switch (sd->class_&MAPID_UPPERMASK) { case MAPID_SOUL_LINKER: case MAPID_STAR_GLADIATOR: case MAPID_TAEKWON: @@ -12789,18 +13239,15 @@ void clif_parse_NoviceDoriDori(int fd, struct map_session_data *sd) /// "Help me out~ Please~ T_T" void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) { - if( ( sd->class_&MAPID_UPPERMASK ) == MAPID_SUPER_NOVICE ) - { + if( ( sd->class_&MAPID_UPPERMASK ) == MAPID_SUPER_NOVICE ) { unsigned int next = pc_nextbaseexp(sd); if( next == 0 ) next = pc_thisbaseexp(sd); - if( next ) - { + if( next ) { int percent = (int)( ( (float)sd->status.base_exp/(float)next )*1000. ); - if( percent && ( percent%100 ) == 0 ) - {// 10.0%, 20.0%, ..., 90.0% - sc_start(&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill_get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] - clif_skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions + if( percent && ( percent%100 ) == 0 ) {// 10.0%, 20.0%, ..., 90.0% + sc_start(&sd->bl, status_skill2sc(MO_EXPLOSIONSPIRITS), 100, 17, skill->get_time(MO_EXPLOSIONSPIRITS, 5)); //Lv17-> +50 critical (noted by Poki) [Skotlex] + clif->skill_nodamage(&sd->bl, &sd->bl, MO_EXPLOSIONSPIRITS, 5, 1); // prayer always shows successful Lv5 cast and disregards noskill restrictions } } } @@ -12815,8 +13262,7 @@ void clif_parse_NoviceExplosionSpirits(int fd, struct map_session_data *sd) /// state: /// 0 = online /// 1 = offline -void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int char_id, int online) -{ +void clif_friendslist_toggle(struct map_session_data *sd,int account_id, int char_id, int online) { int i, fd = sd->fd; //Seek friend. @@ -12842,7 +13288,7 @@ int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap) account_id = va_arg(ap, int); char_id = va_arg(ap, int); online = va_arg(ap, int); - clif_friendslist_toggle(sd, account_id, char_id, online); + clif->friendslist_toggle(sd, account_id, char_id, online); return 0; } @@ -12856,8 +13302,7 @@ void clif_friendslist_send(struct map_session_data *sd) // Send friends list WFIFOHEAD(fd, MAX_FRIENDS * 32 + 4); WFIFOW(fd, 0) = 0x201; - for(i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id; i++) - { + for(i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id; i++) { WFIFOL(fd, 4 + 32 * i + 0) = sd->status.friends[i].account_id; WFIFOL(fd, 4 + 32 * i + 4) = sd->status.friends[i].char_id; memcpy(WFIFOP(fd, 4 + 32 * i + 8), &sd->status.friends[i].name, NAME_LENGTH); @@ -12868,10 +13313,9 @@ void clif_friendslist_send(struct map_session_data *sd) WFIFOSET(fd, WFIFOW(fd,2)); } - for (n = 0; n < i; n++) - { //Sending the online players + for (n = 0; n < i; n++) { //Sending the online players if (map_charid2sd(sd->status.friends[n].char_id)) - clif_friendslist_toggle(sd, sd->status.friends[n].account_id, sd->status.friends[n].char_id, 1); + clif->friendslist_toggle(sd, sd->status.friends[n].account_id, sd->status.friends[n].char_id, 1); } } @@ -12892,8 +13336,7 @@ void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_dat WFIFOHEAD(fd,packet_len(0x209)); WFIFOW(fd,0) = 0x209; WFIFOW(fd,2) = type; - if (f_sd) - { + if (f_sd) { WFIFOL(fd,4) = f_sd->status.account_id; WFIFOL(fd,8) = f_sd->status.char_id; memcpy(WFIFOP(fd, 12), f_sd->status.name,NAME_LENGTH); @@ -12904,8 +13347,7 @@ void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_dat /// Asks a player for permission to be added as friend (ZC_REQ_ADD_FRIENDS). /// 0207 <req account id>.L <req char id>.L <req char name>.24B -void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_id, const char* name) -{ +void clif_friendlist_req(struct map_session_data* sd, int account_id, int char_id, const char* name) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0x207)); @@ -12930,31 +13372,30 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) ARR_FIND(0, MAX_FRIENDS, i, sd->status.friends[i].char_id == 0); if( i == MAX_FRIENDS ) { - clif_friendslist_reqack(sd, f_sd, 2); + clif->friendslist_reqack(sd, f_sd, 2); return; } // Friend doesn't exist (no player with this name) if (f_sd == NULL) { - clif_displaymessage(fd, msg_txt(3)); + clif->message(fd, msg_txt(3)); return; } - if( sd->bl.id == f_sd->bl.id ) - {// adding oneself as friend + if( sd->bl.id == f_sd->bl.id ) { // adding oneself as friend return; } // @noask [LuzZza] if(f_sd->state.noask) { - clif_noask_sub(sd, f_sd, 5); + clif->noask_sub(sd, f_sd, 5); return; } // Friend already exists for (i = 0; i < MAX_FRIENDS && sd->status.friends[i].char_id != 0; i++) { if (sd->status.friends[i].char_id == f_sd->status.char_id) { - clif_displaymessage(fd, msg_txt(671)); //"Friend already exists." + clif->message(fd, msg_txt(671)); //"Friend already exists." return; } } @@ -12962,7 +13403,7 @@ void clif_parse_FriendsListAdd(int fd, struct map_session_data *sd) f_sd->friend_req = sd->status.char_id; sd->friend_req = f_sd->status.char_id; - clif_friendlist_req(f_sd, sd->status.account_id, sd->status.char_id, sd->status.name); + clif->friendlist_req(f_sd, sd->status.account_id, sd->status.char_id, sd->status.name); } @@ -12986,8 +13427,7 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) reply = RFIFOL(fd,10); #endif - if( sd->bl.id == account_id ) - {// adding oneself as friend + if( sd->bl.id == account_id ) { // adding oneself as friend return; } @@ -12996,7 +13436,7 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) return; if (reply == 0 || !( sd->friend_req == f_sd->status.char_id && f_sd->friend_req == sd->status.char_id ) ) - clif_friendslist_reqack(f_sd, sd, 1); + clif->friendslist_reqack(f_sd, sd, 1); else { int i; // Find an empty slot @@ -13004,14 +13444,14 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) if (f_sd->status.friends[i].char_id == 0) break; if (i == MAX_FRIENDS) { - clif_friendslist_reqack(f_sd, sd, 2); + clif->friendslist_reqack(f_sd, sd, 2); return; } f_sd->status.friends[i].account_id = sd->status.account_id; f_sd->status.friends[i].char_id = sd->status.char_id; memcpy(f_sd->status.friends[i].name, sd->status.name, NAME_LENGTH); - clif_friendslist_reqack(f_sd, sd, 0); + clif->friendslist_reqack(f_sd, sd, 0); if (battle_config.friend_auto_add) { // Also add f_sd to sd's friendlist. @@ -13022,14 +13462,14 @@ void clif_parse_FriendsListReply(int fd, struct map_session_data *sd) break; } if (i == MAX_FRIENDS) { - clif_friendslist_reqack(sd, f_sd, 2); + clif->friendslist_reqack(sd, f_sd, 2); return; } sd->status.friends[i].account_id = f_sd->status.account_id; sd->status.friends[i].char_id = f_sd->status.char_id; memcpy(sd->status.friends[i].name, f_sd->status.name, NAME_LENGTH); - clif_friendslist_reqack(sd, f_sd, 0); + clif->friendslist_reqack(sd, f_sd, 0); } } } @@ -13051,7 +13491,7 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) (sd->status.friends[i].char_id != char_id || sd->status.friends[i].account_id != account_id); i++); if (i == MAX_FRIENDS) { - clif_displaymessage(fd, msg_txt(672)); //"Name not found in list." + clif->message(fd, msg_txt(672)); //"Name not found in list." return; } @@ -13076,7 +13516,7 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) } else { //friend not online -- ask char server to delete from his friendlist if(chrif_removefriend(char_id,sd->status.char_id)) { // char-server offline, abort - clif_displaymessage(fd, msg_txt(673)); //"This action can't be performed at the moment. Please try again later." + clif->message(fd, msg_txt(673)); //"This action can't be performed at the moment. Please try again later." return; } } @@ -13089,7 +13529,7 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) memcpy(&sd->status.friends[j-1], &sd->status.friends[j], sizeof(sd->status.friends[0])); memset(&sd->status.friends[MAX_FRIENDS-1], 0, sizeof(sd->status.friends[MAX_FRIENDS-1])); - clif_displaymessage(fd, msg_txt(674)); //"Friend removed" + clif->message(fd, msg_txt(674)); //"Friend removed" WFIFOHEAD(fd,packet_len(0x20a)); WFIFOW(fd,0) = 0x20a; @@ -13101,8 +13541,7 @@ void clif_parse_FriendsListRemove(int fd, struct map_session_data *sd) /// /pvpinfo list (ZC_ACK_PVPPOINT). /// 0210 <char id>.L <account id>.L <win point>.L <lose point>.L <point>.L -void clif_PVPInfo(struct map_session_data* sd) -{ +void clif_PVPInfo(struct map_session_data* sd) { int fd = sd->fd; WFIFOHEAD(fd,packet_len(0x210)); @@ -13121,7 +13560,7 @@ void clif_PVPInfo(struct map_session_data* sd) void clif_parse_PVPInfo(int fd,struct map_session_data *sd) { // TODO: Is there a way to use this on an another player (char/acc id)? - clif_PVPInfo(sd); + clif->PVPInfo(sd); } @@ -13160,7 +13599,7 @@ void clif_blacksmith(struct map_session_data* sd) /// 0217 void clif_parse_Blacksmith(int fd,struct map_session_data *sd) { - clif_blacksmith(sd); + clif->blacksmith(sd); } @@ -13180,8 +13619,7 @@ void clif_fame_blacksmith(struct map_session_data *sd, int points) /// /alchemist list (ZC_ALCHEMIST_RANK). /// 021a { <name>.24B }*10 { <point>.L }*10 -void clif_alchemist(struct map_session_data* sd) -{ +void clif_alchemist(struct map_session_data* sd) { int i, fd = sd->fd; const char* name; @@ -13213,7 +13651,7 @@ void clif_alchemist(struct map_session_data* sd) /// 0218 void clif_parse_Alchemist(int fd,struct map_session_data *sd) { - clif_alchemist(sd); + clif->alchemist(sd); } @@ -13233,8 +13671,7 @@ void clif_fame_alchemist(struct map_session_data *sd, int points) /// /taekwon list (ZC_TAEKWON_RANK). /// 0226 { <name>.24B }*10 { <point>.L }*10 -void clif_taekwon(struct map_session_data* sd) -{ +void clif_taekwon(struct map_session_data* sd) { int i, fd = sd->fd; const char* name; @@ -13265,7 +13702,7 @@ void clif_taekwon(struct map_session_data* sd) /// 0225 void clif_parse_Taekwon(int fd,struct map_session_data *sd) { - clif_taekwon(sd); + clif->taekwon(sd); } @@ -13285,8 +13722,7 @@ void clif_fame_taekwon(struct map_session_data *sd, int points) /// /pk list (ZC_KILLER_RANK). /// 0238 { <name>.24B }*10 { <point>.L }*10 -void clif_ranking_pk(struct map_session_data* sd) -{ +void clif_ranking_pk(struct map_session_data* sd) { int i, fd = sd->fd; WFIFOHEAD(fd,packet_len(0x238)); @@ -13303,7 +13739,7 @@ void clif_ranking_pk(struct map_session_data* sd) /// 0237 void clif_parse_RankingPk(int fd,struct map_session_data *sd) { - clif_ranking_pk(sd); + clif->ranking_pk(sd); } @@ -13328,7 +13764,7 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd) //Are these really needed? Shouldn't they show up automatically from the feel save packet? // clif_misceffect2(&sd->bl, 0x1b0); // clif_misceffect2(&sd->bl, 0x21f); - clif_feel_info(sd, i, 0); + clif->feel_info(sd, i, 0); clif_menuskill_clear(sd); } @@ -13352,9 +13788,8 @@ void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv) /// Request to change homunculus' name (CZ_RENAME_MER). /// 0231 <name>.24B -void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) -{ - merc_hom_change_name(sd,(char*)RFIFOP(fd,2)); +void clif_parse_ChangeHomunculusName(int fd, struct map_session_data *sd) { + homun->change_name(sd,(char*)RFIFOP(fd,2)); } @@ -13368,7 +13803,7 @@ void clif_parse_HomMoveToMaster(int fd, struct map_session_data *sd) if( sd->md && sd->md->bl.id == id ) bl = &sd->md->bl; - else if( merc_is_hom_active(sd->hd) && sd->hd->bl.id == id ) + else if( homun_alive(sd->hd) && sd->hd->bl.id == id ) bl = &sd->hd->bl; // Moving Homunculus else return; @@ -13387,11 +13822,11 @@ void clif_parse_HomMoveTo(int fd, struct map_session_data *sd) struct block_list *bl = NULL; short x, y; - RFIFOPOS(fd, packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[1], &x, &y, NULL); + RFIFOPOS(fd, packet_db[RFIFOW(fd,0)].pos[1], &x, &y, NULL); if( sd->md && sd->md->bl.id == id ) bl = &sd->md->bl; // Moving Mercenary - else if( merc_is_hom_active(sd->hd) && sd->hd->bl.id == id ) + else if( homun_alive(sd->hd) && sd->hd->bl.id == id ) bl = &sd->hd->bl; // Moving Homunculus else return; @@ -13411,7 +13846,7 @@ void clif_parse_HomAttack(int fd,struct map_session_data *sd) target_id = RFIFOL(fd,6), action_type = RFIFOB(fd,10); - if( merc_is_hom_active(sd->hd) && sd->hd->bl.id == id ) + if( homun_alive(sd->hd) && sd->hd->bl.id == id ) bl = &sd->hd->bl; else if( sd->md && sd->md->bl.id == id ) bl = &sd->md->bl; @@ -13430,16 +13865,15 @@ void clif_parse_HomAttack(int fd,struct map_session_data *sd) /// 0 = homunculus information /// 1 = feed /// 2 = delete -void clif_parse_HomMenu(int fd, struct map_session_data *sd) -{ //[orn] +void clif_parse_HomMenu(int fd, struct map_session_data *sd) { //[orn] int cmd; cmd = RFIFOW(fd,0); - if(!merc_is_hom_active(sd->hd)) + if(!homun_alive(sd->hd)) return; - merc_menu(sd,RFIFOB(fd,packet_db[sd->packet_ver][cmd].pos[1])); + homun->menu(sd,RFIFOB(fd,packet_db[cmd].pos[1])); } @@ -13458,7 +13892,7 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) if (!status_revive(&sd->bl, 100, 100)) return; - clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); + clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1); pc_delitem(sd, item_position, 1, 0, 1, LOG_TYPE_CONSUME); } @@ -13470,8 +13904,7 @@ void clif_parse_AutoRevive(int fd, struct map_session_data *sd) /// <itemdefPower>.W <plusdefPower>.W <mdefPower>.W <plusmdefPower>.W /// <hitSuccessValue>.W <avoidSuccessValue>.W <plusAvoidSuccessValue>.W /// <criticalSuccessValue>.W <ASPD>.W <plusASPD>.W -void clif_check(int fd, struct map_session_data* pl_sd) -{ +void clif_check(int fd, struct map_session_data* pl_sd) { WFIFOHEAD(fd,packet_len(0x214)); WFIFOW(fd, 0) = 0x214; WFIFOB(fd, 2) = min(pl_sd->status.str, UINT8_MAX); @@ -13515,14 +13948,13 @@ void clif_parse_Check(int fd, struct map_session_data *sd) if(!pc_has_permission(sd, PC_PERM_USE_CHECK)) return; - safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]), sizeof(charname)); + safestrncpy(charname, (const char*)RFIFOP(fd,packet_db[RFIFOW(fd,0)].pos[0]), sizeof(charname)); - if( ( pl_sd = map_nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) - { + if( ( pl_sd = map_nick2sd(charname) ) == NULL || pc_get_group_level(sd) < pc_get_group_level(pl_sd) ) { return; } - clif_check(fd, pl_sd); + clif->check(fd, pl_sd); } @@ -13665,11 +14097,10 @@ void clif_Mail_refreshinbox(struct map_session_data *sd) } WFIFOSET(fd,len); - if( md->full ) - {// TODO: is this official? + if( md->full ) {// TODO: is this official? char output[100]; sprintf(output, "Inbox is full (Max %d). Delete some mails.", MAIL_MAX_INBOX); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } } @@ -13683,7 +14114,7 @@ void clif_parse_Mail_refreshinbox(int fd, struct map_session_data *sd) if( md->amount < MAIL_MAX_INBOX && (md->full || sd->mail.changed) ) intif_Mail_requestinbox(sd->status.char_id, 1); else - clif_Mail_refreshinbox(sd); + clif->mail_refreshinbox(sd); mail_removeitem(sd, 0); mail_removezeny(sd, 0); @@ -13699,14 +14130,11 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) int i, fd = sd->fd; ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if( i == MAIL_MAX_INBOX ) - { - clif_Mail_return(sd->fd, mail_id, 1); // Mail doesn't exist + if( i == MAIL_MAX_INBOX ) { + clif->mail_return(sd->fd, mail_id, 1); // Mail doesn't exist ShowWarning("clif_parse_Mail_read: char '%s' trying to read a message not the inbox.\n", sd->status.name); return; - } - else - { + } else { struct mail_message *msg = &sd->mail.inbox.msg[i]; struct item *item = &msg->item; struct item_data *data; @@ -13728,8 +14156,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) WFIFOL(fd,72) = 0; WFIFOL(fd,76) = msg->zeny; - if( item->nameid && (data = itemdb_exists(item->nameid)) != NULL ) - { + if( item->nameid && (data = itemdb_exists(item->nameid)) != NULL ) { WFIFOL(fd,80) = item->amount; WFIFOW(fd,84) = (data->view_id)?data->view_id:item->nameid; WFIFOW(fd,86) = data->type; @@ -13740,8 +14167,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) WFIFOW(fd,93) = item->card[1]; WFIFOW(fd,95) = item->card[2]; WFIFOW(fd,97) = item->card[3]; - } - else // no item, set all to zero + } else // no item, set all to zero memset(WFIFOP(fd,80), 0x00, 19); WFIFOB(fd,99) = (unsigned char)msg_len; @@ -13751,7 +14177,7 @@ void clif_Mail_read(struct map_session_data *sd, int mail_id) if (msg->status == MAIL_UNREAD) { msg->status = MAIL_READ; intif_Mail_read(mail_id); - clif_parse_Mail_refreshinbox(fd, sd); + clif->pMail_refreshinbox(fd, sd); } } } @@ -13768,7 +14194,7 @@ void clif_parse_Mail_read(int fd, struct map_session_data *sd) if( mail_invalid_operation(sd) ) return; - clif_Mail_read(sd, RFIFOL(fd,2)); + clif->mail_read(sd, RFIFOL(fd,2)); } @@ -13794,22 +14220,19 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) if( sd->mail.inbox.msg[i].zeny < 1 && (sd->mail.inbox.msg[i].item.nameid < 1 || sd->mail.inbox.msg[i].item.amount < 1) ) return; - if( sd->mail.inbox.msg[i].zeny + sd->status.zeny > MAX_ZENY ) - { - clif_Mail_getattachment(fd, 1); + if( sd->mail.inbox.msg[i].zeny + sd->status.zeny > MAX_ZENY ) { + clif->mail_getattachment(fd, 1); return; } - if( sd->mail.inbox.msg[i].item.nameid > 0 ) - { + if( sd->mail.inbox.msg[i].item.nameid > 0 ) { struct item_data *data; unsigned int weight; if ((data = itemdb_exists(sd->mail.inbox.msg[i].item.nameid)) == NULL) return; - switch( pc_checkadditem(sd, data->nameid, sd->mail.inbox.msg[i].item.amount) ) - { + switch( pc_checkadditem(sd, data->nameid, sd->mail.inbox.msg[i].item.amount) ) { case ADDITEM_NEW: fail = ( pc_inventoryblank(sd) == 0 ); break; @@ -13817,23 +14240,21 @@ void clif_parse_Mail_getattach(int fd, struct map_session_data *sd) fail = true; } - if( fail ) - { - clif_Mail_getattachment(fd, 1); + if( fail ) { + clif->mail_getattachment(fd, 1); return; } weight = data->weight * sd->mail.inbox.msg[i].item.amount; - if( sd->weight + weight > sd->max_weight ) - { - clif_Mail_getattachment(fd, 2); + if( sd->weight + weight > sd->max_weight ) { + clif->mail_getattachment(fd, 2); return; } } sd->mail.inbox.msg[i].zeny = 0; memset(&sd->mail.inbox.msg[i].item, 0, sizeof(struct item)); - clif_Mail_read(sd, mail_id); + clif->mail_read(sd, mail_id); intif_Mail_getattach(sd->status.char_id, mail_id); } @@ -13854,13 +14275,11 @@ void clif_parse_Mail_delete(int fd, struct map_session_data *sd) return; ARR_FIND(0, MAIL_MAX_INBOX, i, sd->mail.inbox.msg[i].id == mail_id); - if (i < MAIL_MAX_INBOX) - { + if (i < MAIL_MAX_INBOX) { struct mail_message *msg = &sd->mail.inbox.msg[i]; - if( (msg->item.nameid > 0 && msg->item.amount > 0) || msg->zeny > 0 ) - {// can't delete mail without removing attachment first - clif_Mail_delete(sd->fd, mail_id, 1); + if( (msg->item.nameid > 0 && msg->item.amount > 0) || msg->zeny > 0 ) {// can't delete mail without removing attachment first + clif->mail_delete(sd->fd, mail_id, 1); return; } @@ -13885,7 +14304,7 @@ void clif_parse_Mail_return(int fd, struct map_session_data *sd) if( i < MAIL_MAX_INBOX && sd->mail.inbox.msg[i].send_id != 0 ) intif_Mail_return(sd->status.char_id, mail_id); else - clif_Mail_return(sd->fd, mail_id, 1); + clif->mail_return(sd->fd, mail_id, 1); } @@ -13903,7 +14322,7 @@ void clif_parse_Mail_setattach(int fd, struct map_session_data *sd) return; flag = mail_setitem(sd, idx, amount); - clif_Mail_setattachment(fd,idx,flag); + clif->mail_setattachment(fd,idx,flag); } @@ -13941,10 +14360,9 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) return; } - if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) - { - clif_displaymessage(sd->fd,msg_txt(675)); //"Cannot send mails too fast!!." - clif_Mail_send(fd, true); // fail + if( DIFF_TICK(sd->cansendmail_tick, gettick()) > 0 ) { + clif->message(sd->fd,msg_txt(675)); //"Cannot send mails too fast!!." + clif->mail_send(fd, true); // fail return; } @@ -13953,9 +14371,8 @@ void clif_parse_Mail_send(int fd, struct map_session_data *sd) if (body_len > MAIL_BODY_LENGTH) body_len = MAIL_BODY_LENGTH; - if( !mail_setattachment(sd, &msg) ) - { // Invalid Append condition - clif_Mail_send(sd->fd, true); // fail + if( !mail_setattachment(sd, &msg) ) { // Invalid Append condition + clif->mail_send(sd->fd, true); // fail mail_removeitem(sd,0); mail_removezeny(sd,0); return; @@ -14023,8 +14440,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, WFIFOL(fd,4) = pages; WFIFOL(fd,8) = count; - for( i = 0; i < count; i++ ) - { + for( i = 0; i < count; i++ ) { memcpy(&auction, RBUFP(buf,i * len), len); k = 12 + (i * 83); @@ -14059,8 +14475,7 @@ void clif_Auction_results(struct map_session_data *sd, short count, short pages, /// result: /// 0 = success /// 1 = failure -static void clif_Auction_setitem(int fd, int index, bool fail) -{ +void clif_Auction_setitem(int fd, int index, bool fail) { WFIFOHEAD(fd,packet_len(0x256)); WFIFOW(fd,0) = 0x256; WFIFOW(fd,2) = index; @@ -14078,7 +14493,7 @@ static void clif_Auction_setitem(int fd, int index, bool fail) void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd) { if( sd->auction.amount > 0 ) - clif_additem(sd, sd->auction.index, sd->auction.amount, 0); + clif->additem(sd, sd->auction.index, sd->auction.amount, 0); sd->auction.amount = 0; } @@ -14095,34 +14510,32 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd) if( sd->auction.amount > 0 ) sd->auction.amount = 0; - if( idx < 0 || idx >= MAX_INVENTORY ) - { + if( idx < 0 || idx >= MAX_INVENTORY ) { ShowWarning("Character %s trying to set invalid item index in auctions.\n", sd->status.name); return; } - if( amount != 1 || amount > sd->status.inventory[idx].amount ) - { // By client, amount is always set to 1. Maybe this is a future implementation. + if( amount != 1 || amount > sd->status.inventory[idx].amount ) { // By client, amount is always set to 1. Maybe this is a future implementation. ShowWarning("Character %s trying to set invalid amount in auctions.\n", sd->status.name); return; } if( (item = itemdb_exists(sd->status.inventory[idx].nameid)) != NULL && !(item->type == IT_ARMOR || item->type == IT_PETARMOR || item->type == IT_WEAPON || item->type == IT_CARD || item->type == IT_ETC) ) { // Consumable or pets are not allowed - clif_Auction_setitem(sd->fd, idx, true); + clif->auction_setitem(sd->fd, idx, true); return; } if( !pc_can_give_items(sd) || sd->status.inventory[idx].expire_time || !sd->status.inventory[idx].identify || !itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd)) ) { // Quest Item or something else - clif_Auction_setitem(sd->fd, idx, true); + clif->auction_setitem(sd->fd, idx, true); return; } sd->auction.index = idx; sd->auction.amount = amount; - clif_Auction_setitem(fd, idx + 2, false); + clif->auction_setitem(fd, idx + 2, false); } /// Result from an auction action (ZC_AUCTION_RESULT). @@ -14174,28 +14587,24 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) auction.hours = RFIFOW(fd,10); // Invalid Situations... - if( sd->auction.amount < 1 ) - { + if( sd->auction.amount < 1 ) { ShowWarning("Character %s trying to register auction without item.\n", sd->status.name); return; } - if( auction.price >= auction.buynow ) - { + if( auction.price >= auction.buynow ) { ShowWarning("Character %s trying to alter auction prices.\n", sd->status.name); return; } - if( auction.hours < 1 || auction.hours > 48 ) - { + if( auction.hours < 1 || auction.hours > 48 ) { ShowWarning("Character %s trying to enter an invalid time for auction.\n", sd->status.name); return; } // Auction checks... - if( sd->status.zeny < (auction.hours * battle_config.auction_feeperhour) ) - { - clif_Auction_message(fd, 5); // You do not have enough zeny to pay the Auction Fee. + if( sd->status.zeny < (auction.hours * battle_config.auction_feeperhour) ) { + clif->auction_message(fd, 5); // You do not have enough zeny to pay the Auction Fee. return; } @@ -14214,13 +14623,13 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) if( sd->status.inventory[sd->auction.index].nameid == 0 || sd->status.inventory[sd->auction.index].amount < sd->auction.amount ) { - clif_Auction_message(fd, 2); // The auction has been canceled + clif->auction_message(fd, 2); // The auction has been canceled return; } if( (item = itemdb_exists(sd->status.inventory[sd->auction.index].nameid)) == NULL ) { // Just in case - clif_Auction_message(fd, 2); // The auction has been canceled + clif->auction_message(fd, 2); // The auction has been canceled return; } @@ -14231,7 +14640,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd) auction.timestamp = 0; if( !intif_Auction_register(&auction) ) - clif_Auction_message(fd, 4); // No Char Server? lets say something to the client + clif->auction_message(fd, 4); // No Char Server? lets say something to the client else { int zeny = auction.hours*battle_config.auction_feeperhour; @@ -14272,16 +14681,16 @@ void clif_parse_Auction_bid(int fd, struct map_session_data *sd) int bid = RFIFOL(fd,6); if( !pc_can_give_items(sd) ) { //They aren't supposed to give zeny [Inkfish] - clif_displaymessage(sd->fd, msg_txt(246)); + clif->message(sd->fd, msg_txt(246)); return; } if( bid <= 0 ) - clif_Auction_message(fd, 0); // You have failed to bid into the auction + clif->auction_message(fd, 0); // You have failed to bid into the auction else if( bid > sd->status.zeny ) - clif_Auction_message(fd, 8); // You do not have enough zeny + clif->auction_message(fd, 8); // You do not have enough zeny else if ( CheckForCharServer() ) // char server is down (bugreport:1138) - clif_Auction_message(fd, 0); // You have failed to bid into the auction + clif->auction_message(fd, 0); // You have failed to bid into the auction else { pc_payzeny(sd, bid, LOG_TYPE_AUCTION, NULL); intif_Auction_bid(sd->status.char_id, sd->status.name, auction_id, bid); @@ -14304,7 +14713,7 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) short type = RFIFOW(fd,2), page = RFIFOW(fd,32); int price = RFIFOL(fd,4); // FIXME: bug #5071 - clif_parse_Auction_cancelreg(fd, sd); + clif->pAuction_cancelreg(fd, sd); safestrncpy(search_text, (char*)RFIFOP(fd,8), sizeof(search_text)); intif_Auction_requestlist(sd->status.char_id, type, price, search_text, page); @@ -14319,7 +14728,7 @@ void clif_parse_Auction_search(int fd, struct map_session_data* sd) void clif_parse_Auction_buysell(int fd, struct map_session_data* sd) { short type = RFIFOW(fd,2) + 6; - clif_parse_Auction_cancelreg(fd, sd); + clif->pAuction_cancelreg(fd, sd); intif_Auction_requestlist(sd->status.char_id, type, 0, "", 1); } @@ -14353,8 +14762,7 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) WFIFOL(fd,8) = sd->kafraPoints; // Kafra Points #endif - for( i = 0; i < nd->u.shop.count; i++ ) - { + for( i = 0; i < nd->u.shop.count; i++ ) { struct item_data* id = itemdb_search(nd->u.shop.shop_item[i].nameid); WFIFOL(fd,offset+0+i*11) = nd->u.shop.shop_item[i].value; WFIFOL(fd,offset+4+i*11) = nd->u.shop.shop_item[i].value; // Discount Price @@ -14378,8 +14786,7 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) /// 6 = You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY) /// 7 = You can purchase up to 10 items. /// 8 = Some items could not be purchased. -void clif_cashshop_ack(struct map_session_data* sd, int error) -{ +void clif_cashshop_ack(struct map_session_data* sd, int error) { int fd = sd->fd; WFIFOHEAD(fd, packet_len(0x289)); @@ -14406,8 +14813,7 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) if( sd->state.trading || !sd->npc_shopid ) fail = 1; - else - { + else { #if PACKETVER < 20101116 short nameid = RFIFOW(fd,2); short amount = RFIFOW(fd,4); @@ -14429,7 +14835,7 @@ void clif_parse_cashshop_buy(int fd, struct map_session_data *sd) #endif } - clif_cashshop_ack(sd,fail); + clif->cashshop_ack(sd,fail); } @@ -14455,8 +14861,7 @@ void clif_Adopt_reply(struct map_session_data *sd, int type) /// Adoption confirmation (ZC_REQ_BABY). /// 01f6 <account id>.L <char id>.L <name>.B -void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *src, int p_id) -{ +void clif_Adopt_request(struct map_session_data *sd, struct map_session_data *src, int p_id) { int fd = sd->fd; WFIFOHEAD(fd,34); @@ -14474,10 +14879,9 @@ void clif_parse_Adopt_request(int fd, struct map_session_data *sd) { struct map_session_data *tsd = map_id2sd(RFIFOL(fd,2)), *p_sd = map_charid2sd(sd->status.partner_id); - if( pc_can_Adopt(sd, p_sd, tsd) ) - { + if( pc_can_Adopt(sd, p_sd, tsd) ) { tsd->adopt_invite = sd->status.account_id; - clif_Adopt_request(tsd, sd, p_sd->status.account_id); + clif->adopt_request(tsd, sd, p_sd->status.account_id); } } @@ -14524,21 +14928,15 @@ void clif_bossmapinfo(int fd, struct mob_data *md, short flag) memset(WFIFOP(fd,0),0,70); WFIFOW(fd,0) = 0x293; - if( md != NULL ) - { - if( md->bl.prev != NULL ) - { // Boss on This Map - if( flag ) - { + if( md != NULL ) { + if( md->bl.prev != NULL ) { // Boss on This Map + if( flag ) { WFIFOB(fd,2) = 1; WFIFOL(fd,3) = md->bl.x; WFIFOL(fd,7) = md->bl.y; - } - else + } else WFIFOB(fd,2) = 2; // First Time - } - else if (md->spawn_timer != INVALID_TIMER) - { // Boss is Dead + } else if (md->spawn_timer != INVALID_TIMER) { // Boss is Dead const struct TimerData * timer_data = get_timer(md->spawn_timer); unsigned int seconds; int hours, minutes; @@ -14570,9 +14968,9 @@ void clif_parse_ViewPlayerEquip(int fd, struct map_session_data* sd) return; if( tsd->status.show_equip || pc_has_permission(sd, PC_PERM_VIEW_EQUIPMENT) ) - clif_viewequip_ack(sd, tsd); + clif->viewequip_ack(sd, tsd); else - clif_viewequip_fail(sd); + clif->viewequip_fail(sd); } @@ -14587,9 +14985,19 @@ void clif_parse_EquipTick(int fd, struct map_session_data* sd) { bool flag = (bool)RFIFOL(fd,6); sd->status.show_equip = flag; - clif_equiptickack(sd, flag); + clif->equiptickack(sd, flag); } +/// Request to change party invitation tick. +/// value: +/// 0 = disabled +/// 1 = enabled +void clif_parse_PartyTick(int fd, struct map_session_data* sd) +{ + bool flag = RFIFOB(fd,6)?true:false; + sd->status.allow_party = flag; + clif->partytickack(sd, flag); +} /// Questlog System [Kevin] [Inkfish] /// @@ -14607,8 +15015,7 @@ void clif_quest_send_list(struct map_session_data * sd) WFIFOW(fd, 2) = len; WFIFOL(fd, 4) = sd->avail_quests; - for( i = 0; i < sd->avail_quests; i++ ) - { + for( i = 0; i < sd->avail_quests; i++ ) { WFIFOL(fd, i*5+8) = sd->quest_log[i].quest_id; WFIFOB(fd, i*5+12) = sd->quest_log[i].state; } @@ -14631,8 +15038,7 @@ void clif_quest_send_mission(struct map_session_data * sd) WFIFOW(fd, 2) = len; WFIFOL(fd, 4) = sd->avail_quests; - for( i = 0; i < sd->avail_quests; i++ ) - { + for( i = 0; i < sd->avail_quests; i++ ) { WFIFOL(fd, i*104+8) = sd->quest_log[i].quest_id; WFIFOL(fd, i*104+12) = sd->quest_log[i].time - quest_db[sd->quest_index[i]].time; WFIFOL(fd, i*104+16) = sd->quest_log[i].time; @@ -14667,8 +15073,7 @@ void clif_quest_add(struct map_session_data * sd, struct quest * qd, int index) WFIFOL(fd, 11) = qd->time; WFIFOW(fd, 15) = quest_db[index].num_objectives; - for( i = 0; i < quest_db[index].num_objectives; i++ ) - { + for( i = 0; i < quest_db[index].num_objectives; i++ ) { WFIFOL(fd, i*30+17) = quest_db[index].mob[i]; WFIFOW(fd, i*30+21) = qd->count[i]; mob = mob_db(quest_db[index].mob[i]); @@ -14705,8 +15110,7 @@ void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd WFIFOW(fd, 2) = len; WFIFOW(fd, 4) = quest_db[index].num_objectives; - for( i = 0; i < quest_db[index].num_objectives; i++ ) - { + for( i = 0; i < quest_db[index].num_objectives; i++ ) { WFIFOL(fd, i*12+6) = qd->quest_id; WFIFOL(fd, i*12+10) = quest_db[index].mob[i]; WFIFOW(fd, i*12+14) = quest_db[index].count[i]; @@ -14785,8 +15189,7 @@ void clif_mercenary_updatestatus(struct map_session_data *sd, int type) WFIFOHEAD(fd,packet_len(0x2a2)); WFIFOW(fd,0) = 0x2a2; WFIFOW(fd,2) = type; - switch( type ) - { + switch( type ) { case SP_ATK1: { int atk = rnd()%(status->rhw.atk2 - status->rhw.atk + 1) + status->rhw.atk; @@ -14902,11 +15305,11 @@ void clif_mercenary_skillblock(struct map_session_data *sd) continue; j = id - MC_SKILLBASE; WFIFOW(fd,len) = id; - WFIFOL(fd,len+2) = skill_get_inf(id); + WFIFOL(fd,len+2) = skill->get_inf(id); WFIFOW(fd,len+6) = md->db->skill[j].lv; - WFIFOW(fd,len+8) = skill_get_sp(id, md->db->skill[j].lv); - WFIFOW(fd,len+10) = skill_get_range2(&md->bl, id, md->db->skill[j].lv); - safestrncpy((char*)WFIFOP(fd,len+12), skill_get_name(id), NAME_LENGTH); + WFIFOW(fd,len+8) = skill->get_sp(id, md->db->skill[j].lv); + WFIFOW(fd,len+10) = skill->get_range2(&md->bl, id, md->db->skill[j].lv); + safestrncpy((char*)WFIFOP(fd,len+12), skill->get_name(id), NAME_LENGTH); WFIFOB(fd,len+36) = 0; // Skillable for Mercenary? len += 37; } @@ -14938,7 +15341,7 @@ void clif_parse_mercenary_action(int fd, struct map_session_data* sd) /// 3 = Your mercenary soldier has ran away. void clif_mercenary_message(struct map_session_data* sd, int message) { - clif_msg(sd, 1266 + message); + clif->msg(sd, 1266 + message); } @@ -15004,7 +15407,7 @@ void clif_bg_hp(struct map_session_data *sd) WBUFW(buf,32) = sd->battle_status.max_hp; } - clif_send(buf, packet_len(cmd), &sd->bl, BG_AREA_WOS); + clif->send(buf, packet_len(cmd), &sd->bl, BG_AREA_WOS); } @@ -15022,7 +15425,7 @@ void clif_bg_xy(struct map_session_data *sd) WBUFW(buf,32)=sd->bl.x; WBUFW(buf,34)=sd->bl.y; - clif_send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); + clif->send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); } void clif_bg_xy_remove(struct map_session_data *sd) @@ -15037,7 +15440,7 @@ void clif_bg_xy_remove(struct map_session_data *sd) WBUFW(buf,32)=-1; WBUFW(buf,34)=-1; - clif_send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); + clif->send(buf, packet_len(0x2df), &sd->bl, BG_SAMEMAP_WOS); } @@ -15057,7 +15460,7 @@ void clif_bg_message(struct battleground_data *bg, int src_id, const char *name, WBUFL(buf,4) = src_id; memcpy(WBUFP(buf,8), name, NAME_LENGTH); memcpy(WBUFP(buf,32), mes, len); - clif_send(buf,WBUFW(buf,2), &sd->bl, BG); + clif->send(buf,WBUFW(buf,2), &sd->bl, BG); if( buf ) aFree(buf); @@ -15074,17 +15477,16 @@ void clif_parse_BattleChat(int fd, struct map_session_data* sd) char *name, *message; int namelen, messagelen; - if( !clif_process_message(sd, 0, &name, &namelen, &message, &messagelen) ) + if( !clif->process_message(sd, 0, &name, &namelen, &message, &messagelen) ) return; - if( is_atcommand(fd, sd, message, 1) ) + if( atcommand->parse(fd, sd, message, 1) ) return; if( sd->sc.data[SC_BERSERK] || sd->sc.data[SC__BLOODYLUST] || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) ) return; - if( battle_config.min_chat_delay ) - { + if( battle_config.min_chat_delay ) { if( DIFF_TICK(sd->cantalk_tick, gettick()) > 0 ) return; sd->cantalk_tick = gettick() + battle_config.min_chat_delay; @@ -15108,7 +15510,7 @@ void clif_bg_updatescore(int16 m) WBUFW(buf,0) = 0x2de; WBUFW(buf,2) = map[m].bgscore_lion; WBUFW(buf,4) = map[m].bgscore_eagle; - clif_send(buf,packet_len(0x2de),&bl,ALL_SAMEMAP); + clif->send(buf,packet_len(0x2de),&bl,ALL_SAMEMAP); } void clif_bg_updatescore_single(struct map_session_data *sd) @@ -15136,7 +15538,7 @@ void clif_sendbgemblem_area(struct map_session_data *sd) WBUFL(buf,2) = sd->bl.id; safestrncpy((char*)WBUFP(buf,6), sd->status.name, NAME_LENGTH); // name don't show in screen. WBUFW(buf,30) = sd->bg_id; - clif_send(buf,packet_len(0x2dd), &sd->bl, AREA); + clif->send(buf,packet_len(0x2dd), &sd->bl, AREA); } void clif_sendbgemblem_single(int fd, struct map_session_data *sd) @@ -15161,7 +15563,7 @@ void clif_font(struct map_session_data *sd) WBUFW(buf,0) = 0x2ef; WBUFL(buf,2) = sd->bl.id; WBUFW(buf,6) = sd->user_font; - clif_send(buf, packet_len(0x2ef), &sd->bl, AREA); + clif->send(buf, packet_len(0x2ef), &sd->bl, AREA); #endif } @@ -15178,79 +15580,73 @@ int clif_instance(int instance_id, int type, int flag) if( (p = party_search(instance[instance_id].party_id)) == NULL || (sd = party_getavailablesd(p)) == NULL ) return 0; - switch( type ) - { - case 1: - // S 0x2cb <Instance name>.61B <Standby Position>.W - // Required to start the instancing information window on Client - // This window re-appear each "refresh" of client automatically until type 4 is send to client. - WBUFW(buf,0) = 0x02CB; - memcpy(WBUFP(buf,2),instance[instance_id].name,INSTANCE_NAME_LENGTH); - WBUFW(buf,63) = flag; - clif_send(buf,packet_len(0x02CB),&sd->bl,PARTY); - break; - case 2: - // S 0x2cc <Standby Position>.W - // To announce Instancing queue creation if no maps available - WBUFW(buf,0) = 0x02CC; - WBUFW(buf,2) = flag; - clif_send(buf,packet_len(0x02CC),&sd->bl,PARTY); - break; - case 3: - case 4: - // S 0x2cd <Instance Name>.61B <Instance Remaining Time>.L <Instance Noplayers close time>.L - WBUFW(buf,0) = 0x02CD; - memcpy(WBUFP(buf,2),instance[instance_id].name,61); - if( type == 3 ) - { - WBUFL(buf,63) = (uint32)instance[instance_id].progress_timeout; - WBUFL(buf,67) = 0; - } - else - { - WBUFL(buf,63) = 0; - WBUFL(buf,67) = (uint32)instance[instance_id].idle_timeout; - } - clif_send(buf,packet_len(0x02CD),&sd->bl,PARTY); - break; - case 5: - // S 0x2ce <Message ID>.L - // 0 = Notification (EnterLimitDate update?) - // 1 = The Memorial Dungeon expired; it has been destroyed - // 2 = The Memorial Dungeon's entry time limit expired; it has been destroyed - // 3 = The Memorial Dungeon has been removed. - // 4 = Create failure (removes the instance window) - WBUFW(buf,0) = 0x02CE; - WBUFL(buf,2) = flag; - //WBUFL(buf,6) = EnterLimitDate; - clif_send(buf,packet_len(0x02CE),&sd->bl,PARTY); - break; + switch( type ) { + case 1: + // S 0x2cb <Instance name>.61B <Standby Position>.W + // Required to start the instancing information window on Client + // This window re-appear each "refresh" of client automatically until type 4 is send to client. + WBUFW(buf,0) = 0x02CB; + memcpy(WBUFP(buf,2),instance[instance_id].name,INSTANCE_NAME_LENGTH); + WBUFW(buf,63) = flag; + clif->send(buf,packet_len(0x02CB),&sd->bl,PARTY); + break; + case 2: + // S 0x2cc <Standby Position>.W + // To announce Instancing queue creation if no maps available + WBUFW(buf,0) = 0x02CC; + WBUFW(buf,2) = flag; + clif->send(buf,packet_len(0x02CC),&sd->bl,PARTY); + break; + case 3: + case 4: + // S 0x2cd <Instance Name>.61B <Instance Remaining Time>.L <Instance Noplayers close time>.L + WBUFW(buf,0) = 0x02CD; + memcpy(WBUFP(buf,2),instance[instance_id].name,61); + if( type == 3 ) + { + WBUFL(buf,63) = (uint32)instance[instance_id].progress_timeout; + WBUFL(buf,67) = 0; + } + else + { + WBUFL(buf,63) = 0; + WBUFL(buf,67) = (uint32)instance[instance_id].idle_timeout; + } + clif->send(buf,packet_len(0x02CD),&sd->bl,PARTY); + break; + case 5: + // S 0x2ce <Message ID>.L + // 0 = Notification (EnterLimitDate update?) + // 1 = The Memorial Dungeon expired; it has been destroyed + // 2 = The Memorial Dungeon's entry time limit expired; it has been destroyed + // 3 = The Memorial Dungeon has been removed. + // 4 = Create failure (removes the instance window) + WBUFW(buf,0) = 0x02CE; + WBUFL(buf,2) = flag; + //WBUFL(buf,6) = EnterLimitDate; + clif->send(buf,packet_len(0x02CE),&sd->bl,PARTY); + break; } return 0; } void clif_instance_join(int fd, int instance_id) { - if( instance[instance_id].idle_timer != INVALID_TIMER ) - { + if( instance[instance_id].idle_timer != INVALID_TIMER ) { WFIFOHEAD(fd,packet_len(0x02CD)); WFIFOW(fd,0) = 0x02CD; memcpy(WFIFOP(fd,2),instance[instance_id].name,61); WFIFOL(fd,63) = 0; WFIFOL(fd,67) = (uint32)instance[instance_id].idle_timeout; WFIFOSET(fd,packet_len(0x02CD)); - } - else if( instance[instance_id].progress_timer != INVALID_TIMER ) - { + } else if( instance[instance_id].progress_timer != INVALID_TIMER ) { WFIFOHEAD(fd,packet_len(0x02CD)); WFIFOW(fd,0) = 0x02CD; memcpy(WFIFOP(fd,2),instance[instance_id].name,61); WFIFOL(fd,63) = (uint32)instance[instance_id].progress_timeout;; WFIFOL(fd,67) = 0; WFIFOSET(fd,packet_len(0x02CD)); - } - else - { + } else { WFIFOHEAD(fd,packet_len(0x02CB)); WFIFOW(fd,0) = 0x02CB; memcpy(WFIFOP(fd,2),instance[instance_id].name,61); @@ -15282,10 +15678,10 @@ void clif_party_show_picker(struct map_session_data * sd, struct item * item_dat WBUFB(buf,8) = item_data->identify; WBUFB(buf,9) = item_data->attribute; WBUFB(buf,10) = item_data->refine; - clif_addcards(WBUFP(buf,11), item_data); + clif->addcards(WBUFP(buf,11), item_data); WBUFW(buf,19) = id->equip; // equip location WBUFB(buf,21) = itemtype(id->type); // item type - clif_send(buf, packet_len(0x2b8), &sd->bl, PARTY_SAMEMAP_WOS); + clif->send(buf, packet_len(0x2b8), &sd->bl, PARTY_SAMEMAP_WOS); #endif } @@ -15347,7 +15743,7 @@ void clif_showdigit(struct map_session_data* sd, unsigned char type, int value) /// Graffiti. void clif_parse_LessEffect(int fd, struct map_session_data* sd) { - int isLess = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + int isLess = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); sd->state.lesseffect = ( isLess != 0 ); } @@ -15374,11 +15770,11 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) { switch( type ) { case 0: // Change Material - skill_changematerial(sd,n,item_list); + skill->changematerial(sd,n,item_list); break; case 1: // Level 1: Pure to Rough case 2: // Level 2: Rough to Pure - skill_elementalanalysis(sd,n,type,item_list); + skill->elementalanalysis(sd,n,type,item_list); break; } clif_menuskill_clear(sd); @@ -15462,15 +15858,14 @@ void clif_buyingstore_open(struct map_session_data* sd) /// result: /// 0 = cancel /// 1 = open -static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) -{ +void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) { const unsigned int blocksize = 8; uint8* itemlist; char storename[MESSAGE_SIZE]; unsigned char result; int zenylimit; unsigned int count, packet_len; - struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + struct s_packet_db* info = &packet_db[RFIFOW(fd,0)]; packet_len = RFIFOW(fd,info->pos[0]); @@ -15496,7 +15891,7 @@ static void clif_parse_ReqOpenBuyingStore(int fd, struct map_session_data* sd) } count = packet_len/blocksize; - buyingstore_create(sd, zenylimit, result, storename, itemlist, count); + buyingstore->create(sd, zenylimit, result, storename, itemlist, count); } @@ -15554,7 +15949,7 @@ void clif_buyingstore_entry(struct map_session_data* sd) WBUFL(buf,2) = sd->bl.id; memcpy(WBUFP(buf,6), sd->message, MESSAGE_SIZE); - clif_send(buf, packet_len(0x814), &sd->bl, AREA_WOS); + clif->send(buf, packet_len(0x814), &sd->bl, AREA_WOS); } void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) { @@ -15570,9 +15965,8 @@ void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_sessi /// Request to close own buying store (CZ_REQ_CLOSE_BUYING_STORE). /// 0815 -static void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) -{ - buyingstore_close(sd); +void clif_parse_ReqCloseBuyingStore(int fd, struct map_session_data* sd) { + buyingstore->close(sd); } @@ -15585,7 +15979,7 @@ void clif_buyingstore_disappear_entry(struct map_session_data* sd) WBUFW(buf,0) = 0x816; WBUFL(buf,2) = sd->bl.id; - clif_send(buf, packet_len(0x816), &sd->bl, AREA_WOS); + clif->send(buf, packet_len(0x816), &sd->bl, AREA_WOS); } void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd) { @@ -15600,13 +15994,13 @@ void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct /// Request to open someone else's buying store (CZ_REQ_CLICK_TO_BUYING_STORE). /// 0817 <account id>.L -static void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd) +void clif_parse_ReqClickBuyingStore(int fd, struct map_session_data* sd) { int account_id; - account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); + account_id = RFIFOL(fd,packet_db[RFIFOW(fd,0)].pos[0]); - buyingstore_open(sd, account_id); + buyingstore->open(sd, account_id); } @@ -15638,13 +16032,12 @@ void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_d /// Request to sell items to a buying store (CZ_REQ_TRADE_BUYING_STORE). /// 0819 <packet len>.W <account id>.L <store id>.L { <index>.W <name id>.W <amount>.W }* -static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) -{ +void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) { const unsigned int blocksize = 6; uint8* itemlist; int account_id; unsigned int count, packet_len, buyer_id; - struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + struct s_packet_db* info = &packet_db[RFIFOW(fd,0)]; packet_len = RFIFOW(fd,info->pos[0]); @@ -15663,12 +16056,12 @@ static void clif_parse_ReqTradeBuyingStore(int fd, struct map_session_data* sd) if( packet_len%blocksize ) { - ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%d, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); + ShowError("clif_parse_ReqTradeBuyingStore: Unexpected item list size %u (account_id=%d, buyer_id=%u, block size=%u)\n", packet_len, sd->bl.id, account_id, blocksize); return; } count = packet_len/blocksize; - buyingstore_trade(sd, account_id, buyer_id, itemlist, count); + buyingstore->trade(sd, account_id, buyer_id, itemlist, count); } @@ -15754,14 +16147,13 @@ void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short res /// NOTE: The client determines the item ids by specifying a name and optionally, /// amount of card slots. If the client does not know about the item it /// cannot be searched. -static void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) -{ +void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) { const unsigned int blocksize = 2; const uint8* itemlist; const uint8* cardlist; unsigned char type; unsigned int min_price, max_price, packet_len, count, item_count, card_count; - struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + struct s_packet_db* info = &packet_db[RFIFOW(fd,0)]; packet_len = RFIFOW(fd,info->pos[0]); @@ -15795,7 +16187,7 @@ static void clif_parse_SearchStoreInfo(int fd, struct map_session_data* sd) return; } - searchstore_query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count); + searchstore->query(sd, type, min_price, max_price, (const unsigned short*)itemlist, item_count, (const unsigned short*)cardlist, card_count); } @@ -15820,11 +16212,10 @@ void clif_search_store_info_ack(struct map_session_data* sd) WFIFOW(fd,0) = 0x836; WFIFOW(fd,2) = 7+(end-start)*blocksize; WFIFOB(fd,4) = !sd->searchstore.pages; - WFIFOB(fd,5) = searchstore_querynext(sd); + WFIFOB(fd,5) = searchstore->querynext(sd); WFIFOB(fd,6) = (unsigned char)min(sd->searchstore.uses, UINT8_MAX); - for( i = start; i < end; i++ ) - { + for( i = start; i < end; i++ ) { struct s_search_store_info_item* ssitem = &sd->searchstore.items[i]; struct item it; @@ -15843,7 +16234,7 @@ void clif_search_store_info_ack(struct map_session_data* sd) it.nameid = ssitem->nameid; it.amount = ssitem->amount; - clif_addcards(WFIFOP(fd,i*blocksize+25+MESSAGE_SIZE), &it); + clif->addcards(WFIFOP(fd,i*blocksize+25+MESSAGE_SIZE), &it); } WFIFOSET(fd,WFIFOW(fd,2)); @@ -15871,9 +16262,9 @@ void clif_search_store_info_failed(struct map_session_data* sd, unsigned char re /// Request to display next page of results (CZ_SEARCH_STORE_INFO_NEXT_PAGE). /// 0838 -static void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) +void clif_parse_SearchStoreInfoNextPage(int fd, struct map_session_data* sd) { - searchstore_next(sd); + searchstore->next(sd); } @@ -15898,25 +16289,25 @@ void clif_open_search_store_info(struct map_session_data* sd) /// Request to close the store search window (CZ_CLOSE_SEARCH_STORE_INFO). /// 083b -static void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) +void clif_parse_CloseSearchStoreInfo(int fd, struct map_session_data* sd) { - searchstore_close(sd); + searchstore->close(sd); } /// Request to invoke catalog effect on a store from search results (CZ_SSILIST_ITEM_CLICK). /// 083c <account id>.L <store id>.L <nameid>.W -static void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd) +void clif_parse_SearchStoreInfoListItemClick(int fd, struct map_session_data* sd) { unsigned short nameid; int account_id, store_id; - struct s_packet_db* info = &packet_db[sd->packet_ver][RFIFOW(fd,0)]; + struct s_packet_db* info = &packet_db[RFIFOW(fd,0)]; account_id = RFIFOL(fd,info->pos[0]); store_id = RFIFOL(fd,info->pos[1]); nameid = RFIFOW(fd,info->pos[2]); - searchstore_click(sd, account_id, store_id, nameid); + searchstore->click(sd, account_id, store_id, nameid); } @@ -15935,29 +16326,20 @@ void clif_search_store_info_click_ack(struct map_session_data* sd, short x, shor /// Parse function for packet debugging. -void clif_parse_debug(int fd,struct map_session_data *sd) -{ +void clif_parse_debug(int fd,struct map_session_data *sd) { int cmd, packet_len; // clif_parse ensures, that there is at least 2 bytes of data cmd = RFIFOW(fd,0); - if( sd ) - { - packet_len = packet_db[sd->packet_ver][cmd].len; + if( sd ) { + packet_len = packet_db[cmd].len; - if( packet_len == 0 ) - {// unknown - packet_len = RFIFOREST(fd); - } - else if( packet_len == -1 ) - {// variable length + if( packet_len == -1 ) {// variable length packet_len = RFIFOW(fd,2); // clif_parse ensures, that this amount of data is already received } ShowDebug("Packet debug of 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); - } - else - { + } else { packet_len = RFIFOREST(fd); ShowDebug("Packet debug of 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); } @@ -15980,7 +16362,7 @@ int clif_elementalconverter_list(struct map_session_data *sd) { WFIFOW(fd, 0)=0x1ad; for(i=0,c=0;i<MAX_SKILL_PRODUCE_DB;i++){ - if( skill_can_produce_mix(sd,skill_produce_db[i].nameid,23, 1) ){ + if( skill->can_produce_mix(sd,skill_produce_db[i].nameid,23, 1) ){ if((view = itemdb_viewid(skill_produce_db[i].nameid)) > 0) WFIFOW(fd,c*2+ 4)= view; else @@ -16008,7 +16390,7 @@ void clif_millenniumshield(struct map_session_data *sd, short shields ) { WBUFL(buf,2) = sd->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),&sd->bl,AREA); #endif } /** @@ -16046,7 +16428,7 @@ int clif_spellbook_list(struct map_session_data *sd) } else{ status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK, 0); + clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK, 0); } return 1; @@ -16081,7 +16463,7 @@ int clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x, WFIFOW(fd,2) = c * 2 + 4; WFIFOSET(fd, WFIFOW(fd, 2)); } else { - clif_skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); return 0; } @@ -16115,7 +16497,7 @@ int clif_poison_list(struct map_session_data *sd, uint16 skill_lv) { WFIFOW(fd,2) = c * 2 + 4; WFIFOSET(fd, WFIFOW(fd, 2)); } else { - clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_GUILLONTINE_POISON,0); + clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_GUILLONTINE_POISON,0); return 0; } @@ -16134,7 +16516,7 @@ int clif_autoshadowspell_list(struct map_session_data *sd) { WFIFOW(fd,0) = 0x442; for( i = 0, c = 0; i < MAX_SKILL; i++ ) if( sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].id > 0 && - sd->status.skill[i].id < GS_GLITTERING && skill_get_type(sd->status.skill[i].id) == BF_MAGIC ) + sd->status.skill[i].id < GS_GLITTERING && skill->get_type(sd->status.skill[i].id) == BF_MAGIC ) { // Can't auto cast both Extended class and 3rd class skills. WFIFOW(fd,8+c*2) = sd->status.skill[i].id; c++; @@ -16148,7 +16530,7 @@ int clif_autoshadowspell_list(struct map_session_data *sd) { sd->menuskill_val = c; } else { status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); - clif_skill_fail(sd,SC_AUTOSHADOWSPELL,USESKILL_FAIL_IMITATION_SKILL_NONE,0); + clif->skill_fail(sd,SC_AUTOSHADOWSPELL,USESKILL_FAIL_IMITATION_SKILL_NONE,0); } return 1; @@ -16182,40 +16564,6 @@ int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uin return 1; } -/** - * Sends a new status without a tick (currently used by the new mounts) - **/ -int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3) { - unsigned char buf[32]; - - nullpo_ret(bl); - - WBUFW(buf,0)=0x043f; - WBUFW(buf,2)=type; - WBUFL(buf,4)=bl->id; - WBUFB(buf,8)=flag; - WBUFL(buf,9) = 0; - WBUFL(buf,13) = val1; - WBUFL(buf,17) = val2; - WBUFL(buf,21) = val3; - - clif_send(buf,packet_len(0x043f),bl,AREA); - return 0; -} -//Notifies FD of ID's type -int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3) { - WFIFOHEAD(fd, packet_len(0x043f)); - WFIFOW(fd,0)=0x043f; - WFIFOW(fd,2)=type; - WFIFOL(fd,4)=id; - WFIFOB(fd,8)=flag; - WFIFOL(fd,9) = 0; - WFIFOL(fd,13) = val1; - WFIFOL(fd,17) = val2; - WFIFOL(fd,21) = val3; - WFIFOSET(fd, packet_len(0x043f)); - return 0; -} // msgstringtable.txt // 0x291 <line>.W void clif_msgtable(int fd, int line) { @@ -16246,12 +16594,12 @@ void clif_parse_SkillSelectMenu(int fd, struct map_session_data *sd) { return; if( pc_istrading(sd) ) { - clif_skill_fail(sd,sd->ud.skill_id,0,0); + clif->skill_fail(sd,sd->ud.skill_id,0,0); clif_menuskill_clear(sd); return; } - skill_select_menu(sd,RFIFOW(fd,6)); + skill->select_menu(sd,RFIFOW(fd,6)); clif_menuskill_clear(sd); } @@ -16268,7 +16616,7 @@ void clif_talisman(struct map_session_data *sd,short type) WBUFL(buf,2)=sd->bl.id; WBUFW(buf,6)=type; WBUFW(buf,8)=sd->talisman[type]; - clif_send(buf,packet_len(0x08cf),&sd->bl,AREA); + clif->send(buf,packet_len(0x08cf),&sd->bl,AREA); } /// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE] /// 0907 <index>.W @@ -16298,11 +16646,80 @@ void clif_parse_MoveItem(int fd, struct map_session_data *sd) { else return;/* nothing to do. */ - clif_favorite_item(sd, index); + clif->favorite_item(sd, index); #endif } - - +/* [Ind/Hercules] */ +void clif_cashshop_db(void) { + config_t cashshop_conf; + config_setting_t *cashshop = NULL; + const char *config_filename = "db/cashshop_db.conf"; // FIXME hardcoded name + int i; + for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { + CREATE(clif->cs.data[i], struct hCSData *, 1); + clif->cs.item_count[i] = 0; + } + + if (conf_read_file(&cashshop_conf, config_filename)) { + ShowError("can't read %s\n", config_filename); + return; + } + + cashshop = config_lookup(&cashshop_conf, "cash_shop"); + + if (cashshop != NULL) { + config_setting_t *cats = config_setting_get_elem(cashshop, 0); + config_setting_t *cat; + int k, item_count_t = 0; + + for(i = 0; i < CASHSHOP_TAB_MAX; i++) { + char entry_name[10]; + + sprintf(entry_name,"cat_%d",i); + + if( (cat = config_setting_get_member(cats, entry_name)) != NULL ) { + int item_count = config_setting_length(cat); + + for(k = 0; k < item_count; k++) { + config_setting_t *entry = config_setting_get_elem(cat,k); + const char *name = config_setting_name(entry); + int price = config_setting_get_int(entry); + struct item_data * data = NULL; + + if( price < 1 ) { + ShowWarning("cashshop_db: unsupported price '%d' for entry named '%s' in category '%s'\n", price, name, entry_name); + continue; + } + + if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) { + if( !( data = itemdb_exists(atoi(name+2))) ) { + ShowWarning("cashshop_db: unknown item id '%s' in category '%s'\n", name+2, entry_name); + continue; + } + } else { + if( !( data = itemdb_searchname(name) ) ) { + ShowWarning("cashshop_db: unknown item name '%s' in category '%s'\n", name, entry_name); + continue; + } + } + + + RECREATE(clif->cs.data[i], struct hCSData *, ++clif->cs.item_count[i]); + CREATE(clif->cs.data[i][ clif->cs.item_count[i] - 1 ], struct hCSData , 1); + + clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->id = data->nameid; + clif->cs.data[i][ clif->cs.item_count[i] - 1 ]->price = price; + item_count_t++; + } + } else { + ShowError("cashshop_db: category '%s' (%d) not found!!\n",entry_name,i); + } + } + + ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename); + config_destroy(&cashshop_conf); + } +} /// Items that are in favorite tab of inventory (ZC_ITEM_FAVORITE). /// 0900 <index>.W <favorite>.B void clif_favorite_item(struct map_session_data* sd, unsigned short index) { @@ -16323,776 +16740,387 @@ void clif_snap( struct block_list *bl, short x, short y ) { WBUFW(buf,6) = x; WBUFW(buf,8) = y; - clif_send(buf,packet_len(0x8d2),bl,AREA); + clif->send(buf,packet_len(0x8d2),bl,AREA); } -void clif_monster_hp_bar( struct mob_data* md, int fd ) { -#if PACKETVER >= 20120404 - WFIFOHEAD(fd,packet_len(0x977)); +void clif_monster_hp_bar( struct mob_data* md, struct map_session_data *sd ) { + struct packet_monster_hp p; + + p.PacketType = monsterhpType; + p.GID = md->bl.id; + p.HP = md->status.hp; + p.MaxHP = md->status.max_hp; + + clif->send(&p,sizeof(p),&sd->bl,SELF); +} +/* [Ind/Hercules] placeholder for unsupported incoming packets (avoids server disconnecting client) */ +void __attribute__ ((unused)) clif_parse_dull(int fd,struct map_session_data *sd) { + return; +} - WFIFOW(fd,0) = 0x977; - WFIFOL(fd,2) = md->bl.id; - WFIFOL(fd,6) = md->status.hp; - WFIFOL(fd,10) = md->status.max_hp; +void clif_parse_CashShopOpen(int fd, struct map_session_data *sd) { + WFIFOHEAD(fd, 10); + WFIFOW(fd, 0) = 0x845; + WFIFOL(fd, 2) = sd->cashPoints; //[Ryuuzaki] - switched positions to reflect proper values + WFIFOL(fd, 6) = sd->kafraPoints; + WFIFOSET(fd, 10); +} + +void clif_parse_CashShopClose(int fd, struct map_session_data *sd) { + /* TODO apply some state tracking */ +} - WFIFOSET(fd,packet_len(0x977)); +void clif_parse_CashShopSchedule(int fd, struct map_session_data *sd) { + int i, j = 0; + + for( i = 0; i < CASHSHOP_TAB_MAX; i++ ) { + WFIFOHEAD(fd, 8 + ( clif->cs.item_count[i] * 6 ) ); + WFIFOW(fd, 0) = 0x8ca; + WFIFOW(fd, 2) = 8 + ( clif->cs.item_count[i] * 6 ); + WFIFOW(fd, 4) = clif->cs.item_count[i]; + WFIFOW(fd, 6) = i; + + for( j = 0; j < clif->cs.item_count[i]; j++ ) { + WFIFOW(fd, 8 + ( 6 * j ) ) = clif->cs.data[i][j]->id; + WFIFOL(fd, 10 + ( 6 * j ) ) = clif->cs.data[i][j]->price; + } + + WFIFOSET(fd, 8 + ( clif->cs.item_count[i] * 6 )); + } +} +void clif_parse_CashShopBuy(int fd, struct map_session_data *sd) { + unsigned short limit = RFIFOW(fd, 4), i, j; + unsigned int kafra_pay = RFIFOL(fd, 6);// [Ryuuzaki] - These are free cash points (strangely #CASH = main cash curreny for us, confusing) + + for(i = 0; i < limit; i++) { + int qty = RFIFOL(fd, 14 + ( i * 10 )); + int id = RFIFOL(fd, 10 + ( i * 10 )); + short tab = RFIFOW(fd, 18 + ( i * 10 )); + enum CASH_SHOP_BUY_RESULT result = CSBR_UNKNOWN; + + if( tab < 0 || tab > CASHSHOP_TAB_MAX ) + continue; + + for( j = 0; j < clif->cs.item_count[tab]; j++ ) { + if( clif->cs.data[tab][j]->id == id ) + break; + } + if( j < clif->cs.item_count[tab] ) { + struct item_data *data; + if( sd->kafraPoints < kafra_pay ) { + result = CSBR_SHORTTAGE_CASH; + } else if( (sd->cashPoints+kafra_pay) < (clif->cs.data[tab][j]->price * qty) ) { + result = CSBR_SHORTTAGE_CASH; + } else if ( !( data = itemdb_exists(clif->cs.data[tab][j]->id) ) ) { + result = CSBR_UNKONWN_ITEM; + } else { + struct item item_tmp; + int k, get_count; + + get_count = qty; + + if (!itemdb_isstackable2(data)) + get_count = 1; + + pc_paycash(sd, clif->cs.data[tab][j]->price * qty, kafra_pay);// [Ryuuzaki] + for (k = 0; k < qty; k += get_count) { + if (!pet_create_egg(sd, data->nameid)) { + memset(&item_tmp, 0, sizeof(item_tmp)); + item_tmp.nameid = data->nameid; + item_tmp.identify = 1; + + switch (pc_additem(sd, &item_tmp, get_count, LOG_TYPE_NPC)) { + case 0: + result = CSBR_SUCCESS; + break; + case 1: + result = CSBR_EACHITEM_OVERCOUNT; + break; + case 2: + result = CSBR_INVENTORY_WEIGHT; + break; + case 4: + result = CSBR_INVENTORY_ITEMCNT; + break; + case 5: + result = CSBR_EACHITEM_OVERCOUNT; + break; + case 7: + result = CSBR_RUNE_OVERCOUNT; + break; + } + + if( result != CSBR_SUCCESS ) + pc_getcash(sd, clif->cs.data[tab][j]->price * get_count,0); + } + } + } + } else { + result = CSBR_UNKONWN_ITEM; + } + + WFIFOHEAD(fd, 16); + WFIFOW(fd, 0) = 0x849; + WFIFOL(fd, 2) = id; + WFIFOW(fd, 6) = result;/* result */ + WFIFOL(fd, 8) = sd->cashPoints;/* current cash point */ + WFIFOL(fd, 12) = sd->kafraPoints;// [Ryuuzaki] + WFIFOSET(fd, 16); + + } +} +/* [Ind/Hercules] */ +void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) { + short tab = RFIFOW(fd, 2); + int j; + + if( tab < 0 || tab > CASHSHOP_TAB_MAX ) + return; + + WFIFOHEAD(fd, 10 + ( clif->cs.item_count[tab] * 6 ) ); + WFIFOW(fd, 0) = 0x8c0; + WFIFOW(fd, 2) = 10 + ( clif->cs.item_count[tab] * 6 ); + WFIFOL(fd, 4) = tab; + WFIFOW(fd, 8) = clif->cs.item_count[tab]; + + for( j = 0; j < clif->cs.item_count[tab]; j++ ) { + WFIFOW(fd, 10 + ( 6 * j ) ) = clif->cs.data[tab][j]->id; + WFIFOL(fd, 12 + ( 6 * j ) ) = clif->cs.data[tab][j]->price; + } + + WFIFOSET(fd, 10 + ( clif->cs.item_count[tab] * 6 )); +} +/* [Ind/Hercules] */ +void clif_maptypeproperty2(struct block_list *bl,enum send_target t) { +#if PACKETVER >= 20121010 + struct packet_maptypeproperty2 p; + + p.PacketType = maptypeproperty2Type; + p.type = 0x28; + p.flag.usecart = 1; + p.flag.party = 1; + p.flag.guild = 1; + p.flag.siege = map_flag_gvg2(bl->m) ? 1: 0; + p.flag.mineffect = 1; + p.flag.nolockon = 0; + p.flag.countpk = map[bl->m].flag.pvp ? 1 : 0; + p.flag.nopartyformation = 0; + p.flag.noitemconsumption = 0; + p.flag.summonstarmiracle = 0; + p.flag.bg = map[bl->m].flag.battleground ? 1 : 0; + + clif->send(&p,sizeof(p),bl,t); #endif } +void clif_status_change2(struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3) { + struct packet_status_change2 p; + + p.PacketType = status_change2Type; + p.index = type; + p.AID = tid; + p.state = 1; + p.Left = -1;// officially its 9999 but -1 is a explicit "no-duration" which behaves best [Ind/Hercules] + p.val1 = val1; + p.val2 = val2; + p.val3 = val3; + + clif->send(&p,sizeof(p), bl, target); +} + +void clif_partytickack(struct map_session_data* sd, bool flag) { + + WFIFOHEAD(sd->fd, packet_len(0x2c9)); + WFIFOW(sd->fd, 0) = 0x2c9; + WFIFOB(sd->fd, 2) = flag; + WFIFOSET(sd->fd, packet_len(0x2c9)); +} + +void clif_status_change_end(struct block_list *bl, int tid, enum send_target target, int type) { + struct packet_status_change_end p; + + p.PacketType = status_change_endType; + p.index = type; + p.AID = tid; + p.state = 0; + + clif->send(&p,sizeof(p), bl, target); +} + /*========================================== * Main client packet processing function *------------------------------------------*/ -static int clif_parse(int fd) -{ - int cmd, packet_ver, packet_len, err; +int clif_parse(int fd) { + int cmd, packet_len; TBL_PC* sd; int pnum; - + //TODO apply delays or disconnect based on packet throughput [FlavioJS] // Note: "click masters" can do 80+ clicks in 10 seconds - - for( pnum = 0; pnum < 3; ++pnum )// Limit max packets per cycle to 3 (delay packet spammers) [FlavioJS] -- This actually aids packet spammers, but stuff like /str+ gets slow without it [Ai4rei] - { // begin main client packet processing loop - - sd = (TBL_PC *)session[fd]->session_data; - if (session[fd]->flag.eof) { - if (sd) { - if (sd->state.autotrade) { - //Disassociate character from the socket connection. - session[fd]->session_data = NULL; - sd->fd = 0; - ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", sd->status.name); - } else - if (sd->state.active) { - // Player logout display [Valaris] - ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off.\n", sd->status.name); - clif_quitsave(fd, sd); + + for( pnum = 0; pnum < 3; ++pnum ) { // Limit max packets per cycle to 3 (delay packet spammers) [FlavioJS] -- This actually aids packet spammers, but stuff like /str+ gets slow without it [Ai4rei] + // begin main client packet processing loop + + sd = (TBL_PC *)session[fd]->session_data; + if (session[fd]->flag.eof) { + if (sd) { + if (sd->state.autotrade) { + //Disassociate character from the socket connection. + session[fd]->session_data = NULL; + sd->fd = 0; + ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off (using @autotrade).\n", sd->status.name); + } else + if (sd->state.active) { + // Player logout display [Valaris] + ShowInfo("Character '"CL_WHITE"%s"CL_RESET"' logged off.\n", sd->status.name); + clif->quitsave(fd, sd); + } else { + //Unusual logout (during log on/off/map-changer procedure) + ShowInfo("Player AID:%d/CID:%d logged off.\n", sd->status.account_id, sd->status.char_id); + map_quit(sd); + } } else { - //Unusual logout (during log on/off/map-changer procedure) - ShowInfo("Player AID:%d/CID:%d logged off.\n", sd->status.account_id, sd->status.char_id); - map_quit(sd); + ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip2str(session[fd]->client_addr, NULL)); } - } else { - ShowInfo("Closed connection from '"CL_WHITE"%s"CL_RESET"'.\n", ip2str(session[fd]->client_addr, NULL)); + do_close(fd); + return 0; } - do_close(fd); - return 0; - } - - if (RFIFOREST(fd) < 2) - return 0; - - cmd = RFIFOW(fd,0); - - // identify client's packet version - if (sd) { - packet_ver = sd->packet_ver; - } else { - // check authentification packet to know packet version - packet_ver = clif_guess_PacketVer(fd, 0, &err); - if( err ) {// failed to identify packet version - ShowInfo("clif_parse: Disconnecting session #%d with unknown packet version%s (p:0x%04x,l:%d).\n", fd, ( - err == 1 ? "" : - err == 2 ? ", possibly for having an invalid account_id" : - err == 3 ? ", possibly for having an invalid char_id." : - /* Uncomment when checks are added in clif_guess_PacketVer. [FlavioJS] - err == 4 ? ", possibly for having an invalid login_id1." : - err == 5 ? ", possibly for having an invalid client_tick." : - */ - err == 6 ? ", possibly for having an invalid sex." : - ". ERROR invalid error code"), cmd, RFIFOREST(fd)); - WFIFOHEAD(fd,packet_len(0x6a)); - WFIFOW(fd,0) = 0x6a; - WFIFOB(fd,2) = 3; // Rejected from Server - WFIFOSET(fd,packet_len(0x6a)); - + + if (RFIFOREST(fd) < 2) + return 0; + + cmd = RFIFOW(fd,0); + // filter out invalid / unsupported packets + if (cmd > MAX_PACKET_DB || packet_db[cmd].len == 0) { + ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", cmd, RFIFOREST(fd), fd); #ifdef DUMP_INVALID_PACKET ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif - - RFIFOSKIP(fd, RFIFOREST(fd)); set_eof(fd); return 0; } - } - - // filter out invalid / unsupported packets - if (cmd > MAX_PACKET_DB || packet_db[packet_ver][cmd].len == 0) { - ShowWarning("clif_parse: Received unsupported packet (packet 0x%04x, %d bytes received), disconnecting session #%d.\n", cmd, RFIFOREST(fd), fd); + // determine real packet length + packet_len = packet_db[cmd].len; + if (packet_len == -1) { // variable-length packet + if (RFIFOREST(fd) < 4) + return 0; + + packet_len = RFIFOW(fd,2); + if (packet_len < 4 || packet_len > 32768) { + ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd); #ifdef DUMP_INVALID_PACKET - ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); + ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); #endif - set_eof(fd); - return 0; - } - - // determine real packet length - packet_len = packet_db[packet_ver][cmd].len; - if (packet_len == -1) { // variable-length packet - if (RFIFOREST(fd) < 4) - return 0; - - packet_len = RFIFOW(fd,2); - if (packet_len < 4 || packet_len > 32768) { - ShowWarning("clif_parse: Received packet 0x%04x specifies invalid packet_len (%d), disconnecting session #%d.\n", cmd, packet_len, fd); -#ifdef DUMP_INVALID_PACKET - ShowDump(RFIFOP(fd,0), RFIFOREST(fd)); -#endif - set_eof(fd); - return 0; + set_eof(fd); + return 0; + } + } + if ((int)RFIFOREST(fd) < packet_len) + return 0; // not enough data received to form the packet + + if( packet_db[cmd].func == clif->pDebug ) + packet_db[cmd].func(fd, sd); + else if( packet_db[cmd].func != NULL ) { + if( !sd && packet_db[cmd].func != clif->pWantToConnection ) + ; //Only valid packet when there is no session + else + if( sd && sd->bl.prev == NULL && packet_db[cmd].func != clif->pLoadEndAck ) + ; //Only valid packet when player is not on a map + else + packet_db[cmd].func(fd, sd); } - } - if ((int)RFIFOREST(fd) < packet_len) - return 0; // not enough data received to form the packet - - if( packet_db[packet_ver][cmd].func == clif_parse_debug ) - packet_db[packet_ver][cmd].func(fd, sd); - else if( packet_db[packet_ver][cmd].func != NULL ) { - if( !sd && packet_db[packet_ver][cmd].func != clif_parse_WantToConnection ) - ; //Only valid packet when there is no session - else - if( sd && sd->bl.prev == NULL && packet_db[packet_ver][cmd].func != clif_parse_LoadEndAck ) - ; //Only valid packet when player is not on a map - else - if( sd && session[sd->fd]->flag.eof ) - ; //No more packets accepted - else - packet_db[packet_ver][cmd].func(fd, sd); - } #ifdef DUMP_UNKNOWN_PACKET - else { - const char* packet_txt = "save/packet.txt"; - FILE* fp; - - if( ( fp = fopen( packet_txt , "a" ) ) != NULL ) { - if( sd ) { - fprintf(fp, "Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); - } else { - fprintf(fp, "Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); - } - - WriteDump(fp, RFIFOP(fd,0), packet_len); - fprintf(fp, "\n"); - fclose(fp); - } else { - ShowError("Failed to write '%s'.\n", packet_txt); - - // Dump on console instead - if( sd ) { - ShowDebug("Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + else { + const char* packet_txt = "save/packet.txt"; + FILE* fp; + + if( ( fp = fopen( packet_txt , "a" ) ) != NULL ) { + if( sd ) { + fprintf(fp, "Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + } else { + fprintf(fp, "Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + } + + WriteDump(fp, RFIFOP(fd,0), packet_len); + fprintf(fp, "\n"); + fclose(fp); } else { - ShowDebug("Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + ShowError("Failed to write '%s'.\n", packet_txt); + + // Dump on console instead + if( sd ) { + ShowDebug("Unknown packet 0x%04X (length %d), %s session #%d, %d/%d (AID/CID)\n", cmd, packet_len, sd->state.active ? "authed" : "unauthed", fd, sd->status.account_id, sd->status.char_id); + } else { + ShowDebug("Unknown packet 0x%04X (length %d), session #%d\n", cmd, packet_len, fd); + } + + ShowDump(RFIFOP(fd,0), packet_len); } - - ShowDump(RFIFOP(fd,0), packet_len); } - } #endif - - RFIFOSKIP(fd, packet_len); - + + RFIFOSKIP(fd, packet_len); + }; // main loop end - + return 0; } -/*========================================== - * Reads packet_db.txt and setups its array reference - *------------------------------------------*/ -static int packetdb_readdb(void) -{ - FILE *fp; - char line[1024]; - int ln=0; - int cmd,i,j,packet_ver; - int max_cmd=-1; - int skip_ver = 0; - int warned = 0; - char *str[64],*p,*str2[64],*p2,w1[64],w2[64]; - int packet_len_table[MAX_PACKET_DB] = { - 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0040 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -#if PACKETVER <= 20081217 - 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,110, 3, 2, -#else - 0, 0, 0, 0, 55, 17, 3, 37, 46, -1, 23, -1, 3,114, 3, 2, -#endif -#if PACKETVER < 2 - 3, 28, 19, 11, 3, -1, 9, 5, 52, 51, 56, 58, 41, 2, 6, 6, -#elif PACKETVER < 20071106 // 78-7b Lv99 effect for later Kameshima - 3, 28, 19, 11, 3, -1, 9, 5, 54, 53, 58, 60, 41, 2, 6, 6, -#elif PACKETVER <= 20081217 // change in 0x78 and 0x7c - 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 42, 2, 6, 6, -#else - 3, 28, 19, 11, 3, -1, 9, 5, 55, 53, 58, 60, 44, 2, 6, 6, -#endif - //#0x0080 - 7, 3, 2, 2, 2, 5, 16, 12, 10, 7, 29, 2, -1, -1, -1, 0, // 0x8b changed to 2 (was 23) - 7, 22, 28, 2, 6, 30, -1, -1, 3, -1, -1, 5, 9, 17, 17, 6, -#if PACKETVER <= 20100622 - 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 7, 4, 7, 0, -1, 6, -#else - 23, 6, 6, -1, -1, -1, -1, 8, 7, 6, 9, 4, 7, 0, -1, 6, // 0xaa changed to 9 (was 7) -#endif - 8, 8, 3, 3, -1, 6, 6, -1, 7, 6, 2, 5, 6, 44, 5, 3, - //#0x00C0 - 7, 2, 6, 8, 6, 7, -1, -1, -1, -1, 3, 3, 6, 3, 2, 27, // 0xcd change to 3 (was 6) - 3, 4, 4, 2, -1, -1, 3, -1, 6, 14, 3, -1, 28, 29, -1, -1, - 30, 30, 26, 2, 6, 26, 3, 3, 8, 19, 5, 2, 3, 2, 2, 2, - 3, 2, 6, 8, 21, 8, 8, 2, 2, 26, 3, -1, 6, 27, 30, 10, - //#0x0100 - 2, 6, 6, 30, 79, 31, 10, 10, -1, -1, 4, 6, 6, 2, 11, -1, - 10, 39, 4, 10, 31, 35, 10, 18, 2, 13, 15, 20, 68, 2, 3, 16, - 6, 14, -1, -1, 21, 8, 8, 8, 8, 8, 2, 2, 3, 4, 2, -1, - 6, 86, 6, -1, -1, 7, -1, 6, 3, 16, 4, 4, 4, 6, 24, 26, - //#0x0140 - 22, 14, 6, 10, 23, 19, 6, 39, 8, 9, 6, 27, -1, 2, 6, 6, - 110, 6, -1, -1, -1, -1, -1, 6, -1, 54, 66, 54, 90, 42, 6, 42, - -1, -1, -1, -1, -1, 30, -1, 3, 14, 3, 30, 10, 43, 14,186,182, - 14, 30, 10, 3, -1, 6,106, -1, 4, 5, 4, -1, 6, 7, -1, -1, - //#0x0180 - 6, 3,106, 10, 10, 34, 0, 6, 8, 4, 4, 4, 29, -1, 10, 6, -#if PACKETVER < 1 - 90, 86, 24, 6, 30,102, 8, 4, 8, 4, 14, 10, -1, 6, 2, 6, -#else // 196 comodo icon status display for later - 90, 86, 24, 6, 30,102, 9, 4, 8, 4, 14, 10, -1, 6, 2, 6, -#endif -#if PACKETVER < 20081126 - 3, 3, 35, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, -#else // 0x1a2 changed (35->37) - 3, 3, 37, 5, 11, 26, -1, 4, 4, 6, 10, 12, 6, -1, 4, 4, -#endif - 11, 7, -1, 67, 12, 18,114, 6, 3, 6, 26, 26, 26, 26, 2, 3, - //#0x01C0, Set 0x1d5=-1 - 2, 14, 10, -1, 22, 22, 4, 2, 13, 97, 3, 9, 9, 30, 6, 28, - 8, 14, 10, 35, 6, -1, 4, 11, 54, 53, 60, 2, -1, 47, 33, 6, - 30, 8, 34, 14, 2, 6, 26, 2, 28, 81, 6, 10, 26, 2, -1, -1, - -1, -1, 20, 10, 32, 9, 34, 14, 2, 6, 48, 56, -1, 4, 5, 10, - //#0x0200 - 26, -1, 26, 10, 18, 26, 11, 34, 14, 36, 10, 0, 0, -1, 32, 10, // 0x20c change to 0 (was 19) - 22, 0, 26, 26, 42, 6, 6, 2, 2,282,282, 10, 10, -1, -1, 66, -#if PACKETVER < 20071106 - 10, -1, -1, 8, 10, 2,282, 18, 18, 15, 58, 57, 64, 5, 71, 5, -#else // 0x22c changed - 10, -1, -1, 8, 10, 2,282, 18, 18, 15, 58, 57, 65, 5, 71, 5, -#endif - 12, 26, 9, 11, -1, -1, 10, 2,282, 11, 4, 36, 6, -1, 4, 2, - //#0x0240 - -1, -1, -1, -1, -1, 3, 4, 8, -1, 3, 70, 4, 8, 12, 4, 10, - 3, 32, -1, 3, 3, 5, 5, 8, 2, 3, -1, 6, 4, 6, 4, 6, - 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0280 -#if PACKETVER < 20070711 - 0, 0, 0, 6, 14, 0, 0, -1, 6, 8, 18, 0, 0, 0, 0, 0, -#else - 0, 0, 0, 6, 14, 0, 0, -1, 10, 12, 18, 0, 0, 0, 0, 0, // 0x288, 0x289 increase by 4 (kafra points) -#endif - 0, 4, 0, 70, 10, 0, 0, 0, 8, 6, 27, 80, 0, -1, 0, 0, - 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 85, -1, -1,107, 6, -1, 7, 7, 22,191, 0, 8, 0, 0, 0, 0, - //#0x02C0 - 0, -1, 0, 0, 0, 30, 30, 0, 0, 3, 0, 65, 4, 71, 10, 0, - -1, -1, -1, 0, 29, 0, 6, -1, 10, 10, 3, 0, -1, 32, 6, 36, - 34, 33, 0, 0, 0, 0, 0, 0, -1, -1, -1, 13, 67, 59, 60, 8, - 10, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0300 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0340 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0380 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x03C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0400 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 0, 25, - //#0x0440 - 10, 4, -1, 0, 0, 0, 14, 0, 0, 0, 6, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0480 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x04C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0500 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, - //#0x0540 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0580 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x05C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0600 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, - //#0x0640 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0680 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x06C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0700 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 25, - //#0x0740 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0780 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x07C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -#if PACKETVER < 20090617 - 6, 2, -1, 4, 4, 4, 4, 8, 8,254, 6, 8, 6, 54, 30, 54, -#else // 0x7d9 changed - 6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54, -#endif - 0, 15, 8, 6, -1, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0, - //#0x0800 -#if PACKETVER < 20091229 - -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 14, 20, -#else // for Party booking ( PACKETVER >= 20091229 ) - -1, -1, 18, 4, 8, 6, 2, 4, 14, 50, 18, 6, 2, 3, 14, 20, -#endif - 3, -1, 8, -1, 86, 2, 6, 6, -1, -1, 4, 10, 10, 0, 0, 0, - 0, 0, 0, 0, 6, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, -1, -1, 3, 2, 66, 5, 2, 12, 6, 0, 0, - //#0x0840 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0880 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x08C0 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10, - 0, 0, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0900 - 0, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - //#0x0940 - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 14, 0, 0, 0, 0, 0, 0, 0, 0, - - }; - struct { - void (*func)(int, struct map_session_data *); - char *name; - } clif_parse_func[]={ - {clif_parse_WantToConnection,"wanttoconnection"}, - {clif_parse_LoadEndAck,"loadendack"}, - {clif_parse_TickSend,"ticksend"}, - {clif_parse_WalkToXY,"walktoxy"}, - {clif_parse_QuitGame,"quitgame"}, - {clif_parse_GetCharNameRequest,"getcharnamerequest"}, - {clif_parse_GlobalMessage,"globalmessage"}, - {clif_parse_MapMove,"mapmove"}, - {clif_parse_ChangeDir,"changedir"}, - {clif_parse_Emotion,"emotion"}, - {clif_parse_HowManyConnections,"howmanyconnections"}, - {clif_parse_ActionRequest,"actionrequest"}, - {clif_parse_Restart,"restart"}, - {clif_parse_WisMessage,"wis"}, - {clif_parse_Broadcast,"broadcast"}, - {clif_parse_TakeItem,"takeitem"}, - {clif_parse_DropItem,"dropitem"}, - {clif_parse_UseItem,"useitem"}, - {clif_parse_EquipItem,"equipitem"}, - {clif_parse_UnequipItem,"unequipitem"}, - {clif_parse_NpcClicked,"npcclicked"}, - {clif_parse_NpcBuySellSelected,"npcbuysellselected"}, - {clif_parse_NpcBuyListSend,"npcbuylistsend"}, - {clif_parse_NpcSellListSend,"npcselllistsend"}, - {clif_parse_CreateChatRoom,"createchatroom"}, - {clif_parse_ChatAddMember,"chataddmember"}, - {clif_parse_ChatRoomStatusChange,"chatroomstatuschange"}, - {clif_parse_ChangeChatOwner,"changechatowner"}, - {clif_parse_KickFromChat,"kickfromchat"}, - {clif_parse_ChatLeave,"chatleave"}, - {clif_parse_TradeRequest,"traderequest"}, - {clif_parse_TradeAck,"tradeack"}, - {clif_parse_TradeAddItem,"tradeadditem"}, - {clif_parse_TradeOk,"tradeok"}, - {clif_parse_TradeCancel,"tradecancel"}, - {clif_parse_TradeCommit,"tradecommit"}, - {clif_parse_StopAttack,"stopattack"}, - {clif_parse_PutItemToCart,"putitemtocart"}, - {clif_parse_GetItemFromCart,"getitemfromcart"}, - {clif_parse_RemoveOption,"removeoption"}, - {clif_parse_ChangeCart,"changecart"}, - {clif_parse_StatusUp,"statusup"}, - {clif_parse_SkillUp,"skillup"}, - {clif_parse_UseSkillToId,"useskilltoid"}, - {clif_parse_UseSkillToPos,"useskilltopos"}, - {clif_parse_UseSkillToPosMoreInfo,"useskilltoposinfo"}, - {clif_parse_UseSkillMap,"useskillmap"}, - {clif_parse_RequestMemo,"requestmemo"}, - {clif_parse_ProduceMix,"producemix"}, - {clif_parse_Cooking,"cooking"}, - {clif_parse_NpcSelectMenu,"npcselectmenu"}, - {clif_parse_NpcNextClicked,"npcnextclicked"}, - {clif_parse_NpcAmountInput,"npcamountinput"}, - {clif_parse_NpcStringInput,"npcstringinput"}, - {clif_parse_NpcCloseClicked,"npccloseclicked"}, - {clif_parse_ItemIdentify,"itemidentify"}, - {clif_parse_SelectArrow,"selectarrow"}, - {clif_parse_AutoSpell,"autospell"}, - {clif_parse_UseCard,"usecard"}, - {clif_parse_InsertCard,"insertcard"}, - {clif_parse_RepairItem,"repairitem"}, - {clif_parse_WeaponRefine,"weaponrefine"}, - {clif_parse_SolveCharName,"solvecharname"}, - {clif_parse_ResetChar,"resetchar"}, - {clif_parse_LocalBroadcast,"localbroadcast"}, - {clif_parse_MoveToKafra,"movetokafra"}, - {clif_parse_MoveFromKafra,"movefromkafra"}, - {clif_parse_MoveToKafraFromCart,"movetokafrafromcart"}, - {clif_parse_MoveFromKafraToCart,"movefromkafratocart"}, - {clif_parse_CloseKafra,"closekafra"}, - {clif_parse_CreateParty,"createparty"}, - {clif_parse_CreateParty2,"createparty2"}, - {clif_parse_PartyInvite,"partyinvite"}, - {clif_parse_PartyInvite2,"partyinvite2"}, - {clif_parse_ReplyPartyInvite,"replypartyinvite"}, - {clif_parse_ReplyPartyInvite2,"replypartyinvite2"}, - {clif_parse_LeaveParty,"leaveparty"}, - {clif_parse_RemovePartyMember,"removepartymember"}, - {clif_parse_PartyChangeOption,"partychangeoption"}, - {clif_parse_PartyMessage,"partymessage"}, - {clif_parse_PartyChangeLeader,"partychangeleader"}, - {clif_parse_CloseVending,"closevending"}, - {clif_parse_VendingListReq,"vendinglistreq"}, - {clif_parse_PurchaseReq,"purchasereq"}, - {clif_parse_PurchaseReq2,"purchasereq2"}, - {clif_parse_OpenVending,"openvending"}, - {clif_parse_CreateGuild,"createguild"}, - {clif_parse_GuildCheckMaster,"guildcheckmaster"}, - {clif_parse_GuildRequestInfo,"guildrequestinfo"}, - {clif_parse_GuildChangePositionInfo,"guildchangepositioninfo"}, - {clif_parse_GuildChangeMemberPosition,"guildchangememberposition"}, - {clif_parse_GuildRequestEmblem,"guildrequestemblem"}, - {clif_parse_GuildChangeEmblem,"guildchangeemblem"}, - {clif_parse_GuildChangeNotice,"guildchangenotice"}, - {clif_parse_GuildInvite,"guildinvite"}, - {clif_parse_GuildReplyInvite,"guildreplyinvite"}, - {clif_parse_GuildLeave,"guildleave"}, - {clif_parse_GuildExpulsion,"guildexpulsion"}, - {clif_parse_GuildMessage,"guildmessage"}, - {clif_parse_GuildRequestAlliance,"guildrequestalliance"}, - {clif_parse_GuildReplyAlliance,"guildreplyalliance"}, - {clif_parse_GuildDelAlliance,"guilddelalliance"}, - {clif_parse_GuildOpposition,"guildopposition"}, - {clif_parse_GuildBreak,"guildbreak"}, - {clif_parse_PetMenu,"petmenu"}, - {clif_parse_CatchPet,"catchpet"}, - {clif_parse_SelectEgg,"selectegg"}, - {clif_parse_SendEmotion,"sendemotion"}, - {clif_parse_ChangePetName,"changepetname"}, - - {clif_parse_GMKick,"gmkick"}, - {clif_parse_GMHide,"gmhide"}, - {clif_parse_GMReqNoChat,"gmreqnochat"}, - {clif_parse_GMReqAccountName,"gmreqaccname"}, - {clif_parse_GMKickAll,"killall"}, - {clif_parse_GMRecall,"recall"}, - {clif_parse_GMRecall,"summon"}, - {clif_parse_GM_Monster_Item,"itemmonster"}, - {clif_parse_GMShift,"remove"}, - {clif_parse_GMShift,"shift"}, - {clif_parse_GMChangeMapType,"changemaptype"}, - {clif_parse_GMRc,"rc"}, - {clif_parse_GMRecall2,"recall2"}, - {clif_parse_GMRemove2,"remove2"}, - - {clif_parse_NoviceDoriDori,"sndoridori"}, - {clif_parse_NoviceExplosionSpirits,"snexplosionspirits"}, - {clif_parse_PMIgnore,"wisexin"}, - {clif_parse_PMIgnoreList,"wisexlist"}, - {clif_parse_PMIgnoreAll,"wisall"}, - {clif_parse_FriendsListAdd,"friendslistadd"}, - {clif_parse_FriendsListRemove,"friendslistremove"}, - {clif_parse_FriendsListReply,"friendslistreply"}, - {clif_parse_Blacksmith,"blacksmith"}, - {clif_parse_Alchemist,"alchemist"}, - {clif_parse_Taekwon,"taekwon"}, - {clif_parse_RankingPk,"rankingpk"}, - {clif_parse_FeelSaveOk,"feelsaveok"}, - {clif_parse_debug,"debug"}, - {clif_parse_ChangeHomunculusName,"changehomunculusname"}, - {clif_parse_HomMoveToMaster,"hommovetomaster"}, - {clif_parse_HomMoveTo,"hommoveto"}, - {clif_parse_HomAttack,"homattack"}, - {clif_parse_HomMenu,"hommenu"}, - {clif_parse_StoragePassword,"storagepassword"}, - {clif_parse_Hotkey,"hotkey"}, - {clif_parse_AutoRevive,"autorevive"}, - {clif_parse_Check,"check"}, - {clif_parse_Adopt_request,"adoptrequest"}, - {clif_parse_Adopt_reply,"adoptreply"}, - // MAIL SYSTEM - {clif_parse_Mail_refreshinbox,"mailrefresh"}, - {clif_parse_Mail_read,"mailread"}, - {clif_parse_Mail_getattach,"mailgetattach"}, - {clif_parse_Mail_delete,"maildelete"}, - {clif_parse_Mail_return,"mailreturn"}, - {clif_parse_Mail_setattach,"mailsetattach"}, - {clif_parse_Mail_winopen,"mailwinopen"}, - {clif_parse_Mail_send,"mailsend"}, - // AUCTION SYSTEM - {clif_parse_Auction_search,"auctionsearch"}, - {clif_parse_Auction_buysell,"auctionbuysell"}, - {clif_parse_Auction_setitem,"auctionsetitem"}, - {clif_parse_Auction_cancelreg,"auctioncancelreg"}, - {clif_parse_Auction_register,"auctionregister"}, - {clif_parse_Auction_cancel,"auctioncancel"}, - {clif_parse_Auction_close,"auctionclose"}, - {clif_parse_Auction_bid,"auctionbid"}, - // Quest Log System - {clif_parse_questStateAck,"queststate"}, - {clif_parse_cashshop_buy,"cashshopbuy"}, - {clif_parse_ViewPlayerEquip,"viewplayerequip"}, - {clif_parse_EquipTick,"equiptickbox"}, - {clif_parse_BattleChat,"battlechat"}, - {clif_parse_mercenary_action,"mermenu"}, - {clif_parse_progressbar,"progressbar"}, - {clif_parse_SkillSelectMenu,"skillselectmenu"}, - {clif_parse_ItemListWindowSelected,"itemlistwindowselected"}, -#if PACKETVER >= 20091229 - {clif_parse_PartyBookingRegisterReq,"bookingregreq"}, - {clif_parse_PartyBookingSearchReq,"bookingsearchreq"}, - {clif_parse_PartyBookingUpdateReq,"bookingupdatereq"}, - {clif_parse_PartyBookingDeleteReq,"bookingdelreq"}, -#endif - {clif_parse_PVPInfo,"pvpinfo"}, - {clif_parse_LessEffect,"lesseffect"}, - // Buying Store - {clif_parse_ReqOpenBuyingStore,"reqopenbuyingstore"}, - {clif_parse_ReqCloseBuyingStore,"reqclosebuyingstore"}, - {clif_parse_ReqClickBuyingStore,"reqclickbuyingstore"}, - {clif_parse_ReqTradeBuyingStore,"reqtradebuyingstore"}, - // Store Search - {clif_parse_SearchStoreInfo,"searchstoreinfo"}, - {clif_parse_SearchStoreInfoNextPage,"searchstoreinfonextpage"}, - {clif_parse_CloseSearchStoreInfo,"closesearchstoreinfo"}, - {clif_parse_SearchStoreInfoListItemClick,"searchstoreinfolistitemclick"}, - /* */ - { clif_parse_MoveItem , "moveitem" }, - {NULL,NULL} - }; - - // initialize packet_db[SERVER] from hardcoded packet_len_table[] values - memset(packet_db,0,sizeof(packet_db)); - for( i = 0; i < ARRAYLENGTH(packet_len_table); ++i ) - packet_len(i) = packet_len_table[i]; - - sprintf(line, "%s/packet_db.txt", db_path); - if( (fp=fopen(line,"r"))==NULL ){ - ShowFatalError("can't read %s\n", line); - exit(EXIT_FAILURE); - } - - clif_config.packet_db_ver = MAX_PACKET_VER; - packet_ver = MAX_PACKET_VER; // read into packet_db's version by default - while( fgets(line, sizeof(line), fp) ) - { - ln++; - if(line[0]=='/' && line[1]=='/') - continue; - if (sscanf(line,"%256[^:]: %256[^\r\n]",w1,w2) == 2) - { - if(strcmpi(w1,"packet_ver")==0) { - int prev_ver = packet_ver; - skip_ver = 0; - packet_ver = atoi(w2); - if ( packet_ver > MAX_PACKET_VER ) - { //Check to avoid overflowing. [Skotlex] - if( (warned&1) == 0 ) - ShowWarning("The packet_db table only has support up to version %d.\n", MAX_PACKET_VER); - warned &= 1; - skip_ver = 1; - } - else if( packet_ver < 0 ) - { - if( (warned&2) == 0 ) - ShowWarning("Negative packet versions are not supported.\n"); - warned &= 2; - skip_ver = 1; - } - else if( packet_ver == SERVER ) - { - if( (warned&4) == 0 ) - ShowWarning("Packet version %d is reserved for server use only.\n", SERVER); - warned &= 4; - skip_ver = 1; - } - - if( skip_ver ) - { - ShowWarning("Skipping packet version %d.\n", packet_ver); - packet_ver = prev_ver; - continue; - } - // copy from previous version into new version and continue - // - indicating all following packets should be read into the newer version - memcpy(&packet_db[packet_ver], &packet_db[prev_ver], sizeof(packet_db[0])); - continue; - } else if(strcmpi(w1,"packet_db_ver")==0) { - if(strcmpi(w2,"default")==0) //This is the preferred version. - clif_config.packet_db_ver = MAX_PACKET_VER; - else // to manually set the packet DB version - clif_config.packet_db_ver = cap_value(atoi(w2), 0, MAX_PACKET_VER); - - continue; - } - } - - if( skip_ver != 0 ) - continue; // Skipping current packet version - - memset(str,0,sizeof(str)); - for(j=0,p=line;j<4 && p; ++j) - { - str[j]=p; - p=strchr(p,','); - if(p) *p++=0; - } - if(str[0]==NULL) - continue; - cmd=strtol(str[0],(char **)NULL,0); - if(max_cmd < cmd) - max_cmd = cmd; - if(cmd <= 0 || cmd > MAX_PACKET_DB) - continue; - if(str[1]==NULL){ - ShowError("packet_db: packet len error\n"); - continue; - } - - packet_db[packet_ver][cmd].len = (short)atoi(str[1]); - - if(str[2]==NULL){ - packet_db[packet_ver][cmd].func = NULL; - ln++; - continue; - } - - // look up processing function by name - ARR_FIND( 0, ARRAYLENGTH(clif_parse_func), j, clif_parse_func[j].name != NULL && strcmp(str[2],clif_parse_func[j].name)==0 ); - if( j < ARRAYLENGTH(clif_parse_func) ) - packet_db[packet_ver][cmd].func = clif_parse_func[j].func; - - // set the identifying cmd for the packet_db version - if (strcmp(str[2],"wanttoconnection")==0) - clif_config.connect_cmd[packet_ver] = cmd; - - if(str[3]==NULL){ - ShowError("packet_db: packet error\n"); - exit(EXIT_FAILURE); - } - for(j=0,p2=str[3];p2;j++){ - short k; - str2[j]=p2; - p2=strchr(p2,':'); - if(p2) *p2++=0; - k = atoi(str2[j]); - // if (packet_db[packet_ver][cmd].pos[j] != k && clif_config.prefer_packet_db) // not used for now - - if( j >= MAX_PACKET_POS ) - { - ShowError("Too many positions found for packet 0x%04x (max=%d).\n", cmd, MAX_PACKET_POS); - break; - } - - packet_db[packet_ver][cmd].pos[j] = k; - } - } - fclose(fp); - if(max_cmd > MAX_PACKET_DB) - { - ShowWarning("Found packets up to 0x%X, ignored 0x%X and above.\n", max_cmd, MAX_PACKET_DB); - ShowWarning("Please increase MAX_PACKET_DB and recompile.\n"); - } - if (!clif_config.connect_cmd[clif_config.packet_db_ver]) - { //Locate the nearest version that we still support. [Skotlex] - for(j = clif_config.packet_db_ver; j >= 0 && !clif_config.connect_cmd[j]; j--); - - clif_config.packet_db_ver = j?j:MAX_PACKET_VER; +static void __attribute__ ((unused)) packetdb_addpacket(short cmd, int len, ...) { + va_list va; + int i; + int pos; + pFunc func; + + if (cmd > MAX_PACKET_DB) { + ShowError("Packet Error: packet 0x%x is greater than the maximum allowed (0x%x), skipping...\n", cmd, MAX_PACKET_DB); + return; + } + + packet_db[cmd].len = len; + + va_start(va,len); + + pos = va_arg(va, int); + + if( pos == 0xFFFF ) /* nothing more to do */ + return; + + va_end(va); + va_start(va,len); + + func = va_arg(va,pFunc); + + packet_db[cmd].func = func; + + for (i = 0; i < MAX_PACKET_POS; i++) { + pos = va_arg(va, int); + + if (pos == 0xFFFF) + break; + + packet_db[cmd].pos[i] = pos; } - ShowStatus("Done reading packet database from '"CL_WHITE"%s"CL_RESET"'. Using default packet version: "CL_WHITE"%d"CL_RESET".\n", "packet_db.txt", clif_config.packet_db_ver); - return 0; } - +void packetdb_loaddb(void) { + + memset(packet_db,0,sizeof(packet_db)); + + #define packet(id, size, ...) packetdb_addpacket(id, size, ##__VA_ARGS__, 0xFFFF) + #include "packets.h" /* load structure data */ + #undef packet +} +void clif_bc_ready(void) { + if( battle_config.display_status_timers ) + clif->status_change = clif_status_change; + else + clif->status_change = clif_status_change_notick; +} /*========================================== * *------------------------------------------*/ int do_init_clif(void) { - const char* colors[COLOR_MAX] = { "0xFF0000" }; + const char* colors[COLOR_MAX] = { "0xFF0000", "0x00ff00", "0xffffff" }; int i; /** * Setup Color Table (saves unnecessary load of strtoul on every call) @@ -17101,28 +17129,715 @@ int do_init_clif(void) { color_table[i] = strtoul(colors[i],NULL,0); color_table[i] = (color_table[i] & 0x0000FF) << 16 | (color_table[i] & 0x00FF00) | (color_table[i] & 0xFF0000) >> 16;//RGB to BGR } - - clif_config.packet_db_ver = -1; // the main packet version of the DB - memset(clif_config.connect_cmd, 0, sizeof(clif_config.connect_cmd)); //The default connect command will be determined after reading the packet_db [Skotlex] - - memset(packet_db,0,sizeof(packet_db)); - //Using the packet_db file is the only way to set up packets now [Skotlex] - packetdb_readdb(); - - set_defaultparse(clif_parse); - if( make_listen_bind(bind_ip,map_port) == -1 ) { - ShowFatalError("can't bind game port\n"); + + packetdb_loaddb(); + + set_defaultparse(clif->parse); + if( make_listen_bind(clif->bind_ip,clif->map_port) == -1 ) { + ShowFatalError("Failed to bind to port '"CL_WHITE"%d"CL_RESET"'\n",clif->map_port); exit(EXIT_FAILURE); } - add_timer_func_list(clif_clearunit_delayed_sub, "clif_clearunit_delayed_sub"); - add_timer_func_list(clif_delayquit, "clif_delayquit"); + add_timer_func_list(clif->clearunit_delayed_sub, "clif_clearunit_delayed_sub"); + add_timer_func_list(clif->delayquit, "clif_delayquit"); - delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); + clif->delay_clearunit_ers = ers_new(sizeof(struct block_list),"clif.c::delay_clearunit_ers",ERS_OPT_CLEAR); + clif->channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCHSYS_NAME_LENGTH); + hChSys.ally = hChSys.local = hChSys.irc = hChSys.ally_autojoin = hChSys.local_autojoin = false; + clif->chann_config_read(); + return 0; } void do_final_clif(void) { - ers_destroy(delay_clearunit_ers); + DBIterator *iter = db_iterator(clif->channel_db); + struct hChSysCh *channel; + unsigned char i; + + for( channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter) ) { + clif->chsys_delete(channel); + } + + dbi_destroy(iter); + + for(i = 0; i < hChSys.colors_count; i++) { + aFree(hChSys.colors_name[i]); + } + + if( hChSys.colors_count ) { + aFree(hChSys.colors_name); + aFree(hChSys.colors); + } + + db_destroy(clif->channel_db); + ers_destroy(clif->delay_clearunit_ers); + + for(i = 0; i < CASHSHOP_TAB_MAX; i++) { + int k; + for( k = 0; k < clif->cs.item_count[i]; k++ ) { + aFree(clif->cs.data[i][k]); + } + aFree(clif->cs.data[i]); + } + +} +void clif_defaults(void) { + clif = &clif_s; + /* vars */ + clif->bind_ip = INADDR_ANY; + clif->map_port = 5121; + /* core */ + clif->init = do_init_clif; + clif->final = do_final_clif; + clif->setip = clif_setip; + clif->setbindip = clif_setbindip; + clif->setport = clif_setport; + clif->refresh_ip = clif_refresh_ip; + clif->send = clif_send; + clif->send_sub = clif_send_sub; + clif->parse = clif_parse; + /* auth */ + clif->authok = clif_authok; + clif->authrefuse = clif_authrefuse; + clif->authfail_fd = clif_authfail_fd; + clif->charselectok = clif_charselectok; + /* item-related */ + clif->dropflooritem = clif_dropflooritem; + clif->clearflooritem = clif_clearflooritem; + clif->additem = clif_additem; + clif->dropitem = clif_dropitem; + clif->delitem = clif_delitem; + clif->takeitem = clif_takeitem; + clif->arrowequip = clif_arrowequip; + clif->arrow_fail = clif_arrow_fail; + clif->use_card = clif_use_card; + clif->cart_additem = clif_cart_additem; + clif->cart_delitem = clif_cart_delitem; + clif->equipitemack = clif_equipitemack; + clif->unequipitemack = clif_unequipitemack; + clif->useitemack = clif_useitemack; + clif->addcards = clif_addcards; + clif->addcards2 = clif_addcards2; + clif->item_sub = clif_item_sub; + clif->getareachar_item = clif_getareachar_item; + /* unit-related */ + clif->clearunit_single = clif_clearunit_single; + clif->clearunit_area = clif_clearunit_area; + clif->clearunit_delayed = clif_clearunit_delayed; + clif->walkok = clif_walkok; + clif->move = clif_move; + clif->move2 = clif_move2; + clif->blown = clif_blown; + clif->slide = clif_slide; + clif->fixpos = clif_fixpos; + clif->changelook = clif_changelook; + clif->changetraplook = clif_changetraplook; + clif->refreshlook = clif_refreshlook; + clif->class_change = clif_class_change; + clif->skill_setunit = clif_skill_setunit; + clif->skill_delunit = clif_skill_delunit; + clif->skillunit_update = clif_skillunit_update; + clif->clearunit_delayed_sub = clif_clearunit_delayed_sub; + clif->set_unit_idle = clif_set_unit_idle; + clif->spawn_unit = clif_spawn_unit; + clif->set_unit_walking = clif_set_unit_walking; + clif->calc_walkdelay = clif_calc_walkdelay; + clif->getareachar_skillunit = clif_getareachar_skillunit; + clif->getareachar_unit = clif_getareachar_unit; + clif->clearchar_skillunit = clif_clearchar_skillunit; + clif->getareachar = clif_getareachar; + /* main unit spawn */ + clif->spawn = clif_spawn; + /* map-related */ + clif->changemap = clif_changemap; + clif->changemapcell = clif_changemapcell; + clif->map_property = clif_map_property; + clif->pvpset = clif_pvpset; + clif->map_property_mapall = clif_map_property_mapall; + clif->bossmapinfo = clif_bossmapinfo; + clif->map_type = clif_map_type; + clif->maptypeproperty2 = clif_maptypeproperty2; + /* multi-map-server */ + clif->changemapserver = clif_changemapserver; + /* npc-shop-related */ + clif->npcbuysell = clif_npcbuysell; + clif->buylist = clif_buylist; + clif->selllist = clif_selllist; + clif->cashshop_show = clif_cashshop_show; + clif->npc_buy_result = clif_npc_buy_result; + clif->npc_sell_result = clif_npc_sell_result; + clif->cashshop_ack = clif_cashshop_ack; + /* npc-script-related */ + clif->scriptmes = clif_scriptmes; + clif->scriptnext = clif_scriptnext; + clif->scriptclose = clif_scriptclose; + clif->scriptmenu = clif_scriptmenu; + clif->scriptinput = clif_scriptinput; + clif->scriptinputstr = clif_scriptinputstr; + clif->cutin = clif_cutin; + clif->sendfakenpc = clif_sendfakenpc; + /* client-user-interface-related */ + clif->viewpoint = clif_viewpoint; + clif->damage = clif_damage; + clif->sitting = clif_sitting; + clif->standing = clif_standing; + clif->arrow_create_list = clif_arrow_create_list; + clif->refresh = clif_refresh; + clif->fame_blacksmith = clif_fame_blacksmith; + clif->fame_alchemist = clif_fame_alchemist; + clif->fame_taekwon = clif_fame_taekwon; + clif->hotkeys = clif_hotkeys_send; + clif->insight = clif_insight; + clif->outsight = clif_outsight; + clif->skillcastcancel = clif_skillcastcancel; + clif->skill_fail = clif_skill_fail; + clif->skill_cooldown = clif_skill_cooldown; + clif->skill_memomessage = clif_skill_memomessage; + clif->skill_teleportmessage = clif_skill_teleportmessage; + clif->skill_produce_mix_list = clif_skill_produce_mix_list; + clif->cooking_list = clif_cooking_list; + clif->autospell = clif_autospell; + clif->combo_delay = clif_combo_delay; + clif->status_change = clif_status_change; + clif->insert_card = clif_insert_card; + clif->inventorylist = clif_inventorylist; + clif->equiplist = clif_equiplist; + clif->cartlist = clif_cartlist; + clif->favorite_item = clif_favorite_item; + clif->clearcart = clif_clearcart; + clif->item_identify_list = clif_item_identify_list; + clif->item_identified = clif_item_identified; + clif->item_repair_list = clif_item_repair_list; + clif->item_repaireffect = clif_item_repaireffect; + clif->item_damaged = clif_item_damaged; + clif->item_refine_list = clif_item_refine_list; + clif->item_skill = clif_item_skill; + clif->mvp_item = clif_mvp_item; + clif->mvp_exp = clif_mvp_exp; + clif->mvp_noitem = clif_mvp_noitem; + clif->changed_dir = clif_changed_dir; + clif->charnameack = clif_charnameack; + clif->monster_hp_bar = clif_monster_hp_bar; + clif->hpmeter = clif_hpmeter; + clif->hpmeter_single = clif_hpmeter_single; + clif->hpmeter_sub = clif_hpmeter_sub; + clif->upgrademessage = clif_upgrademessage; + clif->get_weapon_view = clif_get_weapon_view; + clif->gospel_info = clif_gospel_info; + clif->feel_req = clif_feel_req; + clif->starskill = clif_starskill; + clif->feel_info = clif_feel_info; + clif->hate_info = clif_hate_info; + clif->mission_info = clif_mission_info; + clif->feel_hate_reset = clif_feel_hate_reset; + clif->partytickack = clif_partytickack; + clif->equiptickack = clif_equiptickack; + clif->viewequip_ack = clif_viewequip_ack; + clif->viewequip_fail = clif_viewequip_fail; + clif->equipcheckbox = clif_equipcheckbox; + clif->displayexp = clif_displayexp; + clif->font = clif_font; + clif->progressbar = clif_progressbar; + clif->progressbar_abort = clif_progressbar_abort; + clif->showdigit = clif_showdigit; + clif->elementalconverter_list = clif_elementalconverter_list; + clif->spellbook_list = clif_spellbook_list; + clif->magicdecoy_list = clif_magicdecoy_list; + clif->poison_list = clif_poison_list; + clif->autoshadowspell_list = clif_autoshadowspell_list; + clif->skill_itemlistwindow = clif_skill_itemlistwindow; + clif->sc_load = clif_status_change2; + clif->sc_end = clif_status_change_end; + clif->initialstatus = clif_initialstatus; + /* player-unit-specific-related */ + clif->updatestatus = clif_updatestatus; + clif->changestatus = clif_changestatus; + clif->statusupack = clif_statusupack; + clif->movetoattack = clif_movetoattack; + clif->solved_charname = clif_solved_charname; + clif->charnameupdate = clif_charnameupdate; + clif->delayquit = clif_delayquit; + clif->getareachar_pc = clif_getareachar_pc; + clif->disconnect_ack = clif_disconnect_ack; + clif->PVPInfo = clif_PVPInfo; + clif->blacksmith = clif_blacksmith; + clif->alchemist = clif_alchemist; + clif->taekwon = clif_taekwon; + clif->ranking_pk = clif_ranking_pk; + clif->quitsave = clif_quitsave; + /* visual effects client-side */ + clif->misceffect = clif_misceffect; + clif->changeoption = clif_changeoption; + clif->changeoption2 = clif_changeoption2; + clif->emotion = clif_emotion; + clif->talkiebox = clif_talkiebox; + clif->wedding_effect = clif_wedding_effect; + clif->divorced = clif_divorced; + clif->callpartner = clif_callpartner; + clif->skill_damage = clif_skill_damage; + clif->skill_nodamage = clif_skill_nodamage; + clif->skill_poseffect = clif_skill_poseffect; + clif->skill_estimation = clif_skill_estimation; + clif->skill_warppoint = clif_skill_warppoint; + clif->skillcasting = clif_skillcasting; + clif->produce_effect = clif_produceeffect; + clif->devotion = clif_devotion; + clif->spiritball = clif_spiritball; + clif->spiritball_single = clif_spiritball_single; + clif->bladestop = clif_bladestop; + clif->mvp_effect = clif_mvp_effect; + clif->heal = clif_heal; + clif->resurrection = clif_resurrection; + clif->refine = clif_refine; + clif->weather = clif_weather; + clif->specialeffect = clif_specialeffect; + clif->specialeffect_single = clif_specialeffect_single; + clif->specialeffect_value = clif_specialeffect_value; + clif->millenniumshield = clif_millenniumshield; + clif->talisman = clif_talisman; + clif->talisman_single = clif_talisman_single; + clif->snap = clif_snap; + clif->weather_check = clif_weather_check; + /* sound effects client-side */ + clif->playBGM = clif_playBGM; + clif->soundeffect = clif_soundeffect; + clif->soundeffectall = clif_soundeffectall; + /* chat/message-related */ + clif->GlobalMessage = clif_GlobalMessage; + clif->createchat = clif_createchat; + clif->dispchat = clif_dispchat; + clif->joinchatfail = clif_joinchatfail; + clif->joinchatok = clif_joinchatok; + clif->addchat = clif_addchat; + clif->changechatowner = clif_changechatowner; + clif->clearchat = clif_clearchat; + clif->leavechat = clif_leavechat; + clif->changechatstatus = clif_changechatstatus; + clif->wis_message = clif_wis_message; + clif->wis_end = clif_wis_end; + clif->disp_onlyself = clif_disp_onlyself; + clif->disp_message = clif_disp_message; + clif->broadcast = clif_broadcast; + clif->broadcast2 = clif_broadcast2; + clif->messagecolor = clif_messagecolor; + clif->disp_overhead = clif_disp_overhead; + clif->msg = clif_msg; + clif->msg_value = clif_msg_value; + clif->msg_skill = clif_msg_skill; + clif->msgtable = clif_msgtable; + clif->msgtable_num = clif_msgtable_num; + clif->message = clif_displaymessage; + clif->messageln = clif_displaymessage2; + clif->colormes = clif_colormes; + clif->process_message = clif_process_message; + clif->wisexin = clif_wisexin; + clif->wisall = clif_wisall; + clif->PMIgnoreList = clif_PMIgnoreList; + /* trade handling */ + clif->traderequest = clif_traderequest; + clif->tradestart = clif_tradestart; + clif->tradeadditem = clif_tradeadditem; + clif->tradeitemok = clif_tradeitemok; + clif->tradedeal_lock = clif_tradedeal_lock; + clif->tradecancelled = clif_tradecancelled; + clif->tradecompleted = clif_tradecompleted; + clif->tradeundo = clif_tradeundo; + /* vending handling */ + clif->openvendingreq = clif_openvendingreq; + clif->showvendingboard = clif_showvendingboard; + clif->closevendingboard = clif_closevendingboard; + clif->vendinglist = clif_vendinglist; + clif->buyvending = clif_buyvending; + clif->openvending = clif_openvending; + clif->vendingreport = clif_vendingreport; + /* storage handling */ + clif->storagelist = clif_storagelist; + clif->updatestorageamount = clif_updatestorageamount; + clif->storageitemadded = clif_storageitemadded; + clif->storageitemremoved = clif_storageitemremoved; + clif->storageclose = clif_storageclose; + /* skill-list handling */ + clif->skillinfoblock = clif_skillinfoblock; + clif->skillup = clif_skillup; + clif->skillinfo = clif_skillinfo; + clif->addskill = clif_addskill; + clif->deleteskill = clif_deleteskill; + /* party-specific */ + clif->party_created = clif_party_created; + clif->party_member_info = clif_party_member_info; + clif->party_info = clif_party_info; + clif->party_invite = clif_party_invite; + clif->party_inviteack = clif_party_inviteack; + clif->party_option = clif_party_option; + clif->party_withdraw = clif_party_withdraw; + clif->party_message = clif_party_message; + clif->party_xy = clif_party_xy; + clif->party_xy_single = clif_party_xy_single; + clif->party_hp = clif_party_hp; + clif->party_xy_remove = clif_party_xy_remove; + clif->party_show_picker = clif_party_show_picker; + clif->partyinvitationstate = clif_partyinvitationstate; + /* guild-specific */ + clif->guild_created = clif_guild_created; + clif->guild_belonginfo = clif_guild_belonginfo; + clif->guild_masterormember = clif_guild_masterormember; + clif->guild_basicinfo = clif_guild_basicinfo; + clif->guild_allianceinfo = clif_guild_allianceinfo; + clif->guild_memberlist = clif_guild_memberlist; + clif->guild_skillinfo = clif_guild_skillinfo; + clif->guild_send_onlineinfo = clif_guild_send_onlineinfo; + clif->guild_memberlogin_notice = clif_guild_memberlogin_notice; + clif->guild_invite = clif_guild_invite; + clif->guild_inviteack = clif_guild_inviteack; + clif->guild_leave = clif_guild_leave; + clif->guild_expulsion = clif_guild_expulsion; + clif->guild_positionchanged = clif_guild_positionchanged; + clif->guild_memberpositionchanged = clif_guild_memberpositionchanged; + clif->guild_emblem = clif_guild_emblem; + clif->guild_emblem_area = clif_guild_emblem_area; + clif->guild_notice = clif_guild_notice; + clif->guild_message = clif_guild_message; + clif->guild_skillup = clif_guild_skillup; + clif->guild_reqalliance = clif_guild_reqalliance; + clif->guild_allianceack = clif_guild_allianceack; + clif->guild_delalliance = clif_guild_delalliance; + clif->guild_oppositionack = clif_guild_oppositionack; + clif->guild_broken = clif_guild_broken; + clif->guild_xy = clif_guild_xy; + clif->guild_xy_single = clif_guild_xy_single; + clif->guild_xy_remove = clif_guild_xy_remove; + clif->guild_positionnamelist = clif_guild_positionnamelist; + clif->guild_positioninfolist = clif_guild_positioninfolist; + clif->guild_expulsionlist = clif_guild_expulsionlist; + clif->validate_emblem = clif_validate_emblem; + /* battleground-specific */ + clif->bg_hp = clif_bg_hp; + clif->bg_xy = clif_bg_xy; + clif->bg_xy_remove = clif_bg_xy_remove; + clif->bg_message = clif_bg_message; + clif->bg_updatescore = clif_bg_updatescore; + clif->bg_updatescore_single = clif_bg_updatescore_single; + clif->sendbgemblem_area = clif_sendbgemblem_area; + clif->sendbgemblem_single = clif_sendbgemblem_single; + /* instance-related */ + clif->instance = clif_instance; + clif->instance_join = clif_instance_join; + clif->instance_leave = clif_instance_leave; + /* pet-related */ + clif->catch_process = clif_catch_process; + clif->pet_roulette = clif_pet_roulette; + clif->sendegg = clif_sendegg; + clif->send_petstatus = clif_send_petstatus; + clif->send_petdata = clif_send_petdata; + clif->pet_emotion = clif_pet_emotion; + clif->pet_food = clif_pet_food; + /* friend-related */ + clif->friendslist_toggle_sub = clif_friendslist_toggle_sub; + clif->friendslist_send = clif_friendslist_send; + clif->friendslist_reqack = clif_friendslist_reqack; + clif->friendslist_toggle = clif_friendslist_toggle; + clif->friendlist_req = clif_friendlist_req; + /* gm-related */ + clif->GM_kickack = clif_GM_kickack; + clif->GM_kick = clif_GM_kick; + clif->manner_message = clif_manner_message; + clif->GM_silence = clif_GM_silence; + clif->account_name = clif_account_name; + clif->check = clif_check; + /* hom-related */ + clif->hominfo = clif_hominfo; + clif->homskillinfoblock = clif_homskillinfoblock; + clif->homskillup = clif_homskillup; + clif->hom_food = clif_hom_food; + clif->send_homdata = clif_send_homdata; + /* questlog-related */ + clif->quest_send_list = clif_quest_send_list; + clif->quest_send_mission = clif_quest_send_mission; + clif->quest_add = clif_quest_add; + clif->quest_delete = clif_quest_delete; + clif->quest_update_status = clif_quest_update_status; + clif->quest_update_objective = clif_quest_update_objective; + clif->quest_show_event = clif_quest_show_event; + /* mail-related */ + clif->mail_window = clif_Mail_window; + clif->mail_read = clif_Mail_read; + clif->mail_delete = clif_Mail_delete; + clif->mail_return = clif_Mail_return; + clif->mail_send = clif_Mail_send; + clif->mail_new = clif_Mail_new; + clif->mail_refreshinbox = clif_Mail_refreshinbox; + clif->mail_getattachment = clif_Mail_getattachment; + clif->mail_setattachment = clif_Mail_setattachment; + /* auction-related */ + clif->auction_openwindow = clif_Auction_openwindow; + clif->auction_results = clif_Auction_results; + clif->auction_message = clif_Auction_message; + clif->auction_close = clif_Auction_close; + clif->auction_setitem = clif_Auction_setitem; + /* mercenary-related */ + clif->mercenary_info = clif_mercenary_info; + clif->mercenary_skillblock = clif_mercenary_skillblock; + clif->mercenary_message = clif_mercenary_message; + clif->mercenary_updatestatus = clif_mercenary_updatestatus; + /* item rental */ + clif->rental_time = clif_rental_time; + clif->rental_expired = clif_rental_expired; + /* party booking related */ + clif->PartyBookingRegisterAck = clif_PartyBookingRegisterAck; + clif->PartyBookingDeleteAck = clif_PartyBookingDeleteAck; + clif->PartyBookingSearchAck = clif_PartyBookingSearchAck; + clif->PartyBookingUpdateNotify = clif_PartyBookingUpdateNotify; + clif->PartyBookingDeleteNotify = clif_PartyBookingDeleteNotify; + clif->PartyBookingInsertNotify = clif_PartyBookingInsertNotify; + /* buying store-related */ + clif->buyingstore_open = clif_buyingstore_open; + clif->buyingstore_open_failed = clif_buyingstore_open_failed; + clif->buyingstore_myitemlist = clif_buyingstore_myitemlist; + clif->buyingstore_entry = clif_buyingstore_entry; + clif->buyingstore_entry_single = clif_buyingstore_entry_single; + clif->buyingstore_disappear_entry = clif_buyingstore_disappear_entry; + clif->buyingstore_disappear_entry_single = clif_buyingstore_disappear_entry_single; + clif->buyingstore_itemlist = clif_buyingstore_itemlist; + clif->buyingstore_trade_failed_buyer = clif_buyingstore_trade_failed_buyer; + clif->buyingstore_update_item = clif_buyingstore_update_item; + clif->buyingstore_delete_item = clif_buyingstore_delete_item; + clif->buyingstore_trade_failed_seller = clif_buyingstore_trade_failed_seller; + /* search store-related */ + clif->search_store_info_ack = clif_search_store_info_ack; + clif->search_store_info_failed = clif_search_store_info_failed; + clif->open_search_store_info = clif_open_search_store_info; + clif->search_store_info_click_ack = clif_search_store_info_click_ack; + /* elemental-related */ + clif->elemental_info = clif_elemental_info; + clif->elemental_updatestatus = clif_elemental_updatestatus; + /* misc-handling */ + clif->adopt_reply = clif_Adopt_reply; + clif->adopt_request = clif_Adopt_request; + clif->readbook = clif_readbook; + clif->notify_time = clif_notify_time; + clif->user_count = clif_user_count; + clif->noask_sub = clif_noask_sub; + clif->chsys_create = clif_hercules_chsys_create; + clif->chsys_msg = clif_hercules_chsys_msg; + clif->chsys_msg2 = clif_hercules_chsys_msg2; + clif->chsys_send = clif_hercules_chsys_send; + clif->chsys_join = clif_hercules_chsys_join; + clif->chsys_left = clif_hercules_chsys_left; + clif->chsys_delete = clif_hercules_chsys_delete; + clif->chsys_mjoin = clif_hercules_chsys_mjoin; + clif->chsys_quit = clif_hercules_chsys_quit; + clif->chsys_quitg = clif_hercules_chsys_quitg; + clif->chsys_gjoin = clif_hercules_chsys_gjoin; + clif->chsys_gleave = clif_hercules_chsys_gleave; + clif->cashshop_load = clif_cashshop_db; + clif->bc_ready = clif_bc_ready; + clif->undisguise_timer = clif_undisguise_timer; + /*------------------------ + *- Parse Incoming Packet + *------------------------*/ + clif->pWantToConnection = clif_parse_WantToConnection; + clif->pLoadEndAck = clif_parse_LoadEndAck; + clif->pTickSend = clif_parse_TickSend; + clif->pHotkey = clif_parse_Hotkey; + clif->pProgressbar = clif_parse_progressbar; + clif->pWalkToXY = clif_parse_WalkToXY; + clif->pQuitGame = clif_parse_QuitGame; + clif->pGetCharNameRequest = clif_parse_GetCharNameRequest; + clif->pGlobalMessage = clif_parse_GlobalMessage; + clif->pMapMove = clif_parse_MapMove; + clif->pChangeDir = clif_parse_ChangeDir; + clif->pEmotion = clif_parse_Emotion; + clif->pHowManyConnections = clif_parse_HowManyConnections; + clif->pActionRequest = clif_parse_ActionRequest; + clif->pActionRequest_sub = clif_parse_ActionRequest_sub; + clif->pRestart = clif_parse_Restart; + clif->pWisMessage = clif_parse_WisMessage; + clif->pBroadcast = clif_parse_Broadcast; + clif->pTakeItem = clif_parse_TakeItem; + clif->pDropItem = clif_parse_DropItem; + clif->pUseItem = clif_parse_UseItem; + clif->pEquipItem = clif_parse_EquipItem; + clif->pUnequipItem = clif_parse_UnequipItem; + clif->pNpcClicked = clif_parse_NpcClicked; + clif->pNpcBuySellSelected = clif_parse_NpcBuySellSelected; + clif->pNpcBuyListSend = clif_parse_NpcBuyListSend; + clif->pNpcSellListSend = clif_parse_NpcSellListSend; + clif->pCreateChatRoom = clif_parse_CreateChatRoom; + clif->pChatAddMember = clif_parse_ChatAddMember; + clif->pChatRoomStatusChange = clif_parse_ChatRoomStatusChange; + clif->pChangeChatOwner = clif_parse_ChangeChatOwner; + clif->pKickFromChat = clif_parse_KickFromChat; + clif->pChatLeave = clif_parse_ChatLeave; + clif->pTradeRequest = clif_parse_TradeRequest; + clif->pTradeAck = clif_parse_TradeAck; + clif->pTradeAddItem = clif_parse_TradeAddItem; + clif->pTradeOk = clif_parse_TradeOk; + clif->pTradeCancel = clif_parse_TradeCancel; + clif->pTradeCommit = clif_parse_TradeCommit; + clif->pStopAttack = clif_parse_StopAttack; + clif->pPutItemToCart = clif_parse_PutItemToCart; + clif->pGetItemFromCart = clif_parse_GetItemFromCart; + clif->pRemoveOption = clif_parse_RemoveOption; + clif->pChangeCart = clif_parse_ChangeCart; + clif->pStatusUp = clif_parse_StatusUp; + clif->pSkillUp = clif_parse_SkillUp; + clif->pUseSkillToId = clif_parse_UseSkillToId; + clif->pUseSkillToId_homun = clif_parse_UseSkillToId_homun; + clif->pUseSkillToId_mercenary = clif_parse_UseSkillToId_mercenary; + clif->pUseSkillToPos = clif_parse_UseSkillToPos; + clif->pUseSkillToPosSub = clif_parse_UseSkillToPosSub; + clif->pUseSkillToPos_homun = clif_parse_UseSkillToPos_homun; + clif->pUseSkillToPos_mercenary = clif_parse_UseSkillToPos_mercenary; + clif->pUseSkillToPosMoreInfo = clif_parse_UseSkillToPosMoreInfo; + clif->pUseSkillMap = clif_parse_UseSkillMap; + clif->pRequestMemo = clif_parse_RequestMemo; + clif->pProduceMix = clif_parse_ProduceMix; + clif->pCooking = clif_parse_Cooking; + clif->pRepairItem = clif_parse_RepairItem; + clif->pWeaponRefine = clif_parse_WeaponRefine; + clif->pNpcSelectMenu = clif_parse_NpcSelectMenu; + clif->pNpcNextClicked = clif_parse_NpcNextClicked; + clif->pNpcAmountInput = clif_parse_NpcAmountInput; + clif->pNpcStringInput = clif_parse_NpcStringInput; + clif->pNpcCloseClicked = clif_parse_NpcCloseClicked; + clif->pItemIdentify = clif_parse_ItemIdentify; + clif->pSelectArrow = clif_parse_SelectArrow; + clif->pAutoSpell = clif_parse_AutoSpell; + clif->pUseCard = clif_parse_UseCard; + clif->pInsertCard = clif_parse_InsertCard; + clif->pSolveCharName = clif_parse_SolveCharName; + clif->pResetChar = clif_parse_ResetChar; + clif->pLocalBroadcast = clif_parse_LocalBroadcast; + clif->pMoveToKafra = clif_parse_MoveToKafra; + clif->pMoveFromKafra = clif_parse_MoveFromKafra; + clif->pMoveToKafraFromCart = clif_parse_MoveToKafraFromCart; + clif->pMoveFromKafraToCart = clif_parse_MoveFromKafraToCart; + clif->pCloseKafra = clif_parse_CloseKafra; + clif->pStoragePassword = clif_parse_StoragePassword; + clif->pCreateParty = clif_parse_CreateParty; + clif->pCreateParty2 = clif_parse_CreateParty2; + clif->pPartyInvite = clif_parse_PartyInvite; + clif->pPartyInvite2 = clif_parse_PartyInvite2; + clif->pReplyPartyInvite = clif_parse_ReplyPartyInvite; + clif->pReplyPartyInvite2 = clif_parse_ReplyPartyInvite2; + clif->pLeaveParty = clif_parse_LeaveParty; + clif->pRemovePartyMember = clif_parse_RemovePartyMember; + clif->pPartyChangeOption = clif_parse_PartyChangeOption; + clif->chann_config_read = read_channels_config; + clif->pPartyMessage = clif_parse_PartyMessage; + clif->pPartyChangeLeader = clif_parse_PartyChangeLeader; + clif->pPartyBookingRegisterReq = clif_parse_PartyBookingRegisterReq; + clif->pPartyBookingSearchReq = clif_parse_PartyBookingSearchReq; + clif->pPartyBookingDeleteReq = clif_parse_PartyBookingDeleteReq; + clif->pPartyBookingUpdateReq = clif_parse_PartyBookingUpdateReq; + clif->pCloseVending = clif_parse_CloseVending; + clif->pVendingListReq = clif_parse_VendingListReq; + clif->pPurchaseReq = clif_parse_PurchaseReq; + clif->pPurchaseReq2 = clif_parse_PurchaseReq2; + clif->pOpenVending = clif_parse_OpenVending; + clif->pCreateGuild = clif_parse_CreateGuild; + clif->pGuildCheckMaster = clif_parse_GuildCheckMaster; + clif->pGuildRequestInfo = clif_parse_GuildRequestInfo; + clif->pGuildChangePositionInfo = clif_parse_GuildChangePositionInfo; + clif->pGuildChangeMemberPosition = clif_parse_GuildChangeMemberPosition; + clif->pGuildRequestEmblem = clif_parse_GuildRequestEmblem; + clif->pGuildChangeEmblem = clif_parse_GuildChangeEmblem; + clif->pGuildChangeNotice = clif_parse_GuildChangeNotice; + clif->pGuildInvite = clif_parse_GuildInvite; + clif->pGuildReplyInvite = clif_parse_GuildReplyInvite; + clif->pGuildLeave = clif_parse_GuildLeave; + clif->pGuildExpulsion = clif_parse_GuildExpulsion; + clif->pGuildMessage = clif_parse_GuildMessage; + clif->pGuildRequestAlliance = clif_parse_GuildRequestAlliance; + clif->pGuildReplyAlliance = clif_parse_GuildReplyAlliance; + clif->pGuildDelAlliance = clif_parse_GuildDelAlliance; + clif->pGuildOpposition = clif_parse_GuildOpposition; + clif->pGuildBreak = clif_parse_GuildBreak; + clif->pPetMenu = clif_parse_PetMenu; + clif->pCatchPet = clif_parse_CatchPet; + clif->pSelectEgg = clif_parse_SelectEgg; + clif->pSendEmotion = clif_parse_SendEmotion; + clif->pChangePetName = clif_parse_ChangePetName; + clif->pGMKick = clif_parse_GMKick; + clif->pGMKickAll = clif_parse_GMKickAll; + clif->pGMShift = clif_parse_GMShift; + clif->pGMRemove2 = clif_parse_GMRemove2; + clif->pGMRecall = clif_parse_GMRecall; + clif->pGMRecall2 = clif_parse_GMRecall2; + clif->pGM_Monster_Item = clif_parse_GM_Monster_Item; + clif->pGMHide = clif_parse_GMHide; + clif->pGMReqNoChat = clif_parse_GMReqNoChat; + clif->pGMRc = clif_parse_GMRc; + clif->pGMReqAccountName = clif_parse_GMReqAccountName; + clif->pGMChangeMapType = clif_parse_GMChangeMapType; + clif->pPMIgnore = clif_parse_PMIgnore; + clif->pPMIgnoreAll = clif_parse_PMIgnoreAll; + clif->pPMIgnoreList = clif_parse_PMIgnoreList; + clif->pNoviceDoriDori = clif_parse_NoviceDoriDori; + clif->pNoviceExplosionSpirits = clif_parse_NoviceExplosionSpirits; + clif->pFriendsListAdd = clif_parse_FriendsListAdd; + clif->pFriendsListReply = clif_parse_FriendsListReply; + clif->pFriendsListRemove = clif_parse_FriendsListRemove; + clif->pPVPInfo = clif_parse_PVPInfo; + clif->pBlacksmith = clif_parse_Blacksmith; + clif->pAlchemist = clif_parse_Alchemist; + clif->pTaekwon = clif_parse_Taekwon; + clif->pRankingPk = clif_parse_RankingPk; + clif->pFeelSaveOk = clif_parse_FeelSaveOk; + clif->pChangeHomunculusName = clif_parse_ChangeHomunculusName; + clif->pHomMoveToMaster = clif_parse_HomMoveToMaster; + clif->pHomMoveTo = clif_parse_HomMoveTo; + clif->pHomAttack = clif_parse_HomAttack; + clif->pHomMenu = clif_parse_HomMenu; + clif->pAutoRevive = clif_parse_AutoRevive; + clif->pCheck = clif_parse_Check; + clif->pMail_refreshinbox = clif_parse_Mail_refreshinbox; + clif->pMail_read = clif_parse_Mail_read; + clif->pMail_getattach = clif_parse_Mail_getattach; + clif->pMail_delete = clif_parse_Mail_delete; + clif->pMail_return = clif_parse_Mail_return; + clif->pMail_setattach = clif_parse_Mail_setattach; + clif->pMail_winopen = clif_parse_Mail_winopen; + clif->pMail_send = clif_parse_Mail_send; + clif->pAuction_cancelreg = clif_parse_Auction_cancelreg; + clif->pAuction_setitem = clif_parse_Auction_setitem; + clif->pAuction_register = clif_parse_Auction_register; + clif->pAuction_cancel = clif_parse_Auction_cancel; + clif->pAuction_close = clif_parse_Auction_close; + clif->pAuction_bid = clif_parse_Auction_bid; + clif->pAuction_search = clif_parse_Auction_search; + clif->pAuction_buysell = clif_parse_Auction_buysell; + clif->pcashshop_buy = clif_parse_cashshop_buy; + clif->pAdopt_request = clif_parse_Adopt_request; + clif->pAdopt_reply = clif_parse_Adopt_reply; + clif->pViewPlayerEquip = clif_parse_ViewPlayerEquip; + clif->pEquipTick = clif_parse_EquipTick; + clif->pquestStateAck = clif_parse_questStateAck; + clif->pmercenary_action = clif_parse_mercenary_action; + clif->pBattleChat = clif_parse_BattleChat; + clif->pLessEffect = clif_parse_LessEffect; + clif->pItemListWindowSelected = clif_parse_ItemListWindowSelected; + clif->pReqOpenBuyingStore = clif_parse_ReqOpenBuyingStore; + clif->pReqCloseBuyingStore = clif_parse_ReqCloseBuyingStore; + clif->pReqClickBuyingStore = clif_parse_ReqClickBuyingStore; + clif->pReqTradeBuyingStore = clif_parse_ReqTradeBuyingStore; + clif->pSearchStoreInfo = clif_parse_SearchStoreInfo; + clif->pSearchStoreInfoNextPage = clif_parse_SearchStoreInfoNextPage; + clif->pCloseSearchStoreInfo = clif_parse_CloseSearchStoreInfo; + clif->pSearchStoreInfoListItemClick = clif_parse_SearchStoreInfoListItemClick; + clif->pDebug = clif_parse_debug; + clif->pSkillSelectMenu = clif_parse_SkillSelectMenu; + clif->pMoveItem = clif_parse_MoveItem; + /* RagExe Cash Shop [Ind/Hercules] */ + clif->pCashShopOpen = clif_parse_CashShopOpen; + clif->pCashShopClose = clif_parse_CashShopClose; + clif->pCashShopReqTab = clif_parse_CashShopReqTab; + clif->pCashShopSchedule = clif_parse_CashShopSchedule; + clif->pCashShopBuy = clif_parse_CashShopBuy; + /* */ + clif->pPartyTick = clif_parse_PartyTick; + clif->pGuildInvite2 = clif_parse_GuildInvite2; + /* dull */ + clif->pDull = clif_parse_dull; } diff --git a/src/map/clif.h b/src/map/clif.h index cd7fbdb35..3e3db98c1 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -1,19 +1,27 @@ -// 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 _CLIF_H_ #define _CLIF_H_ #include "../common/cbasetypes.h" -//#include "../common/mmo.h" +#include "../common/db.h" +#include "../common/mmo.h" +#include <stdarg.h> + +/** + * Declarations + **/ struct item; +struct item_data; struct storage_data; struct guild_storage; -//#include "map.h" struct block_list; struct unit_data; struct map_session_data; struct homun_data; +struct mercenary_data; struct pet_data; struct mob_data; struct npc_data; @@ -27,27 +35,24 @@ struct guild; struct battleground_data; struct quest; struct party_booking_ad_info; -#include <stdarg.h> +struct view_data; +struct eri; -enum -{// packet DB - MAX_PACKET_DB = 0xA00, - MAX_PACKET_VER = 30, - MAX_PACKET_POS = 20, -}; +/** + * Defines + **/ +#define packet_len(cmd) packet_db[cmd].len +#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0; +#define HCHSYS_NAME_LENGTH 20 -struct s_packet_db { - short len; - void (*func)(int, struct map_session_data *); - short pos[MAX_PACKET_POS]; +/** + * Enumerations + **/ +enum {// packet DB + MAX_PACKET_DB = 0xF00, + MAX_PACKET_POS = 20, }; -// packet_db[SERVER] is reserved for server use -#define SERVER 0 -#define packet_len(cmd) packet_db[SERVER][cmd].len -extern struct s_packet_db packet_db[MAX_PACKET_VER+1][MAX_PACKET_DB+1]; - -// local define typedef enum send_target { ALL_CLIENT, ALL_SAMEMAP, @@ -73,8 +78,8 @@ typedef enum send_target { GUILD_NOBG, DUEL, DUEL_WOS, - CHAT_MAINCHAT, // everyone on main chat SELF, + BG, // BattleGround System BG_WOS, BG_SAMEMAP, @@ -83,8 +88,7 @@ typedef enum send_target { BG_AREA_WOS, } send_target; -typedef enum emotion_type -{ +typedef enum emotion_type { E_GASP = 0, // /! E_WHAT, // /? E_HO, @@ -173,12 +177,11 @@ typedef enum emotion_type E_YUT5, E_YUT6, E_YUT7, - // + /* ... */ E_MAX } emotion_type; -typedef enum clr_type -{ +typedef enum clr_type { CLR_OUTSIGHT = 0, CLR_DEAD, CLR_RESPAWN, @@ -186,8 +189,7 @@ typedef enum clr_type CLR_TRICKDEAD, } clr_type; -enum map_property -{// clif_map_property +enum map_property { // clif_map_property MAPPROPERTY_NOTHING = 0, MAPPROPERTY_FREEPVPZONE = 1, MAPPROPERTY_EVENTPVPZONE = 2, @@ -197,8 +199,7 @@ enum map_property MAPPROPERTY_DENYSKILLZONE = 6, }; -enum map_type -{// clif_map_type +enum map_type { // clif_map_type MAPTYPE_VILLAGE = 0, MAPTYPE_VILLAGE_IN = 1, MAPTYPE_FIELD = 2, @@ -226,8 +227,7 @@ enum map_type MAPTYPE_UNUSED = 29, }; -enum useskill_fail_cause -{// clif_skill_fail +enum useskill_fail_cause { // clif_skill_fail USESKILL_FAIL_LEVEL = 0, USESKILL_FAIL_SP_INSUFFICIENT = 1, USESKILL_FAIL_HP_INSUFFICIENT = 2, @@ -314,459 +314,782 @@ enum useskill_fail_cause USESKILL_FAIL_THERE_ARE_NPC_AROUND = 83, }; -int clif_setip(const char* ip); -void clif_setbindip(const char* ip); -void clif_setport(uint16 port); - -uint32 clif_getip(void); -uint32 clif_refresh_ip(void); -uint16 clif_getport(void); - -void clif_authok(struct map_session_data *sd); -void clif_authrefuse(int fd, uint8 error_code); -void clif_authfail_fd(int fd, int type); -void clif_charselectok(int id, uint8 ok); -void clif_dropflooritem(struct flooritem_data* fitem); -void clif_clearflooritem(struct flooritem_data *fitem, int fd); - -void clif_clearunit_single(int id, clr_type type, int fd); -void clif_clearunit_area(struct block_list* bl, clr_type type); -void clif_clearunit_delayed(struct block_list* bl, clr_type type, unsigned int tick); -int clif_spawn(struct block_list *bl); //area -void clif_walkok(struct map_session_data *sd); // self -void clif_move(struct unit_data *ud); //area -void clif_changemap(struct map_session_data *sd, short map, int x, int y); //self -void clif_changemapserver(struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port); //self -void clif_blown(struct block_list *bl); // area -void clif_slide(struct block_list *bl, int x, int y); // area -void clif_fixpos(struct block_list *bl); // area -void clif_npcbuysell(struct map_session_data* sd, int id); //self -void clif_buylist(struct map_session_data *sd, struct npc_data *nd); //self -void clif_selllist(struct map_session_data *sd); //self -void clif_scriptmes(struct map_session_data *sd, int npcid, const char *mes); //self -void clif_scriptnext(struct map_session_data *sd,int npcid); //self -void clif_scriptclose(struct map_session_data *sd, int npcid); //self -void clif_scriptmenu(struct map_session_data* sd, int npcid, const char* mes); //self -void clif_scriptinput(struct map_session_data *sd, int npcid); //self -void clif_scriptinputstr(struct map_session_data *sd, int npcid); // self -void clif_cutin(struct map_session_data* sd, const char* image, int type); //self -void clif_viewpoint(struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color); //self -void clif_additem(struct map_session_data *sd, int n, int amount, int fail); // self -void clif_dropitem(struct map_session_data *sd,int n,int amount); //self -void clif_delitem(struct map_session_data *sd,int n,int amount, short reason); //self -void clif_updatestatus(struct map_session_data *sd,int type); //self -void clif_changestatus(struct map_session_data* sd,int type,int val); //area -int clif_damage(struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2); // area -void clif_takeitem(struct block_list* src, struct block_list* dst); -void clif_sitting(struct block_list* bl); -void clif_standing(struct block_list* bl); -void clif_changelook(struct block_list *bl,int type,int val); // area -void clif_changetraplook(struct block_list *bl,int val); // area -void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_target target); //area specified in 'target' -void clif_arrowequip(struct map_session_data *sd,int val); //self -void clif_arrow_fail(struct map_session_data *sd,int type); //self -void clif_arrow_create_list(struct map_session_data *sd); //self -void clif_statusupack(struct map_session_data *sd,int type,int ok,int val); // self -void clif_equipitemack(struct map_session_data *sd,int n,int pos,int ok); // self -void clif_unequipitemack(struct map_session_data *sd,int n,int pos,int ok); // self -void clif_misceffect(struct block_list* bl,int type); // area -void clif_changeoption(struct block_list* bl); // area -void clif_changeoption2(struct block_list* bl); // area -void clif_useitemack(struct map_session_data *sd,int index,int amount,bool ok); // self -void clif_GlobalMessage(struct block_list* bl, const char* message); -void clif_createchat(struct map_session_data* sd, int flag); // self -void clif_dispchat(struct chat_data* cd, int fd); // area or fd -void clif_joinchatfail(struct map_session_data *sd,int flag); // self -void clif_joinchatok(struct map_session_data *sd,struct chat_data* cd); // self -void clif_addchat(struct chat_data* cd,struct map_session_data *sd); // chat -void clif_changechatowner(struct chat_data* cd, struct map_session_data* sd); // chat -void clif_clearchat(struct chat_data *cd,int fd); // area or fd -void clif_leavechat(struct chat_data* cd, struct map_session_data* sd, bool flag); // chat -void clif_changechatstatus(struct chat_data* cd); // chat -void clif_refresh(struct map_session_data *sd); // self - -void clif_fame_blacksmith(struct map_session_data *sd, int points); -void clif_fame_alchemist(struct map_session_data *sd, int points); -void clif_fame_taekwon(struct map_session_data *sd, int points); - -void clif_emotion(struct block_list *bl,int type); -void clif_talkiebox(struct block_list* bl, const char* talkie); -void clif_wedding_effect(struct block_list *bl); -void clif_divorced(struct map_session_data* sd, const char* name); -void clif_callpartner(struct map_session_data *sd); -void clif_playBGM(struct map_session_data* sd, const char* name); -void clif_soundeffect(struct map_session_data* sd, struct block_list* bl, const char* name, int type); -void clif_soundeffectall(struct block_list* bl, const char* name, int type, enum send_target coverage); -void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type, int target_id, unsigned int tick); -void clif_parse_LoadEndAck(int fd,struct map_session_data *sd); -void clif_hotkeys_send(struct map_session_data *sd); - -// trade -void clif_traderequest(struct map_session_data* sd, const char* name); -void clif_tradestart(struct map_session_data* sd, uint8 type); -void clif_tradeadditem(struct map_session_data* sd, struct map_session_data* tsd, int index, int amount); -void clif_tradeitemok(struct map_session_data* sd, int index, int fail); -void clif_tradedeal_lock(struct map_session_data* sd, int fail); -void clif_tradecancelled(struct map_session_data* sd); -void clif_tradecompleted(struct map_session_data* sd, int fail); -void clif_tradeundo(struct map_session_data* sd); - -// storage -void clif_storagelist(struct map_session_data* sd, struct item* items, int items_length); -void clif_updatestorageamount(struct map_session_data* sd, int amount, int max_amount); -void clif_storageitemadded(struct map_session_data* sd, struct item* i, int index, int amount); -void clif_storageitemremoved(struct map_session_data* sd, int index, int amount); -void clif_storageclose(struct map_session_data* sd); - -int clif_insight(struct block_list *bl,va_list ap); // map_forallinmovearea callback -int clif_outsight(struct block_list *bl,va_list ap); // map_forallinmovearea callback - -void clif_class_change(struct block_list *bl,int class_,int type); -#define clif_mob_class_change(md, class_) clif_class_change(&md->bl, class_, 1) - -void clif_skillinfoblock(struct map_session_data *sd); -void clif_skillup(struct map_session_data *sd,uint16 skill_id); -void clif_skillinfo(struct map_session_data *sd,int skill, int inf); -void clif_addskill(struct map_session_data *sd, int id); -void clif_deleteskill(struct map_session_data *sd, int id); - -void clif_skillcasting(struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime); -void clif_skillcastcancel(struct block_list* bl); -void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype); -void clif_skill_cooldown(struct map_session_data *sd, uint16 skill_id, unsigned int tick); -int clif_skill_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type); -//int clif_skill_damage2(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type); -int clif_skill_nodamage(struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,int fail); -void clif_skill_poseffect(struct block_list *src,uint16 skill_id,int val,int x,int y,int tick); -void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst); -void clif_skill_warppoint(struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4); -void clif_skill_memomessage(struct map_session_data* sd, int type); -void clif_skill_teleportmessage(struct map_session_data *sd, int type); -void clif_skill_produce_mix_list(struct map_session_data *sd, int skill_id, int trigger); -void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id, int qty, int list_type); - -void clif_produceeffect(struct map_session_data* sd,int flag,int nameid); - -void clif_skill_setunit(struct skill_unit *unit); -void clif_skill_delunit(struct skill_unit *unit); - -void clif_skillunit_update(struct block_list* bl); - -void clif_autospell(struct map_session_data *sd,uint16 skill_lv); -void clif_devotion(struct block_list *src, struct map_session_data *tsd); -void clif_spiritball(struct block_list *bl); -void clif_combo_delay(struct block_list *bl,int wait); -void clif_bladestop(struct block_list *src, int dst_id, int active); -void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target); - -#define clif_status_load(bl, type, flag) clif_status_change((bl), (type), (flag), 0, 0, 0, 0) -void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3); - -void clif_wis_message(int fd, const char* nick, const char* mes, int mes_len); -void clif_wis_end(int fd, int flag); - -void clif_solved_charname(int fd, int charid, const char* name); -void clif_charnameack(int fd, struct block_list *bl); -void clif_charnameupdate(struct map_session_data *ssd); - -void clif_use_card(struct map_session_data *sd,int idx); -void clif_insert_card(struct map_session_data *sd,int idx_equip,int idx_card,int flag); - -void clif_inventorylist(struct map_session_data *sd); -void clif_equiplist(struct map_session_data *sd); - -void clif_cart_additem(struct map_session_data *sd,int n,int amount,int fail); -void clif_cart_delitem(struct map_session_data *sd,int n,int amount); -void clif_cartlist(struct map_session_data *sd); -void clif_clearcart(int fd); - -void clif_item_identify_list(struct map_session_data *sd); -void clif_item_identified(struct map_session_data *sd,int idx,int flag); -void clif_item_repair_list(struct map_session_data *sd, struct map_session_data *dstsd, int lv); -void clif_item_repaireffect(struct map_session_data *sd, int idx, int flag); -void clif_item_damaged(struct map_session_data* sd, unsigned short position); -void clif_item_refine_list(struct map_session_data *sd); - -void clif_item_skill(struct map_session_data *sd,uint16 skill_id,uint16 skill_lv); - -void clif_mvp_effect(struct map_session_data *sd); -void clif_mvp_item(struct map_session_data *sd,int nameid); -void clif_mvp_exp(struct map_session_data *sd, unsigned int exp); -void clif_mvp_noitem(struct map_session_data* sd); -void clif_changed_dir(struct block_list *bl, enum send_target target); - -// vending -void clif_openvendingreq(struct map_session_data* sd, int num); -void clif_showvendingboard(struct block_list* bl, const char* message, int fd); -void clif_closevendingboard(struct block_list* bl, int fd); -void clif_vendinglist(struct map_session_data* sd, int id, struct s_vending* vending); -void clif_buyvending(struct map_session_data* sd, int index, int amount, int fail); -void clif_openvending(struct map_session_data* sd, int id, struct s_vending* vending); -void clif_vendingreport(struct map_session_data* sd, int index, int amount); - -void clif_movetoattack(struct map_session_data *sd,struct block_list *bl); - -// party -void clif_party_created(struct map_session_data *sd,int result); -void clif_party_member_info(struct party_data *p, struct map_session_data *sd); -void clif_party_info(struct party_data* p, struct map_session_data *sd); -void clif_party_invite(struct map_session_data *sd,struct map_session_data *tsd); -void clif_party_inviteack(struct map_session_data* sd, const char* nick, int result); -void clif_party_option(struct party_data *p,struct map_session_data *sd,int flag); -void clif_party_withdraw(struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag); -void clif_party_message(struct party_data* p, int account_id, const char* mes, int len); -void clif_party_xy(struct map_session_data *sd); -void clif_party_xy_single(int fd, struct map_session_data *sd); -void clif_party_hp(struct map_session_data *sd); -void clif_hpmeter_single(int fd, int id, unsigned int hp, unsigned int maxhp); - -// guild -void clif_guild_created(struct map_session_data *sd,int flag); -void clif_guild_belonginfo(struct map_session_data *sd, struct guild *g); -void clif_guild_masterormember(struct map_session_data *sd); -void clif_guild_basicinfo(struct map_session_data *sd); -void clif_guild_allianceinfo(struct map_session_data *sd); -void clif_guild_memberlist(struct map_session_data *sd); -void clif_guild_skillinfo(struct map_session_data* sd); -void clif_guild_send_onlineinfo(struct map_session_data *sd); //[LuzZza] -void clif_guild_memberlogin_notice(struct guild *g,int idx,int flag); -void clif_guild_invite(struct map_session_data *sd,struct guild *g); -void clif_guild_inviteack(struct map_session_data *sd,int flag); -void clif_guild_leave(struct map_session_data *sd,const char *name,const char *mes); -void clif_guild_expulsion(struct map_session_data* sd, const char* name, const char* mes, int account_id); -void clif_guild_positionchanged(struct guild *g,int idx); -void clif_guild_memberpositionchanged(struct guild *g,int idx); -void clif_guild_emblem(struct map_session_data *sd,struct guild *g); -void clif_guild_emblem_area(struct block_list* bl); -void clif_guild_notice(struct map_session_data* sd, struct guild* g); -void clif_guild_message(struct guild *g,int account_id,const char *mes,int len); -int clif_guild_skillup(struct map_session_data *sd,uint16 skill_id,int lv); -void clif_guild_reqalliance(struct map_session_data *sd,int account_id,const char *name); -void clif_guild_allianceack(struct map_session_data *sd,int flag); -void clif_guild_delalliance(struct map_session_data *sd,int guild_id,int flag); -void clif_guild_oppositionack(struct map_session_data *sd,int flag); -void clif_guild_broken(struct map_session_data *sd,int flag); -void clif_guild_xy(struct map_session_data *sd); -void clif_guild_xy_single(int fd, struct map_session_data *sd); -void clif_guild_xy_remove(struct map_session_data *sd); - -// Battleground -void clif_bg_hp(struct map_session_data *sd); -void clif_bg_xy(struct map_session_data *sd); -void clif_bg_xy_remove(struct map_session_data *sd); -void clif_bg_message(struct battleground_data *bg, int src_id, const char *name, const char *mes, int len); -void clif_bg_updatescore(int16 m); -void clif_bg_updatescore_single(struct map_session_data *sd); -void clif_sendbgemblem_area(struct map_session_data *sd); -void clif_sendbgemblem_single(int fd, struct map_session_data *sd); - -// Instancing -int clif_instance(int instance_id, int type, int flag); -void clif_instance_join(int fd, int instance_id); -void clif_instance_leave(int fd); - -// Custom Fonts -void clif_font(struct map_session_data *sd); - -// atcommand -void clif_displaymessage(const int fd, const char* mes); -void clif_disp_onlyself(struct map_session_data *sd, const char *mes, int len); -void clif_disp_message(struct block_list* src, const char* mes, int len, enum send_target target); -void clif_broadcast(struct block_list* bl, const char* mes, int len, int type, enum send_target target); -void clif_MainChatMessage(const char* message); -void clif_broadcast2(struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target); -void clif_heal(int fd,int type,int val); -void clif_resurrection(struct block_list *bl,int type); -void clif_map_property(struct map_session_data* sd, enum map_property property); -void clif_pvpset(struct map_session_data *sd, int pvprank, int pvpnum,int type); -void clif_map_property_mapall(int map, enum map_property property); -void clif_refine(int fd, int fail, int index, int val); -void clif_upgrademessage(int fd, int result, int item_id); - -//petsystem -void clif_catch_process(struct map_session_data *sd); -void clif_pet_roulette(struct map_session_data *sd,int data); -void clif_sendegg(struct map_session_data *sd); -void clif_send_petstatus(struct map_session_data *sd); -void clif_send_petdata(struct map_session_data* sd, struct pet_data* pd, int type, int param); -#define clif_pet_equip(sd, pd) clif_send_petdata(sd, pd, 3, (pd)->vd.head_bottom) -#define clif_pet_equip_area(pd) clif_send_petdata(NULL, pd, 3, (pd)->vd.head_bottom) -#define clif_pet_performance(pd, param) clif_send_petdata(NULL, pd, 4, param) -void clif_pet_emotion(struct pet_data *pd,int param); -void clif_pet_food(struct map_session_data *sd,int foodid,int fail); - -//friends list -int clif_friendslist_toggle_sub(struct map_session_data *sd,va_list ap); -void clif_friendslist_send(struct map_session_data *sd); -void clif_friendslist_reqack(struct map_session_data *sd, struct map_session_data *f_sd, int type); - -void clif_weather(int16 m); // [Valaris] -void clif_specialeffect(struct block_list* bl, int type, enum send_target target); // special effects [Valaris] -void clif_specialeffect_single(struct block_list* bl, int type, int fd); -void clif_messagecolor(struct block_list* bl, unsigned long color, const char* msg); // Mob/Npc color talk [SnakeDrak] -void clif_message(struct block_list* bl, const char* msg); -void clif_specialeffect_value(struct block_list* bl, int effect_id, int num, send_target target); - -void clif_GM_kickack(struct map_session_data *sd, int id); -void clif_GM_kick(struct map_session_data *sd,struct map_session_data *tsd); -void clif_manner_message(struct map_session_data* sd, uint32 type); -void clif_GM_silence(struct map_session_data* sd, struct map_session_data* tsd, uint8 type); - -void clif_disp_overhead(struct map_session_data *sd, const char* mes); - -void clif_get_weapon_view(struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand); - -void clif_party_xy_remove(struct map_session_data *sd); //Fix for minimap [Kevin] -void clif_gospel_info(struct map_session_data *sd, int type); -void clif_feel_req(int fd, struct map_session_data *sd, uint16 skill_lv); -void clif_starskill(struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result); -void clif_feel_info(struct map_session_data* sd, unsigned char feel_level, unsigned char type); -void clif_hate_info(struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type); -void clif_mission_info(struct map_session_data *sd, int mob_id, unsigned char progress); -void clif_feel_hate_reset(struct map_session_data *sd); - -// [blackhole89] -void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag); -int clif_homskillinfoblock(struct map_session_data *sd); -void clif_homskillup(struct map_session_data *sd, uint16 skill_id); //[orn] -int clif_hom_food(struct map_session_data *sd,int foodid,int fail); //[orn] -void clif_send_homdata(struct map_session_data *sd, int state, int param); //[orn] - -void clif_equiptickack(struct map_session_data* sd, int flag); -void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* tsd); -void clif_viewequip_fail(struct map_session_data* sd); -void clif_equipcheckbox(struct map_session_data* sd); - -void clif_msg(struct map_session_data* sd, unsigned short id); -void clif_msg_value(struct map_session_data* sd, unsigned short id, int value); -void clif_msg_skill(struct map_session_data* sd, uint16 skill_id, int msg_id); - -//quest system [Kevin] [Inkfish] -void clif_quest_send_list(struct map_session_data * sd); -void clif_quest_send_mission(struct map_session_data * sd); -void clif_quest_add(struct map_session_data * sd, struct quest * qd, int index); -void clif_quest_delete(struct map_session_data * sd, int quest_id); -void clif_quest_update_status(struct map_session_data * sd, int quest_id, bool active); -void clif_quest_update_objective(struct map_session_data * sd, struct quest * qd, int index); -void clif_quest_show_event(struct map_session_data *sd, struct block_list *bl, short state, short color); -void clif_displayexp(struct map_session_data *sd, unsigned int exp, char type, bool quest); - -int clif_send(const uint8* buf, int len, struct block_list* bl, enum send_target type); -int do_init_clif(void); -void do_final_clif(void); - -// MAIL SYSTEM -void clif_Mail_window(int fd, int flag); -void clif_Mail_read(struct map_session_data *sd, int mail_id); -void clif_Mail_delete(int fd, int mail_id, short fail); -void clif_Mail_return(int fd, int mail_id, short fail); -void clif_Mail_send(int fd, bool fail); -void clif_Mail_new(int fd, int mail_id, const char *sender, const char *title); -void clif_Mail_refreshinbox(struct map_session_data *sd); -void clif_Mail_getattachment(int fd, uint8 flag); -// AUCTION SYSTEM -void clif_Auction_openwindow(struct map_session_data *sd); -void clif_Auction_results(struct map_session_data *sd, short count, short pages, uint8 *buf); -void clif_Auction_message(int fd, unsigned char flag); -void clif_Auction_close(int fd, unsigned char flag); -void clif_parse_Auction_cancelreg(int fd, struct map_session_data *sd); - -void clif_bossmapinfo(int fd, struct mob_data *md, short flag); -void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd); - -// ADOPTION -void clif_Adopt_reply(struct map_session_data *sd, int type); - -// MERCENARIES -void clif_mercenary_info(struct map_session_data *sd); -void clif_mercenary_skillblock(struct map_session_data *sd); -void clif_mercenary_message(struct map_session_data* sd, int message); -void clif_mercenary_updatestatus(struct map_session_data *sd, int type); - -// RENTAL SYSTEM -void clif_rental_time(int fd, int nameid, int seconds); -void clif_rental_expired(int fd, int index, int nameid); - -// BOOK READING -void clif_readbook(int fd, int book_id, int page); - -// Show Picker -void clif_party_show_picker(struct map_session_data * sd, struct item * item_data); - -// Progress Bar [Inkfish] -void clif_progressbar(struct map_session_data * sd, unsigned long color, unsigned int second); -void clif_progressbar_abort(struct map_session_data * sd); - -void clif_PartyBookingRegisterAck(struct map_session_data *sd, int flag); -void clif_PartyBookingDeleteAck(struct map_session_data* sd, int flag); -void clif_PartyBookingSearchAck(int fd, struct party_booking_ad_info** results, int count, bool more_result); -void clif_PartyBookingUpdateNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad); -void clif_PartyBookingDeleteNotify(struct map_session_data* sd, int index); -void clif_PartyBookingInsertNotify(struct map_session_data* sd, struct party_booking_ad_info* pb_ad); - -void clif_showdigit(struct map_session_data* sd, unsigned char type, int value); - -/// Buying Store System -void clif_buyingstore_open(struct map_session_data* sd); -void clif_buyingstore_open_failed(struct map_session_data* sd, unsigned short result, unsigned int weight); -void clif_buyingstore_myitemlist(struct map_session_data* sd); -void clif_buyingstore_entry(struct map_session_data* sd); -void clif_buyingstore_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd); -void clif_buyingstore_disappear_entry(struct map_session_data* sd); -void clif_buyingstore_disappear_entry_single(struct map_session_data* sd, struct map_session_data* pl_sd); -void clif_buyingstore_itemlist(struct map_session_data* sd, struct map_session_data* pl_sd); -void clif_buyingstore_trade_failed_buyer(struct map_session_data* sd, short result); -void clif_buyingstore_update_item(struct map_session_data* sd, unsigned short nameid, unsigned short amount); -void clif_buyingstore_delete_item(struct map_session_data* sd, short index, unsigned short amount, int price); -void clif_buyingstore_trade_failed_seller(struct map_session_data* sd, short result, unsigned short nameid); +enum clif_messages { + SKILL_CANT_USE_AREA = 0x536, +}; -/// Search Store System -void clif_search_store_info_ack(struct map_session_data* sd); -void clif_search_store_info_failed(struct map_session_data* sd, unsigned char reason); -void clif_open_search_store_info(struct map_session_data* sd); -void clif_search_store_info_click_ack(struct map_session_data* sd, short x, short y); /** - * 3CeAM + * Color Table **/ -void clif_msgtable(int fd, int line); -void clif_msgtable_num(int fd, int line, int num); - -int clif_elementalconverter_list(struct map_session_data *sd); - -void clif_millenniumshield(struct map_session_data *sd, short shields ); - -int clif_spellbook_list(struct map_session_data *sd); +enum clif_colors { + COLOR_RED, + COLOR_DEFAULT, + COLOR_WHITE, + COLOR_MAX +}; -int clif_magicdecoy_list(struct map_session_data *sd, uint16 skill_lv, short x, short y); +enum hChSysChOpt { + hChSys_OPT_BASE = 0x0, + hChSys_OPT_ANNOUNCE_JOIN = 0x1, + hChSys_OPT_MSG_DELAY = 0x2, +}; -int clif_poison_list(struct map_session_data *sd, uint16 skill_lv); +enum hChSysChType { + hChSys_PUBLIC = 0, + hChSys_PRIVATE = 1, + hChSys_MAP = 2, + hChSys_ALLY = 3, + hChSys_IRC = 4, +}; -int clif_autoshadowspell_list(struct map_session_data *sd); +enum CASH_SHOP_TABS { + CASHSHOP_TAB_NEW = 0, + CASHSHOP_TAB_POPULAR = 1, + CASHSHOP_TAB_LIMITED = 2, + CASHSHOP_TAB_RENTAL = 3, + CASHSHOP_TAB_PERPETUITY = 4, + CASHSHOP_TAB_BUFF = 5, + CASHSHOP_TAB_RECOVERY = 6, + CASHSHOP_TAB_ETC = 7, + CASHSHOP_TAB_MAX, +}; -int clif_status_load_notick(struct block_list *bl,int type,int flag,int val1, int val2, int val3); -int clif_status_load_single(int fd, int id,int type,int flag,int val1, int val2, int val3); +enum CASH_SHOP_BUY_RESULT { + CSBR_SUCCESS = 0x0, + CSBR_SHORTTAGE_CASH = 0x2, + CSBR_UNKONWN_ITEM = 0x3, + CSBR_INVENTORY_WEIGHT = 0x4, + CSBR_INVENTORY_ITEMCNT = 0x5, + CSBR_RUNE_OVERCOUNT = 0x9, + CSBR_EACHITEM_OVERCOUNT = 0xa, + CSBR_UNKNOWN = 0xb, +}; +/** + * Structures + **/ +typedef void (*pFunc)(int, struct map_session_data *); //cant help but put it first +struct s_packet_db { + short len; + pFunc func; + short pos[MAX_PACKET_POS]; +}; -int clif_skill_itemlistwindow( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv ); -void clif_elemental_info(struct map_session_data *sd); -void clif_elemental_updatestatus(struct map_session_data *sd, int type); +struct { + unsigned long *colors; + char **colors_name; + unsigned char colors_count; + bool local, ally, irc; + bool local_autojoin, ally_autojoin; + char local_name[HCHSYS_NAME_LENGTH], ally_name[HCHSYS_NAME_LENGTH], irc_name[HCHSYS_NAME_LENGTH]; + unsigned char local_color, ally_color, irc_color; + bool closing; + bool allow_user_channel_creation; + char irc_server[40], irc_channel[20], irc_nick[30], irc_nick_pw[30]; + unsigned short irc_server_port; +} hChSys; + +struct hChSysBanEntry { + char name[NAME_LENGTH]; +}; -void clif_talisman(struct map_session_data *sd, short type); +struct hChSysCh { + char name[HCHSYS_NAME_LENGTH]; + char pass[HCHSYS_NAME_LENGTH]; + unsigned char color; + DBMap *users; + DBMap *banned; + unsigned int opt; + unsigned int owner; + enum hChSysChType type; + uint16 m; + unsigned char msg_delay; +}; -void clif_snap( struct block_list *bl, short x, short y ); -void clif_monster_hp_bar( struct mob_data* md, int fd ); +struct hCSData { + unsigned short id; + unsigned int price; +}; /** - * Color Table + * Vars **/ -enum clif_colors { - COLOR_RED, - - COLOR_MAX -}; +struct s_packet_db packet_db[MAX_PACKET_DB + 1]; unsigned long color_table[COLOR_MAX]; -int clif_colormes(struct map_session_data * sd, enum clif_colors color, const char* msg); -#define clif_menuskill_clear(sd) (sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0; +/** + * Clif.c Interface + **/ +struct clif_interface { + /* vars */ + uint32 map_ip; + uint32 bind_ip; + uint16 map_port; + char map_ip_str[128]; + int map_fd; + DBMap* channel_db; + /* for clif_clearunit_delayed */ + struct eri *delay_clearunit_ers; + /* Cash Shop [Ind/Hercules] */ + struct { + struct hCSData **data[CASHSHOP_TAB_MAX]; + unsigned int item_count[CASHSHOP_TAB_MAX]; + } cs; + /* core */ + int (*init) (void); + void (*final) (void); + int (*setip) (const char* ip); + void (*setbindip) (const char* ip); + void (*setport) (uint16 port); + uint32 (*refresh_ip) (void); + int (*send) (const void* buf, int len, struct block_list* bl, enum send_target type); + int (*send_sub) (struct block_list *bl, va_list ap); + int (*parse) (int fd); + /* auth */ + void (*authok) (struct map_session_data *sd); + void (*authrefuse) (int fd, uint8 error_code); + void (*authfail_fd) (int fd, int type); + void (*charselectok) (int id, uint8 ok); + /* item-related */ + void (*dropflooritem) (struct flooritem_data* fitem); + void (*clearflooritem) (struct flooritem_data *fitem, int fd); + void (*additem) (struct map_session_data *sd, int n, int amount, int fail); + void (*dropitem) (struct map_session_data *sd,int n,int amount); + void (*delitem) (struct map_session_data *sd,int n,int amount, short reason); + void (*takeitem) (struct block_list* src, struct block_list* dst); + void (*arrowequip) (struct map_session_data *sd,int val); + void (*arrow_fail) (struct map_session_data *sd,int type); + void (*use_card) (struct map_session_data *sd,int idx); + void (*cart_additem) (struct map_session_data *sd,int n,int amount,int fail); + void (*cart_delitem) (struct map_session_data *sd,int n,int amount); + void (*equipitemack) (struct map_session_data *sd,int n,int pos,int ok); + void (*unequipitemack) (struct map_session_data *sd,int n,int pos,int ok); + void (*useitemack) (struct map_session_data *sd,int index,int amount,bool ok); + void (*addcards) (unsigned char* buf, struct item* item); + void (*addcards2) (unsigned short *cards, struct item* item); + void (*item_sub) (unsigned char *buf, int n, struct item *i, struct item_data *id, int equip); + void (*getareachar_item) (struct map_session_data* sd,struct flooritem_data* fitem); + void (*cashshop_load) (void); + /* unit-related */ + void (*clearunit_single) (int id, clr_type type, int fd); + void (*clearunit_area) (struct block_list* bl, clr_type type); + void (*clearunit_delayed) (struct block_list* bl, clr_type type, unsigned int tick); + void (*walkok) (struct map_session_data *sd); + void (*move) (struct unit_data *ud); + void (*move2) (struct block_list *bl, struct view_data *vd, struct unit_data *ud); + void (*blown) (struct block_list *bl); + void (*slide) (struct block_list *bl, int x, int y); + void (*fixpos) (struct block_list *bl); + void (*changelook) (struct block_list *bl,int type,int val); + void (*changetraplook) (struct block_list *bl,int val); + void (*refreshlook) (struct block_list *bl,int id,int type,int val,enum send_target target); + void (*class_change) (struct block_list *bl,int class_,int type); + void (*skill_setunit) (struct skill_unit *unit); + void (*skill_delunit) (struct skill_unit *unit); + void (*skillunit_update) (struct block_list* bl); + int (*clearunit_delayed_sub) (int tid, unsigned int tick, int id, intptr_t data); + void (*set_unit_idle) (struct block_list* bl, struct map_session_data *tsd,enum send_target target); + void (*spawn_unit) (struct block_list* bl,enum send_target target); + void (*set_unit_walking) (struct block_list* bl, struct map_session_data *tsd,struct unit_data* ud, enum send_target target); + int (*calc_walkdelay) (struct block_list *bl,int delay, int type, int damage, int div_); + void (*getareachar_skillunit) (struct map_session_data *sd, struct skill_unit *unit); + void (*getareachar_unit) (struct map_session_data* sd,struct block_list *bl); + void (*clearchar_skillunit) (struct skill_unit *unit, int fd); + int (*getareachar) (struct block_list* bl,va_list ap); + /* main unit spawn */ + int (*spawn) (struct block_list *bl); + /* map-related */ + void (*changemap) (struct map_session_data *sd, short map, int x, int y); + void (*changemapcell) (int fd, int16 m, int x, int y, int type, enum send_target target); + void (*map_property) (struct map_session_data* sd, enum map_property property); + void (*pvpset) (struct map_session_data *sd, int pvprank, int pvpnum,int type); + void (*map_property_mapall) (int map, enum map_property property); + void (*bossmapinfo) (int fd, struct mob_data *md, short flag); + void (*map_type) (struct map_session_data* sd, enum map_type type); + void (*maptypeproperty2) (struct block_list *bl,enum send_target t); + /* multi-map-server */ + void (*changemapserver) (struct map_session_data* sd, unsigned short map_index, int x, int y, uint32 ip, uint16 port); + /* npc-shop-related */ + void (*npcbuysell) (struct map_session_data* sd, int id); + void (*buylist) (struct map_session_data *sd, struct npc_data *nd); + void (*selllist) (struct map_session_data *sd); + void (*cashshop_show) (struct map_session_data *sd, struct npc_data *nd); + void (*npc_buy_result) (struct map_session_data* sd, unsigned char result); + void (*npc_sell_result) (struct map_session_data* sd, unsigned char result); + void (*cashshop_ack) (struct map_session_data* sd, int error); + /* npc-script-related */ + void (*scriptmes) (struct map_session_data *sd, int npcid, const char *mes); + void (*scriptnext) (struct map_session_data *sd,int npcid); + void (*scriptclose) (struct map_session_data *sd, int npcid); + void (*scriptmenu) (struct map_session_data* sd, int npcid, const char* mes); + void (*scriptinput) (struct map_session_data *sd, int npcid); + void (*scriptinputstr) (struct map_session_data *sd, int npcid); + void (*cutin) (struct map_session_data* sd, const char* image, int type); + void (*sendfakenpc) (struct map_session_data *sd, int npcid); + /* client-user-interface-related */ + void (*viewpoint) (struct map_session_data *sd, int npc_id, int type, int x, int y, int id, int color); + int (*damage) (struct block_list* src, struct block_list* dst, unsigned int tick, int sdelay, int ddelay, int damage, int div, int type, int damage2); + void (*sitting) (struct block_list* bl); + void (*standing) (struct block_list* bl); + void (*arrow_create_list) (struct map_session_data *sd); + void (*refresh) (struct map_session_data *sd); + void (*fame_blacksmith) (struct map_session_data *sd, int points); + void (*fame_alchemist) (struct map_session_data *sd, int points); + void (*fame_taekwon) (struct map_session_data *sd, int points); + void (*hotkeys) (struct map_session_data *sd); + int (*insight) (struct block_list *bl,va_list ap); + int (*outsight) (struct block_list *bl,va_list ap); + void (*skillcastcancel) (struct block_list* bl); + void (*skill_fail) (struct map_session_data *sd,uint16 skill_id,enum useskill_fail_cause cause,int btype); + void (*skill_cooldown) (struct map_session_data *sd, uint16 skill_id, unsigned int tick); + void (*skill_memomessage) (struct map_session_data* sd, int type); + void (*skill_teleportmessage) (struct map_session_data *sd, int type); + void (*skill_produce_mix_list) (struct map_session_data *sd, int skill_id, int trigger); + void (*cooking_list) (struct map_session_data *sd, int trigger, uint16 skill_id, int qty, int list_type); + void (*autospell) (struct map_session_data *sd,uint16 skill_lv); + void (*combo_delay) (struct block_list *bl,int wait); + void (*status_change) (struct block_list *bl,int type,int flag,int tick,int val1, int val2, int val3); + void (*insert_card) (struct map_session_data *sd,int idx_equip,int idx_card,int flag); + void (*inventorylist) (struct map_session_data *sd); + void (*equiplist) (struct map_session_data *sd); + void (*cartlist) (struct map_session_data *sd); + void (*favorite_item) (struct map_session_data* sd, unsigned short index); + void (*clearcart) (int fd); + void (*item_identify_list) (struct map_session_data *sd); + void (*item_identified) (struct map_session_data *sd,int idx,int flag); + void (*item_repair_list) (struct map_session_data *sd, struct map_session_data *dstsd, int lv); + void (*item_repaireffect) (struct map_session_data *sd, int idx, int flag); + void (*item_damaged) (struct map_session_data* sd, unsigned short position); + void (*item_refine_list) (struct map_session_data *sd); + void (*item_skill) (struct map_session_data *sd,uint16 skill_id,uint16 skill_lv); + void (*mvp_item) (struct map_session_data *sd,int nameid); + void (*mvp_exp) (struct map_session_data *sd, unsigned int exp); + void (*mvp_noitem) (struct map_session_data* sd); + void (*changed_dir) (struct block_list *bl, enum send_target target); + void (*charnameack) (int fd, struct block_list *bl); + void (*monster_hp_bar) ( struct mob_data* md, struct map_session_data *sd ); + int (*hpmeter) (struct map_session_data *sd); + void (*hpmeter_single) (int fd, int id, unsigned int hp, unsigned int maxhp); + int (*hpmeter_sub) (struct block_list *bl, va_list ap); + void (*upgrademessage) (int fd, int result, int item_id); + void (*get_weapon_view) (struct map_session_data* sd, unsigned short *rhand, unsigned short *lhand); + void (*gospel_info) (struct map_session_data *sd, int type); + void (*feel_req) (int fd, struct map_session_data *sd, uint16 skill_lv); + void (*starskill) (struct map_session_data* sd, const char* mapname, int monster_id, unsigned char star, unsigned char result); + void (*feel_info) (struct map_session_data* sd, unsigned char feel_level, unsigned char type); + void (*hate_info) (struct map_session_data *sd, unsigned char hate_level,int class_, unsigned char type); + void (*mission_info) (struct map_session_data *sd, int mob_id, unsigned char progress); + void (*feel_hate_reset) (struct map_session_data *sd); + void (*partytickack) (struct map_session_data* sd, bool flag); + void (*equiptickack) (struct map_session_data* sd, int flag); + void (*viewequip_ack) (struct map_session_data* sd, struct map_session_data* tsd); + void (*viewequip_fail) (struct map_session_data* sd); + void (*equipcheckbox) (struct map_session_data* sd); + void (*displayexp) (struct map_session_data *sd, unsigned int exp, char type, bool quest); + void (*font) (struct map_session_data *sd); + void (*progressbar) (struct map_session_data * sd, unsigned long color, unsigned int second); + void (*progressbar_abort) (struct map_session_data * sd); + void (*showdigit) (struct map_session_data* sd, unsigned char type, int value); + int (*elementalconverter_list) (struct map_session_data *sd); + int (*spellbook_list) (struct map_session_data *sd); + int (*magicdecoy_list) (struct map_session_data *sd, uint16 skill_lv, short x, short y); + int (*poison_list) (struct map_session_data *sd, uint16 skill_lv); + int (*autoshadowspell_list) (struct map_session_data *sd); + int (*skill_itemlistwindow) ( struct map_session_data *sd, uint16 skill_id, uint16 skill_lv ); + void (*sc_load) (struct block_list *bl, int tid, enum send_target target, int type, int val1, int val2, int val3); + void (*sc_end) (struct block_list *bl, int tid, enum send_target target, int type); + void (*initialstatus) (struct map_session_data *sd); + /* player-unit-specific-related */ + void (*updatestatus) (struct map_session_data *sd,int type); + void (*changestatus) (struct map_session_data* sd,int type,int val); + void (*statusupack) (struct map_session_data *sd,int type,int ok,int val); + void (*movetoattack) (struct map_session_data *sd,struct block_list *bl); + void (*solved_charname) (int fd, int charid, const char* name); + void (*charnameupdate) (struct map_session_data *ssd); + int (*delayquit) (int tid, unsigned int tick, int id, intptr_t data); + void (*getareachar_pc) (struct map_session_data* sd,struct map_session_data* dstsd); + void (*disconnect_ack) (struct map_session_data* sd, short result); + void (*PVPInfo) (struct map_session_data* sd); + void (*blacksmith) (struct map_session_data* sd); + void (*alchemist) (struct map_session_data* sd); + void (*taekwon) (struct map_session_data* sd); + void (*ranking_pk) (struct map_session_data* sd); + void (*quitsave) (int fd,struct map_session_data *sd); + /* visual effects client-side */ + void (*misceffect) (struct block_list* bl,int type); + void (*changeoption) (struct block_list* bl); + void (*changeoption2) (struct block_list* bl); + void (*emotion) (struct block_list *bl,int type); + void (*talkiebox) (struct block_list* bl, const char* talkie); + void (*wedding_effect) (struct block_list *bl); + void (*divorced) (struct map_session_data* sd, const char* name); + void (*callpartner) (struct map_session_data *sd); + int (*skill_damage) (struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,uint16 skill_id,uint16 skill_lv,int type); + int (*skill_nodamage) (struct block_list *src,struct block_list *dst,uint16 skill_id,int heal,int fail); + void (*skill_poseffect) (struct block_list *src,uint16 skill_id,int val,int x,int y,int tick); + void (*skill_estimation) (struct map_session_data *sd,struct block_list *dst); + void (*skill_warppoint) (struct map_session_data* sd, uint16 skill_id, uint16 skill_lv, unsigned short map1, unsigned short map2, unsigned short map3, unsigned short map4); + void (*skillcasting) (struct block_list* bl, int src_id, int dst_id, int dst_x, int dst_y, uint16 skill_id, int property, int casttime); + void (*produce_effect) (struct map_session_data* sd,int flag,int nameid); + void (*devotion) (struct block_list *src, struct map_session_data *tsd); + void (*spiritball) (struct block_list *bl); + void (*spiritball_single) (int fd, struct map_session_data *sd); + void (*bladestop) (struct block_list *src, int dst_id, int active); + void (*mvp_effect) (struct map_session_data *sd); + void (*heal) (int fd,int type,int val); + void (*resurrection) (struct block_list *bl,int type); + void (*refine) (int fd, int fail, int index, int val); + void (*weather) (int16 m); + 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 (*talisman) (struct map_session_data *sd, short type); + void (*talisman_single) (int fd, struct map_session_data *sd, short type); + void (*snap) ( struct block_list *bl, short x, short y ); + void (*weather_check) (struct map_session_data *sd); + /* sound effects client-side */ + void (*playBGM) (struct map_session_data* sd, const char* name); + void (*soundeffect) (struct map_session_data* sd, struct block_list* bl, const char* name, int type); + void (*soundeffectall) (struct block_list* bl, const char* name, int type, enum send_target coverage); + /* chat/message-related */ + void (*GlobalMessage) (struct block_list* bl, const char* message); + void (*createchat) (struct map_session_data* sd, int flag); + void (*dispchat) (struct chat_data* cd, int fd); + void (*joinchatfail) (struct map_session_data *sd,int flag); + void (*joinchatok) (struct map_session_data *sd,struct chat_data* cd); + void (*addchat) (struct chat_data* cd,struct map_session_data *sd); + void (*changechatowner) (struct chat_data* cd, struct map_session_data* sd); + void (*clearchat) (struct chat_data *cd,int fd); + void (*leavechat) (struct chat_data* cd, struct map_session_data* sd, bool flag); + void (*changechatstatus) (struct chat_data* cd); + void (*wis_message) (int fd, const char* nick, const char* mes, int mes_len); + void (*wis_end) (int fd, int flag); + void (*disp_onlyself) (struct map_session_data *sd, const char *mes, int len); + void (*disp_message) (struct block_list* src, const char* mes, int len, enum send_target target); + void (*broadcast) (struct block_list* bl, const char* mes, int len, int type, enum send_target target); + void (*broadcast2) (struct block_list* bl, const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY, enum send_target target); + void (*messagecolor) (struct block_list* bl, unsigned long color, const char* msg); + void (*disp_overhead) (struct block_list *bl, const char* mes); + void (*msg) (struct map_session_data* sd, unsigned short id); + void (*msg_value) (struct map_session_data* sd, unsigned short id, int value); + void (*msg_skill) (struct map_session_data* sd, uint16 skill_id, int msg_id); + void (*msgtable) (int fd, int line); + void (*msgtable_num) (int fd, int line, int num); + void (*message) (const int fd, const char* mes); + void (*messageln) (const int fd, const char* mes); + int (*colormes) (int fd, enum clif_colors color, const char* msg); + bool (*process_message) (struct map_session_data* sd, int format, char** name_, int* namelen_, char** message_, int* messagelen_); + void (*wisexin) (struct map_session_data *sd,int type,int flag); + void (*wisall) (struct map_session_data *sd,int type,int flag); + void (*PMIgnoreList) (struct map_session_data* sd); + /* trade handling */ + void (*traderequest) (struct map_session_data* sd, const char* name); + void (*tradestart) (struct map_session_data* sd, uint8 type); + void (*tradeadditem) (struct map_session_data* sd, struct map_session_data* tsd, int index, int amount); + void (*tradeitemok) (struct map_session_data* sd, int index, int fail); + void (*tradedeal_lock) (struct map_session_data* sd, int fail); + void (*tradecancelled) (struct map_session_data* sd); + void (*tradecompleted) (struct map_session_data* sd, int fail); + void (*tradeundo) (struct map_session_data* sd); + /* vending handling */ + void (*openvendingreq) (struct map_session_data* sd, int num); + void (*showvendingboard) (struct block_list* bl, const char* message, int fd); + void (*closevendingboard) (struct block_list* bl, int fd); + void (*vendinglist) (struct map_session_data* sd, unsigned int id, struct s_vending* vending); + void (*buyvending) (struct map_session_data* sd, int index, int amount, int fail); + void (*openvending) (struct map_session_data* sd, int id, struct s_vending* vending); + void (*vendingreport) (struct map_session_data* sd, int index, int amount); + /* storage handling */ + void (*storagelist) (struct map_session_data* sd, struct item* items, int items_length); + void (*updatestorageamount) (struct map_session_data* sd, int amount, int max_amount); + void (*storageitemadded) (struct map_session_data* sd, struct item* i, int index, int amount); + void (*storageitemremoved) (struct map_session_data* sd, int index, int amount); + void (*storageclose) (struct map_session_data* sd); + /* skill-list handling */ + void (*skillinfoblock) (struct map_session_data *sd); + void (*skillup) (struct map_session_data *sd,uint16 skill_id); + void (*skillinfo) (struct map_session_data *sd,int skill, int inf); + void (*addskill) (struct map_session_data *sd, int id); + void (*deleteskill) (struct map_session_data *sd, int id); + /* party-specific */ + void (*party_created) (struct map_session_data *sd,int result); + void (*party_member_info) (struct party_data *p, struct map_session_data *sd); + void (*party_info) (struct party_data* p, struct map_session_data *sd); + void (*party_invite) (struct map_session_data *sd,struct map_session_data *tsd); + void (*party_inviteack) (struct map_session_data* sd, const char* nick, int result); + void (*party_option) (struct party_data *p,struct map_session_data *sd,int flag); + void (*party_withdraw) (struct party_data* p, struct map_session_data* sd, int account_id, const char* name, int flag); + void (*party_message) (struct party_data* p, int account_id, const char* mes, int len); + void (*party_xy) (struct map_session_data *sd); + void (*party_xy_single) (int fd, struct map_session_data *sd); + void (*party_hp) (struct map_session_data *sd); + void (*party_xy_remove) (struct map_session_data *sd); + void (*party_show_picker) (struct map_session_data * sd, struct item * item_data); + void (*partyinvitationstate) (struct map_session_data* sd); + /* guild-specific */ + void (*guild_created) (struct map_session_data *sd,int flag); + void (*guild_belonginfo) (struct map_session_data *sd, struct guild *g); + void (*guild_masterormember) (struct map_session_data *sd); + void (*guild_basicinfo) (struct map_session_data *sd); + void (*guild_allianceinfo) (struct map_session_data *sd); + void (*guild_memberlist) (struct map_session_data *sd); + void (*guild_skillinfo) (struct map_session_data* sd); + void (*guild_send_onlineinfo) (struct map_session_data *sd); //[LuzZza] + void (*guild_memberlogin_notice) (struct guild *g,int idx,int flag); + void (*guild_invite) (struct map_session_data *sd,struct guild *g); + void (*guild_inviteack) (struct map_session_data *sd,int flag); + void (*guild_leave) (struct map_session_data *sd,const char *name,const char *mes); + void (*guild_expulsion) (struct map_session_data* sd, const char* name, const char* mes, int account_id); + void (*guild_positionchanged) (struct guild *g,int idx); + void (*guild_memberpositionchanged) (struct guild *g,int idx); + void (*guild_emblem) (struct map_session_data *sd,struct guild *g); + void (*guild_emblem_area) (struct block_list* bl); + void (*guild_notice) (struct map_session_data* sd, struct guild* g); + void (*guild_message) (struct guild *g,int account_id,const char *mes,int len); + int (*guild_skillup) (struct map_session_data *sd,uint16 skill_id,int lv); + void (*guild_reqalliance) (struct map_session_data *sd,int account_id,const char *name); + void (*guild_allianceack) (struct map_session_data *sd,int flag); + void (*guild_delalliance) (struct map_session_data *sd,int guild_id,int flag); + void (*guild_oppositionack) (struct map_session_data *sd,int flag); + void (*guild_broken) (struct map_session_data *sd,int flag); + void (*guild_xy) (struct map_session_data *sd); + void (*guild_xy_single) (int fd, struct map_session_data *sd); + void (*guild_xy_remove) (struct map_session_data *sd); + void (*guild_positionnamelist) (struct map_session_data *sd); + void (*guild_positioninfolist) (struct map_session_data *sd); + void (*guild_expulsionlist) (struct map_session_data* sd); + bool (*validate_emblem) (const uint8* emblem, unsigned long emblem_len); + /* battleground-specific */ + void (*bg_hp) (struct map_session_data *sd); + void (*bg_xy) (struct map_session_data *sd); + void (*bg_xy_remove) (struct map_session_data *sd); + void (*bg_message) (struct battleground_data *bg, int src_id, const char *name, const char *mes, int len); + void (*bg_updatescore) (int16 m); + void (*bg_updatescore_single) (struct map_session_data *sd); + void (*sendbgemblem_area) (struct map_session_data *sd); + void (*sendbgemblem_single) (int fd, struct map_session_data *sd); + /* instance-related */ + int (*instance) (int instance_id, int type, int flag); + void (*instance_join) (int fd, int instance_id); + void (*instance_leave) (int fd); + /* pet-related */ + void (*catch_process) (struct map_session_data *sd); + void (*pet_roulette) (struct map_session_data *sd,int data); + void (*sendegg) (struct map_session_data *sd); + void (*send_petstatus) (struct map_session_data *sd); + void (*send_petdata) (struct map_session_data* sd, struct pet_data* pd, int type, int param); + void (*pet_emotion) (struct pet_data *pd,int param); + void (*pet_food) (struct map_session_data *sd,int foodid,int fail); + /* friend-related */ + int (*friendslist_toggle_sub) (struct map_session_data *sd,va_list ap); + void (*friendslist_send) (struct map_session_data *sd); + void (*friendslist_reqack) (struct map_session_data *sd, struct map_session_data *f_sd, int type); + void (*friendslist_toggle) (struct map_session_data *sd,int account_id, int char_id, int online); + void (*friendlist_req) (struct map_session_data* sd, int account_id, int char_id, const char* name); + /* gm-related */ + void (*GM_kickack) (struct map_session_data *sd, int id); + void (*GM_kick) (struct map_session_data *sd,struct map_session_data *tsd); + void (*manner_message) (struct map_session_data* sd, uint32 type); + void (*GM_silence) (struct map_session_data* sd, struct map_session_data* tsd, uint8 type); + void (*account_name) (struct map_session_data* sd, int account_id, const char* accname); + void (*check) (int fd, struct map_session_data* pl_sd); + /* hom-related */ + void (*hominfo) (struct map_session_data *sd, struct homun_data *hd, int flag); + int (*homskillinfoblock) (struct map_session_data *sd); + void (*homskillup) (struct map_session_data *sd, uint16 skill_id); + int (*hom_food) (struct map_session_data *sd,int foodid,int fail); + void (*send_homdata) (struct map_session_data *sd, int state, int param); + /* questlog-related */ + void (*quest_send_list) (struct map_session_data * sd); + void (*quest_send_mission) (struct map_session_data * sd); + void (*quest_add) (struct map_session_data * sd, struct quest * qd, int index); + void (*quest_delete) (struct map_session_data * sd, int quest_id); + void (*quest_update_status) (struct map_session_data * sd, int quest_id, bool active); + void (*quest_update_objective) (struct map_session_data * sd, struct quest * qd, int index); + void (*quest_show_event) (struct map_session_data *sd, struct block_list *bl, short state, short color); + /* mail-related */ + void (*mail_window) (int fd, int flag); + void (*mail_read) (struct map_session_data *sd, int mail_id); + void (*mail_delete) (int fd, int mail_id, short fail); + void (*mail_return) (int fd, int mail_id, short fail); + void (*mail_send) (int fd, bool fail); + void (*mail_new) (int fd, int mail_id, const char *sender, const char *title); + void (*mail_refreshinbox) (struct map_session_data *sd); + void (*mail_getattachment) (int fd, uint8 flag); + void (*mail_setattachment) (int fd, int index, uint8 flag); + /* auction-related */ + void (*auction_openwindow) (struct map_session_data *sd); + void (*auction_results) (struct map_session_data *sd, short count, short pages, uint8 *buf); + void (*auction_message) (int fd, unsigned char flag); + void (*auction_close) (int fd, unsigned char flag); + void (*auction_setitem) (int fd, int index, bool fail); + /* mercenary-related */ + void (*mercenary_info) (struct map_session_data *sd); + void (*mercenary_skillblock) (struct map_session_data *sd); + void (*mercenary_message) (struct map_session_data* sd, int message); + void (*mercenary_updatestatus) (struct map_session_data *sd, int type); + /* item rental */ + void (*rental_time) (int fd, int nameid, int seconds); + void (*rental_expired) (int fd, int index, int nameid); + /* party booking related */ + void (*PartyBookingRegisterAck) (struct map_session_data *sd, int flag); + void (*PartyBookingDeleteAck) (struct map_session_data* sd, int flag); + void (*PartyBookingSearchAck) (int fd, struct party_booking_ad_info** results, int count, bool more_result); + void (*PartyBookingUpdateNotify) (struct map_session_data* sd, struct party_booking_ad_info* pb_ad); + void (*PartyBookingDeleteNotify) (struct map_session_data* sd, int index); + void (*PartyBookingInsertNotify) (struct map_session_data* sd, struct party_booking_ad_info* pb_ad); + /* buying store-related */ + void (*buyingstore_open) (struct map_session_data* sd); + void (*buyingstore_open_failed) (struct map_session_data* sd, unsigned short result, unsigned int weight); + void (*buyingstore_myitemlist) (struct map_session_data* sd); + void (*buyingstore_entry) (struct map_session_data* sd); + void (*buyingstore_entry_single) (struct map_session_data* sd, struct map_session_data* pl_sd); + void (*buyingstore_disappear_entry) (struct map_session_data* sd); + void (*buyingstore_disappear_entry_single) (struct map_session_data* sd, struct map_session_data* pl_sd); + void (*buyingstore_itemlist) (struct map_session_data* sd, struct map_session_data* pl_sd); + void (*buyingstore_trade_failed_buyer) (struct map_session_data* sd, short result); + void (*buyingstore_update_item) (struct map_session_data* sd, unsigned short nameid, unsigned short amount); + void (*buyingstore_delete_item) (struct map_session_data* sd, short index, unsigned short amount, int price); + void (*buyingstore_trade_failed_seller) (struct map_session_data* sd, short result, unsigned short nameid); + /* search store-related */ + void (*search_store_info_ack) (struct map_session_data* sd); + void (*search_store_info_failed) (struct map_session_data* sd, unsigned char reason); + void (*open_search_store_info) (struct map_session_data* sd); + void (*search_store_info_click_ack) (struct map_session_data* sd, short x, short y); + /* elemental-related */ + void (*elemental_info) (struct map_session_data *sd); + void (*elemental_updatestatus) (struct map_session_data *sd, int type); + /* misc-handling */ + void (*adopt_reply) (struct map_session_data *sd, int type); + void (*adopt_request) (struct map_session_data *sd, struct map_session_data *src, int p_id); + void (*readbook) (int fd, int book_id, int page); + void (*notify_time) (struct map_session_data* sd, unsigned long time); + void (*user_count) (struct map_session_data* sd, int count); + void (*noask_sub) (struct map_session_data *src, struct map_session_data *target, int type); + void (*chsys_create) (struct hChSysCh *channel, char *name, char *pass, unsigned char color); + void (*chsys_msg) (struct hChSysCh *channel, struct map_session_data *sd, char *msg); + void (*chsys_msg2) (struct hChSysCh *channel, char *msg); + void (*chsys_send) (struct hChSysCh *channel, struct map_session_data *sd, char *msg); + void (*chsys_join) (struct hChSysCh *channel, struct map_session_data *sd); + void (*chsys_left) (struct hChSysCh *channel, struct map_session_data *sd); + void (*chsys_delete) (struct hChSysCh *channel); + void (*chsys_mjoin) (struct map_session_data *sd); + void (*chsys_quit) (struct map_session_data *sd); + void (*chsys_quitg) (struct map_session_data *sd); + void (*chsys_gjoin) (struct guild *g1,struct guild *g2); + void (*chsys_gleave) (struct guild *g1,struct guild *g2); + void (*bc_ready) (void); + int (*undisguise_timer) (int tid, unsigned int tick, int id, intptr_t data); + /*------------------------ + *- Parse Incoming Packet + *------------------------*/ + void (*pWantToConnection) (int fd, struct map_session_data *sd); + void (*pLoadEndAck) (int fd,struct map_session_data *sd); + void (*pTickSend) (int fd, struct map_session_data *sd); + void (*pHotkey) (int fd, struct map_session_data *sd); + void (*pProgressbar) (int fd, struct map_session_data * sd); + void (*pWalkToXY) (int fd, struct map_session_data *sd); + void (*pQuitGame) (int fd, struct map_session_data *sd); + void (*pGetCharNameRequest) (int fd, struct map_session_data *sd); + void (*pGlobalMessage) (int fd, struct map_session_data* sd); + void (*pMapMove) (int fd, struct map_session_data *sd); + void (*pChangeDir) (int fd, struct map_session_data *sd); + void (*pEmotion) (int fd, struct map_session_data *sd); + void (*pHowManyConnections) (int fd, struct map_session_data *sd); + void (*pActionRequest) (int fd, struct map_session_data *sd); + void (*pActionRequest_sub) (struct map_session_data *sd, int action_type, int target_id, unsigned int tick); + void (*pRestart) (int fd, struct map_session_data *sd); + void (*pWisMessage) (int fd, struct map_session_data* sd); + void (*pBroadcast) (int fd, struct map_session_data* sd); + void (*pTakeItem) (int fd, struct map_session_data *sd); + void (*pDropItem) (int fd, struct map_session_data *sd); + void (*pUseItem) (int fd, struct map_session_data *sd); + void (*pEquipItem) (int fd,struct map_session_data *sd); + void (*pUnequipItem) (int fd,struct map_session_data *sd); + void (*pNpcClicked) (int fd,struct map_session_data *sd); + void (*pNpcBuySellSelected) (int fd,struct map_session_data *sd); + void (*pNpcBuyListSend) (int fd, struct map_session_data* sd); + void (*pNpcSellListSend) (int fd,struct map_session_data *sd); + void (*pCreateChatRoom) (int fd, struct map_session_data* sd); + void (*pChatAddMember) (int fd, struct map_session_data* sd); + void (*pChatRoomStatusChange) (int fd, struct map_session_data* sd); + void (*pChangeChatOwner) (int fd, struct map_session_data* sd); + void (*pKickFromChat) (int fd,struct map_session_data *sd); + void (*pChatLeave) (int fd, struct map_session_data* sd); + void (*pTradeRequest) (int fd,struct map_session_data *sd); + void (*chann_config_read) (void); + void (*pTradeAck) (int fd,struct map_session_data *sd); + void (*pTradeAddItem) (int fd,struct map_session_data *sd); + void (*pTradeOk) (int fd,struct map_session_data *sd); + void (*pTradeCancel) (int fd,struct map_session_data *sd); + void (*pTradeCommit) (int fd,struct map_session_data *sd); + void (*pStopAttack) (int fd,struct map_session_data *sd); + void (*pPutItemToCart) (int fd,struct map_session_data *sd); + void (*pGetItemFromCart) (int fd,struct map_session_data *sd); + void (*pRemoveOption) (int fd,struct map_session_data *sd); + void (*pChangeCart) (int fd,struct map_session_data *sd); + void (*pStatusUp) (int fd,struct map_session_data *sd); + void (*pSkillUp) (int fd,struct map_session_data *sd); + void (*pUseSkillToId) (int fd, struct map_session_data *sd); + void (*pUseSkillToId_homun) (struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id); + void (*pUseSkillToId_mercenary) (struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, int target_id); + void (*pUseSkillToPos) (int fd, struct map_session_data *sd); + void (*pUseSkillToPosSub) (int fd, struct map_session_data *sd, uint16 skill_lv, uint16 skill_id, short x, short y, int skillmoreinfo); + void (*pUseSkillToPos_homun) (struct homun_data *hd, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo); + void (*pUseSkillToPos_mercenary) (struct mercenary_data *md, struct map_session_data *sd, unsigned int tick, uint16 skill_id, uint16 skill_lv, short x, short y, int skillmoreinfo); + void (*pUseSkillToPosMoreInfo) (int fd, struct map_session_data *sd); + void (*pUseSkillMap) (int fd, struct map_session_data* sd); + void (*pRequestMemo) (int fd,struct map_session_data *sd); + void (*pProduceMix) (int fd,struct map_session_data *sd); + void (*pCooking) (int fd,struct map_session_data *sd); + void (*pRepairItem) (int fd, struct map_session_data *sd); + void (*pWeaponRefine) (int fd, struct map_session_data *sd); + void (*pNpcSelectMenu) (int fd,struct map_session_data *sd); + void (*pNpcNextClicked) (int fd,struct map_session_data *sd); + void (*pNpcAmountInput) (int fd,struct map_session_data *sd); + void (*pNpcStringInput) (int fd, struct map_session_data* sd); + void (*pNpcCloseClicked) (int fd,struct map_session_data *sd); + void (*pItemIdentify) (int fd,struct map_session_data *sd); + void (*pSelectArrow) (int fd,struct map_session_data *sd); + void (*pAutoSpell) (int fd,struct map_session_data *sd); + void (*pUseCard) (int fd,struct map_session_data *sd); + void (*pInsertCard) (int fd,struct map_session_data *sd); + void (*pSolveCharName) (int fd, struct map_session_data *sd); + void (*pResetChar) (int fd, struct map_session_data *sd); + void (*pLocalBroadcast) (int fd, struct map_session_data* sd); + void (*pMoveToKafra) (int fd, struct map_session_data *sd); + void (*pMoveFromKafra) (int fd,struct map_session_data *sd); + void (*pMoveToKafraFromCart) (int fd, struct map_session_data *sd); + void (*pMoveFromKafraToCart) (int fd, struct map_session_data *sd); + void (*pCloseKafra) (int fd, struct map_session_data *sd); + void (*pStoragePassword) (int fd, struct map_session_data *sd); + void (*pCreateParty) (int fd, struct map_session_data *sd); + void (*pCreateParty2) (int fd, struct map_session_data *sd); + void (*pPartyInvite) (int fd, struct map_session_data *sd); + void (*pPartyInvite2) (int fd, struct map_session_data *sd); + void (*pReplyPartyInvite) (int fd,struct map_session_data *sd); + void (*pReplyPartyInvite2) (int fd,struct map_session_data *sd); + void (*pLeaveParty) (int fd, struct map_session_data *sd); + void (*pRemovePartyMember) (int fd, struct map_session_data *sd); + void (*pPartyChangeOption) (int fd, struct map_session_data *sd); + void (*pPartyMessage) (int fd, struct map_session_data* sd); + void (*pPartyChangeLeader) (int fd, struct map_session_data* sd); + void (*pPartyBookingRegisterReq) (int fd, struct map_session_data* sd); + void (*pPartyBookingSearchReq) (int fd, struct map_session_data* sd); + void (*pPartyBookingDeleteReq) (int fd, struct map_session_data* sd); + void (*pPartyBookingUpdateReq) (int fd, struct map_session_data* sd); + void (*pCloseVending) (int fd, struct map_session_data* sd); + void (*pVendingListReq) (int fd, struct map_session_data* sd); + void (*pPurchaseReq) (int fd, struct map_session_data* sd); + void (*pPurchaseReq2) (int fd, struct map_session_data* sd); + void (*pOpenVending) (int fd, struct map_session_data* sd); + void (*pCreateGuild) (int fd,struct map_session_data *sd); + void (*pGuildCheckMaster) (int fd, struct map_session_data *sd); + void (*pGuildRequestInfo) (int fd, struct map_session_data *sd); + void (*pGuildChangePositionInfo) (int fd, struct map_session_data *sd); + void (*pGuildChangeMemberPosition) (int fd, struct map_session_data *sd); + void (*pGuildRequestEmblem) (int fd,struct map_session_data *sd); + void (*pGuildChangeEmblem) (int fd,struct map_session_data *sd); + void (*pGuildChangeNotice) (int fd, struct map_session_data* sd); + void (*pGuildInvite) (int fd,struct map_session_data *sd); + void (*pGuildReplyInvite) (int fd,struct map_session_data *sd); + void (*pGuildLeave) (int fd,struct map_session_data *sd); + void (*pGuildExpulsion) (int fd,struct map_session_data *sd); + void (*pGuildMessage) (int fd, struct map_session_data* sd); + void (*pGuildRequestAlliance) (int fd, struct map_session_data *sd); + void (*pGuildReplyAlliance) (int fd, struct map_session_data *sd); + void (*pGuildDelAlliance) (int fd, struct map_session_data *sd); + void (*pGuildOpposition) (int fd, struct map_session_data *sd); + void (*pGuildBreak) (int fd, struct map_session_data *sd); + void (*pPetMenu) (int fd, struct map_session_data *sd); + void (*pCatchPet) (int fd, struct map_session_data *sd); + void (*pSelectEgg) (int fd, struct map_session_data *sd); + void (*pSendEmotion) (int fd, struct map_session_data *sd); + void (*pChangePetName) (int fd, struct map_session_data *sd); + void (*pGMKick) (int fd, struct map_session_data *sd); + void (*pGMKickAll) (int fd, struct map_session_data* sd); + void (*pGMShift) (int fd, struct map_session_data *sd); + void (*pGMRemove2) (int fd, struct map_session_data* sd); + void (*pGMRecall) (int fd, struct map_session_data *sd); + void (*pGMRecall2) (int fd, struct map_session_data* sd); + void (*pGM_Monster_Item) (int fd, struct map_session_data *sd); + void (*pGMHide) (int fd, struct map_session_data *sd); + void (*pGMReqNoChat) (int fd,struct map_session_data *sd); + void (*pGMRc) (int fd, struct map_session_data* sd); + void (*pGMReqAccountName) (int fd, struct map_session_data *sd); + void (*pGMChangeMapType) (int fd, struct map_session_data *sd); + void (*pPMIgnore) (int fd, struct map_session_data* sd); + void (*pPMIgnoreAll) (int fd, struct map_session_data *sd); + void (*pPMIgnoreList) (int fd,struct map_session_data *sd); + void (*pNoviceDoriDori) (int fd, struct map_session_data *sd); + void (*pNoviceExplosionSpirits) (int fd, struct map_session_data *sd); + void (*pFriendsListAdd) (int fd, struct map_session_data *sd); + void (*pFriendsListReply) (int fd, struct map_session_data *sd); + void (*pFriendsListRemove) (int fd, struct map_session_data *sd); + void (*pPVPInfo) (int fd,struct map_session_data *sd); + void (*pBlacksmith) (int fd,struct map_session_data *sd); + void (*pAlchemist) (int fd,struct map_session_data *sd); + void (*pTaekwon) (int fd,struct map_session_data *sd); + void (*pRankingPk) (int fd,struct map_session_data *sd); + void (*pFeelSaveOk) (int fd,struct map_session_data *sd); + void (*pChangeHomunculusName) (int fd, struct map_session_data *sd); + void (*pHomMoveToMaster) (int fd, struct map_session_data *sd); + void (*pHomMoveTo) (int fd, struct map_session_data *sd); + void (*pHomAttack) (int fd,struct map_session_data *sd); + void (*pHomMenu) (int fd, struct map_session_data *sd); + void (*pAutoRevive) (int fd, struct map_session_data *sd); + void (*pCheck) (int fd, struct map_session_data *sd); + void (*pMail_refreshinbox) (int fd, struct map_session_data *sd); + void (*pMail_read) (int fd, struct map_session_data *sd); + void (*pMail_getattach) (int fd, struct map_session_data *sd); + void (*pMail_delete) (int fd, struct map_session_data *sd); + void (*pMail_return) (int fd, struct map_session_data *sd); + void (*pMail_setattach) (int fd, struct map_session_data *sd); + void (*pMail_winopen) (int fd, struct map_session_data *sd); + void (*pMail_send) (int fd, struct map_session_data *sd); + void (*pAuction_cancelreg) (int fd, struct map_session_data *sd); + void (*pAuction_setitem) (int fd, struct map_session_data *sd); + void (*pAuction_register) (int fd, struct map_session_data *sd); + void (*pAuction_cancel) (int fd, struct map_session_data *sd); + void (*pAuction_close) (int fd, struct map_session_data *sd); + void (*pAuction_bid) (int fd, struct map_session_data *sd); + void (*pAuction_search) (int fd, struct map_session_data* sd); + void (*pAuction_buysell) (int fd, struct map_session_data* sd); + void (*pcashshop_buy) (int fd, struct map_session_data *sd); + void (*pAdopt_request) (int fd, struct map_session_data *sd); + void (*pAdopt_reply) (int fd, struct map_session_data *sd); + void (*pViewPlayerEquip) (int fd, struct map_session_data* sd); + void (*pEquipTick) (int fd, struct map_session_data* sd); + void (*pquestStateAck) (int fd, struct map_session_data * sd); + void (*pmercenary_action) (int fd, struct map_session_data* sd); + void (*pBattleChat) (int fd, struct map_session_data* sd); + void (*pLessEffect) (int fd, struct map_session_data* sd); + void (*pItemListWindowSelected) (int fd, struct map_session_data* sd); + void (*pReqOpenBuyingStore) (int fd, struct map_session_data* sd); + void (*pReqCloseBuyingStore) (int fd, struct map_session_data* sd); + void (*pReqClickBuyingStore) (int fd, struct map_session_data* sd); + void (*pReqTradeBuyingStore) (int fd, struct map_session_data* sd); + void (*pSearchStoreInfo) (int fd, struct map_session_data* sd); + void (*pSearchStoreInfoNextPage) (int fd, struct map_session_data* sd); + void (*pCloseSearchStoreInfo) (int fd, struct map_session_data* sd); + void (*pSearchStoreInfoListItemClick) (int fd, struct map_session_data* sd); + void (*pDebug) (int fd,struct map_session_data *sd); + void (*pSkillSelectMenu) (int fd, struct map_session_data *sd); + void (*pMoveItem) (int fd, struct map_session_data *sd); + void (*pDull) (int fd, struct map_session_data *sd); + /* RagExe Cash Shop [Ind/Hercules] */ + void (*pCashShopOpen) (int fd, struct map_session_data *sd); + void (*pCashShopClose) (int fd, struct map_session_data *sd); + void (*pCashShopReqTab) (int fd, struct map_session_data *sd); + void (*pCashShopSchedule) (int fd, struct map_session_data *sd); + void (*pCashShopBuy) (int fd, struct map_session_data *sd); + void (*pPartyTick) (int fd, struct map_session_data *sd); + void (*pGuildInvite2) (int fd, struct map_session_data *sd); +} clif_s; + +struct clif_interface *clif; + +void clif_defaults(void); #endif /* _CLIF_H_ */ diff --git a/src/map/duel.c b/src/map/duel.c index c13d004b0..7af427304 100644 --- a/src/map/duel.c +++ b/src/map/duel.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" @@ -52,7 +53,7 @@ static int duel_showinfo_sub(struct map_session_data* sd, va_list va) if (sd->duel_group != ssd->duel_group) return 0; sprintf(output, " %d. %s", ++(*p), sd->status.name); - clif_disp_onlyself(ssd, output, strlen(output)); + clif->disp_onlyself(ssd, output, strlen(output)); return 1; } @@ -73,7 +74,7 @@ void duel_showinfo(const unsigned int did, struct map_session_data* sd) duel_list[did].members_count, duel_list[did].members_count + duel_list[did].invites_count); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); map_foreachpc(duel_showinfo_sub, sd, &p); } @@ -92,10 +93,10 @@ int duel_create(struct map_session_data* sd, const unsigned int maxpl) duel_list[i].max_players_limit = maxpl; strcpy(output, msg_txt(372)); // " -- Duel has been created (@invite/@leave) --" - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - //clif_misceffect2(&sd->bl, 159); + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->maptypeproperty2(&sd->bl,SELF); return i; } @@ -105,14 +106,14 @@ void duel_invite(const unsigned int did, struct map_session_data* sd, struct map // " -- Player %s invites %s to duel --" sprintf(output, msg_txt(373), sd->status.name, target_sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); target_sd->duel_invite = did; duel_list[did].invites_count++; // "Blue -- Player %s invites you to PVP duel (@accept/@reject) --" sprintf(output, msg_txt(374), sd->status.name); - clif_broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF); + clif->broadcast((struct block_list *)target_sd, output, strlen(output)+1, 0x10, SELF); } static int duel_leave_sub(struct map_session_data* sd, va_list va) @@ -129,7 +130,7 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) // " <- Player %s has left duel --" sprintf(output, msg_txt(375), sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); duel_list[did].members_count--; @@ -140,7 +141,8 @@ void duel_leave(const unsigned int did, struct map_session_data* sd) sd->duel_group = 0; duel_savetime(sd); - clif_map_property(sd, MAPPROPERTY_NOTHING); + clif->map_property(sd, MAPPROPERTY_NOTHING); + clif->maptypeproperty2(&sd->bl,SELF); } void duel_accept(const unsigned int did, struct map_session_data* sd) @@ -154,10 +156,10 @@ void duel_accept(const unsigned int did, struct map_session_data* sd) // " -> Player %s has accepted duel --" sprintf(output, msg_txt(376), sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); - //clif_misceffect2(&sd->bl, 159); + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->maptypeproperty2(&sd->bl,SELF); } void duel_reject(const unsigned int did, struct map_session_data* sd) @@ -166,7 +168,7 @@ void duel_reject(const unsigned int did, struct map_session_data* sd) // " -- Player %s has rejected duel --" sprintf(output, msg_txt(377), sd->status.name); - clif_disp_message(&sd->bl, output, strlen(output), DUEL_WOS); + clif->disp_message(&sd->bl, output, strlen(output), DUEL_WOS); duel_list[did].invites_count--; sd->duel_invite = 0; diff --git a/src/map/elemental.c b/src/map/elemental.c index 90b90c1e3..dfe1a0c5b 100644 --- a/src/map/elemental.c +++ b/src/map/elemental.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -10,6 +11,7 @@ #include "../common/showmsg.h" #include "../common/utils.h" #include "../common/random.h" +#include "../common/strlib.h" #include "log.h" #include "clif.h" @@ -270,11 +272,11 @@ int elemental_data_received(struct s_elemental *ele, bool flag) { if( ed->bl.prev == NULL && sd->bl.prev != NULL ) { map_addblock(&ed->bl); - clif_spawn(&ed->bl); - clif_elemental_info(sd); - clif_elemental_updatestatus(sd,SP_HP); - clif_hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.max_hp); - clif_elemental_updatestatus(sd,SP_SP); + clif->spawn(&ed->bl); + clif->elemental_info(sd); + clif->elemental_updatestatus(sd,SP_HP); + clif->hpmeter_single(sd->fd,ed->bl.id,ed->battle_status.hp,ed->battle_status.max_hp); + clif->elemental_updatestatus(sd,SP_SP); } return 1; @@ -286,7 +288,7 @@ int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id) { nullpo_ret(ed); - bl = battle_get_master(&ed->bl); + bl = battle->get_master(&ed->bl); if( type ) { switch( type ) { @@ -420,20 +422,20 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned ed->last_thinktime = tick; // Not in skill range. - if( !battle_check_range(&ed->bl,bl,skill_get_range(skill_id,skill_lv)) ) { + if( !battle->check_range(&ed->bl,bl,skill->get_range(skill_id,skill_lv)) ) { // Try to walk to the target. - if( !unit_walktobl(&ed->bl, bl, skill_get_range(skill_id,skill_lv), 2) ) + if( !unit_walktobl(&ed->bl, bl, skill->get_range(skill_id,skill_lv), 2) ) elemental_unlocktarget(ed); else { // Walking, waiting to be in range. Client don't handle it, then we must handle it here. - int walk_dist = distance_bl(&ed->bl,bl) - skill_get_range(skill_id,skill_lv); + int walk_dist = distance_bl(&ed->bl,bl) - skill->get_range(skill_id,skill_lv); ed->ud.skill_id = skill_id; ed->ud.skill_lv = skill_lv; - if( skill_get_inf(skill_id) & INF_GROUND_SKILL ) - ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_pos, ed->bl.id, 0 ); + if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) + ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill->castend_pos, ed->bl.id, 0 ); else - ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill_castend_id, ed->bl.id, 0 ); + ed->ud.skilltimer = add_timer( tick+status_get_speed(&ed->bl)*walk_dist, skill->castend_id, ed->bl.id, 0 ); } return 1; @@ -442,7 +444,7 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned req = elemental_skill_get_requirements(skill_id, skill_lv); if(req.hp || req.sp){ - struct map_session_data *sd = BL_CAST(BL_PC, battle_get_master(&ed->bl)); + struct map_session_data *sd = BL_CAST(BL_PC, battle->get_master(&ed->bl)); if( sd ){ if( sd->skill_id_old != SO_EL_ACTION && //regardless of remaining HP/SP it can be cast (status_get_hp(&ed->bl) < req.hp || status_get_sp(&ed->bl) < req.sp) ) @@ -453,7 +455,7 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, unsigned } //Otherwise, just cast the skill. - if( skill_get_inf(skill_id) & INF_GROUND_SKILL ) + if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv); else unit_skilluse_id(&ed->bl, bl->id, skill_id, skill_lv); @@ -497,7 +499,7 @@ int elemental_change_mode_ack(struct elemental_data *ed, int mode) { ed->target_id = bl->id; // Set new target ed->last_thinktime = gettick(); - if( skill_get_inf(skill_id) & INF_GROUND_SKILL ) + if( skill->get_inf(skill_id) & INF_GROUND_SKILL ) unit_skilluse_pos(&ed->bl, bl->x, bl->y, skill_id, skill_lv); else unit_skilluse_id(&ed->bl,bl->id,skill_id,skill_lv); @@ -534,9 +536,9 @@ int elemental_change_mode(struct elemental_data *ed, int mode) { void elemental_heal(struct elemental_data *ed, int hp, int sp) { if( hp ) - clif_elemental_updatestatus(ed->master, SP_HP); + clif->elemental_updatestatus(ed->master, SP_HP); if( sp ) - clif_elemental_updatestatus(ed->master, SP_SP); + clif->elemental_updatestatus(ed->master, SP_SP); } int elemental_dead(struct elemental_data *ed) { @@ -554,18 +556,18 @@ int elemental_unlocktarget(struct elemental_data *ed) { } int elemental_skillnotok(uint16 skill_id, struct elemental_data *ed) { - int idx = skill_get_index(skill_id); + int idx = skill->get_index(skill_id); nullpo_retr(1,ed); if (idx == 0) return 1; // invalid skill id - return skillnotok(skill_id, ed->master); + return skill->not_ok(skill_id, ed->master); } struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16 skill_lv){ struct skill_condition req; - int idx = skill_get_index(skill_id); + int idx = skill->get_index(skill_id); memset(&req,0,sizeof(req)); @@ -613,7 +615,7 @@ static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap if( (*target) == bl || !status_check_skilluse(&ed->bl, bl, 0, 0) ) return 0; - if( battle_check_target(&ed->bl,bl,BCT_ENEMY) <= 0 ) + if( battle->check_target(&ed->bl,bl,BCT_ENEMY) <= 0 ) return 0; switch( bl->type ) { @@ -622,7 +624,7 @@ static int elemental_ai_sub_timer_activesearch(struct block_list *bl, va_list ap return 0; default: dist = distance_bl(&ed->bl, bl); - if( ((*target) == NULL || !check_distance_bl(&ed->bl, *target, dist)) && battle_check_range(&ed->bl,bl,ed->db->range2) ) { //Pick closest target? + if( ((*target) == NULL || !check_distance_bl(&ed->bl, *target, dist)) && battle->check_range(&ed->bl,bl,ed->db->range2) ) { //Pick closest target? (*target) = bl; ed->target_id = bl->id; ed->min_chase = dist + ed->db->range3; @@ -694,8 +696,8 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_ if( master_dist > AREA_SIZE ) { // Master out of vision range. elemental_unlocktarget(ed); unit_warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT); - clif_elemental_updatestatus(sd,SP_HP); - clif_elemental_updatestatus(sd,SP_SP); + clif->elemental_updatestatus(sd,SP_HP); + clif->elemental_updatestatus(sd,SP_SP); return 0; } else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase. short x = sd->bl.x, y = sd->bl.y; @@ -721,7 +723,7 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_ return 1; } - if( battle_check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill. + if( battle->check_range(&ed->bl,target,view_range) && rnd()%100 < 2 ) { // 2% chance to cast attack skill. if( elemental_action(ed,target,tick) ) return 1; } @@ -731,7 +733,7 @@ static int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_ if( ed->ud.target == target->id && ed->ud.attacktimer != INVALID_TIMER ) //Already locked. return 1; - if( battle_check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage + if( battle->check_range(&ed->bl, target, ed->base_status.rhw.range) ) {//Target within range, engage unit_attack(&ed->bl,target->id,1); return 1; } @@ -795,8 +797,8 @@ int read_elementaldb(void) { db = &elemental_db[j]; db->class_ = atoi(str[0]); - strncpy(db->sprite, str[1], NAME_LENGTH); - strncpy(db->name, str[2], NAME_LENGTH); + safestrncpy(db->sprite, str[1], NAME_LENGTH); + safestrncpy(db->name, str[2], NAME_LENGTH); db->lv = atoi(str[3]); status = &db->status; diff --git a/src/map/guild.c b/src/map/guild.c index 780154590..b83f05f00 100644 --- a/src/map/guild.c +++ b/src/map/guild.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -89,8 +90,7 @@ static TBL_PC* guild_sd_check(int guild_id, int account_id, int char_id) } // Modified [Komurka] -int guild_skill_get_max (int id) -{ +int guild_skill_get_max (int id) { if (id < GD_SKILLBASE || id >= GD_SKILLBASE+MAX_GUILDSKILL) return 0; return guild_skill_tree[id-GD_SKILLBASE].max; @@ -155,7 +155,7 @@ int guild_check_skill_require(struct guild *g,int id) for(i=0;i<MAX_GUILD_SKILL_REQUIRE;i++) { if(guild_skill_tree[idx].need[i].id == 0) break; - if(guild_skill_tree[idx].need[i].lv > guild_checkskill(g,guild_skill_tree[idx].need[i].id)) + if(guild_skill_tree[idx].need[i].lv > guild->checkskill(g,guild_skill_tree[idx].need[i].id)) return 0; } return 1; @@ -229,7 +229,7 @@ struct guild_castle* guild_mapindex2gc(short mapindex) /// lookup: map name -> castle* struct guild_castle* guild_mapname2gc(const char* mapname) { - return guild_mapindex2gc(mapindex_name2id(mapname)); + return guild->mapindex2gc(mapindex_name2id(mapname)); } struct map_session_data* guild_getavailablesd(struct guild* g) @@ -259,7 +259,7 @@ int guild_getposition(struct guild* g, struct map_session_data* sd) { int i; - if( g == NULL && (g=guild_search(sd->status.guild_id)) == NULL ) + if( g == NULL && (g=sd->guild) == NULL ) return -1; ARR_FIND( 0, g->max_member, i, g->member[i].account_id == sd->status.account_id && g->member[i].char_id == sd->status.char_id ); @@ -296,11 +296,11 @@ int guild_payexp_timer_sub(DBKey key, DBData *data, va_list ap) { struct guild_expcache *c; struct guild *g; - c = db_data2ptr(data); + c = DB->data2ptr(data); if ( - (g = guild_search(c->guild_id)) == NULL || - (i = guild_getindex(g, c->account_id, c->char_id)) < 0 + (g = guild->search(c->guild_id)) == NULL || + (i = guild->getindex(g, c->account_id, c->char_id)) < 0 ) { ers_free(expcache_ers, c); return 0; @@ -331,7 +331,7 @@ int guild_payexp_timer(int tid, unsigned int tick, int id, intptr_t data) */ int guild_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) { - struct guild *g = db_data2ptr(data); + struct guild *g = DB->data2ptr(data); int i; nullpo_ret(g); @@ -345,7 +345,7 @@ int guild_send_xy_timer_sub(DBKey key, DBData *data, va_list ap) struct map_session_data* sd = g->member[i].sd; if( sd != NULL && sd->fd && (sd->guild_x != sd->bl.x || sd->guild_y != sd->bl.y) && !sd->bg_id ) { - clif_guild_xy(sd); + clif->guild_xy(sd); sd->guild_x = sd->bl.x; sd->guild_y = sd->bl.y; } @@ -363,7 +363,7 @@ static int guild_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data int guild_send_dot_remove(struct map_session_data *sd) { if (sd->status.guild_id) - clif_guild_xy_remove(sd); + clif->guild_xy_remove(sd); return 0; } //------------------------------------------------------------------------ @@ -382,12 +382,12 @@ int guild_create(struct map_session_data *sd, const char *name) if( sd->status.guild_id ) {// already in a guild - clif_guild_created(sd,1); + clif->guild_created(sd,1); return 0; } if( battle_config.guild_emperium_check && pc_search_inventory(sd,714) == -1 ) {// item required - clif_guild_created(sd,3); + clif->guild_created(sd,3); return 0; } @@ -398,19 +398,18 @@ int guild_create(struct map_session_data *sd, const char *name) } //Whether or not to create guild -int guild_created(int account_id,int guild_id) -{ +int guild_created(int account_id,int guild_id) { struct map_session_data *sd=map_id2sd(account_id); if(sd==NULL) return 0; if(!guild_id) { - clif_guild_created(sd, 2); // Creation failure (presence of the same name Guild) + clif->guild_created(sd, 2); // Creation failure (presence of the same name Guild) return 0; } //struct guild *g; sd->status.guild_id=guild_id; - clif_guild_created(sd,0); + clif->guild_created(sd,0); if(battle_config.guild_emperium_check) pc_delitem(sd,pc_search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption return 0; @@ -425,7 +424,7 @@ int guild_request_info(int guild_id) //Information request with event int guild_npc_request_info(int guild_id,const char *event) { - if( guild_search(guild_id) ) + if( guild->search(guild_id) ) { if( event && *event ) npc_event_do(event); @@ -440,11 +439,11 @@ int guild_npc_request_info(int guild_id,const char *event) ev=(struct eventlist *)aCalloc(sizeof(struct eventlist),1); memcpy(ev->name,event,strlen(event)); //The one in the db (if present) becomes the next event from this. - if (guild_infoevent_db->put(guild_infoevent_db, db_i2key(guild_id), db_ptr2data(ev), &prev)) - ev->next = db_data2ptr(&prev); + if (guild_infoevent_db->put(guild_infoevent_db, DB->i2key(guild_id), DB->ptr2data(ev), &prev)) + ev->next = DB->data2ptr(&prev); } - return guild_request_info(guild_id); + return guild->request_info(guild_id); } //Confirmation of the character belongs to guild @@ -457,19 +456,19 @@ int guild_check_member(struct guild *g) nullpo_ret(g); iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if( sd->status.guild_id != g->guild_id ) continue; - i = guild_getindex(g,sd->status.account_id,sd->status.char_id); + i = guild->getindex(g,sd->status.account_id,sd->status.char_id); if (i < 0) { sd->status.guild_id=0; sd->guild_emblem_id=0; ShowWarning("guild: check_member %d[%s] is not member\n",sd->status.account_id,sd->status.name); } } - mapit_free(iter); + mapit->free(iter); return 0; } @@ -481,54 +480,100 @@ int guild_recv_noinfo(int guild_id) struct s_mapiterator* iter; iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) - { + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if( sd->status.guild_id == guild_id ) sd->status.guild_id = 0; // erase guild } - mapit_free(iter); + mapit->free(iter); return 0; } //Get and display information for all member -int guild_recv_info(struct guild *sg) -{ +int guild_recv_info(struct guild *sg) { struct guild *g,before; int i,bm,m; DBData data; struct map_session_data *sd; bool guild_new = false; + void *aChSysSave = NULL; nullpo_ret(sg); - if((g = (struct guild*)idb_get(guild_db,sg->guild_id))==NULL) - { + if((g = (struct guild*)idb_get(guild_db,sg->guild_id))==NULL) { guild_new = true; g=(struct guild *)aCalloc(1,sizeof(struct guild)); idb_put(guild_db,sg->guild_id,g); - before=*sg; + if( hChSys.ally ) { + struct hChSysCh *channel; + + CREATE(channel, struct hChSysCh , 1); + safestrncpy(channel->name, hChSys.ally_name, HCHSYS_NAME_LENGTH); + channel->type = hChSys_ALLY; + + clif->chsys_create(channel,NULL,NULL,hChSys.ally_color); + if( hChSys.ally_autojoin ) { + struct s_mapiterator* iter = mapit_getallusers(); + struct guild *tg[MAX_GUILDALLIANCE]; + + for (i = 0; i < MAX_GUILDALLIANCE; i++) { + tg[i] = NULL; + if( sg->alliance[i].opposition == 0 && sg->alliance[i].guild_id ) + tg[i] = guild->search(sg->alliance[i].guild_id); + } + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { + if( sd->status.guild_id ) { + if( sd->status.guild_id == sg->guild_id ) { + clif->chsys_join(channel,sd); + sd->guild = g; + } + + for (i = 0; i < MAX_GUILDALLIANCE; i++) { + if( sg->alliance[i].opposition == 0 && sg->alliance[i].guild_id ) { + if( sg->alliance[i].guild_id == sd->status.guild_id ) { + clif->chsys_join(channel,sd); + } else if( tg[i] != NULL ) { + if( !(((struct hChSysCh*)tg[i]->channel)->banned && idb_exists(((struct hChSysCh*)tg[i]->channel)->banned, sd->status.account_id))) + clif->chsys_join((struct hChSysCh*)tg[i]->channel,sd); + } + } + } + } + } + + mapit->free(iter); + + } + + aChSysSave = (void*)channel; + + } + before=*sg; //Perform the check on the user because the first load guild_check_member(sg); - if ((sd = map_nick2sd(sg->master)) != NULL) - { + if ((sd = map_nick2sd(sg->master)) != NULL) { //If the guild master is online the first time the guild_info is received, //that means he was the first to join, so apply guild skill blocking here. if( battle_config.guild_skill_relog_delay ) - guild_block_skill(sd, 300000); + guild->block_skill(sd, 300000); //Also set the guild master flag. + sd->guild = g; sd->state.gmaster_flag = g; - clif_charnameupdate(sd); // [LuzZza] - clif_guild_masterormember(sd); + clif->charnameupdate(sd); // [LuzZza] + clif->guild_masterormember(sd); } - }else + } else { before=*g; + if( g->channel ) + aChSysSave = g->channel; + } memcpy(g,sg,sizeof(struct guild)); - - if(g->max_member > MAX_GUILD) - { + + g->channel = aChSysSave; + + if(g->max_member > MAX_GUILD) { ShowError("guild_recv_info: Received guild with %d members, but MAX_GUILD is only %d. Extra guild-members have been lost!\n", g->max_member, MAX_GUILD); g->max_member = MAX_GUILD; } @@ -536,7 +581,7 @@ int guild_recv_info(struct guild *sg) for(i=bm=m=0;i<g->max_member;i++){ if(g->member[i].account_id>0){ sd = g->member[i].sd = guild_sd_check(g->guild_id, g->member[i].account_id, g->member[i].char_id); - if (sd) clif_charnameupdate(sd); // [LuzZza] + if (sd) clif->charnameupdate(sd); // [LuzZza] m++; }else g->member[i].sd=NULL; @@ -548,32 +593,31 @@ int guild_recv_info(struct guild *sg) sd = g->member[i].sd; if( sd==NULL ) continue; - + sd->guild = g; if (before.guild_lv != g->guild_lv || bm != m || before.max_member != g->max_member) { - clif_guild_basicinfo(sd); //Submit basic information - clif_guild_emblem(sd, g); //Submit emblem + clif->guild_basicinfo(sd); //Submit basic information + clif->guild_emblem(sd, g); //Submit emblem } if (bm != m) { //Send members information - clif_guild_memberlist(g->member[i].sd); + clif->guild_memberlist(g->member[i].sd); } if (before.skill_point != g->skill_point) - clif_guild_skillinfo(sd); //Submit information skills + clif->guild_skillinfo(sd); //Submit information skills if (guild_new) { // Send information and affiliation if unsent - clif_guild_belonginfo(sd, g); - clif_guild_notice(sd, g); + clif->guild_belonginfo(sd, g); + clif->guild_notice(sd, g); sd->guild_emblem_id = g->emblem_id; } } //Occurrence of an event - if (guild_infoevent_db->remove(guild_infoevent_db, db_i2key(sg->guild_id), &data)) - { - struct eventlist *ev = db_data2ptr(&data), *ev2; - while(ev){ + if (guild_infoevent_db->remove(guild_infoevent_db, DB->i2key(sg->guild_id), &data)) { + struct eventlist *ev = DB->data2ptr(&data), *ev2; + while(ev) { npc_event_do(ev->name); ev2=ev->next; aFree(ev); @@ -593,23 +637,23 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) { nullpo_ret(sd); - g=guild_search(sd->status.guild_id); + g=sd->guild; if(tsd==NULL || g==NULL) return 0; - if( (i=guild_getposition(g,sd))<0 || !(g->position[i].mode&0x0001) ) + if( (i=guild->getposition(g,sd))<0 || !(g->position[i].mode&0x0001) ) return 0; //Invite permission. if(!battle_config.invite_request_check) { if (tsd->party_invite > 0 || tsd->trade_partner || tsd->adopt_invite) { //checking if there no other invitation pending - clif_guild_inviteack(sd,0); + clif->guild_inviteack(sd,0); return 0; } } if (!tsd->fd) { //You can't invite someone who has already disconnected. - clif_guild_inviteack(sd,1); + clif->guild_inviteack(sd,1); return 0; } @@ -617,21 +661,21 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) { tsd->guild_invite>0 || ((agit_flag || agit2_flag) && map[tsd->bl.m].flag.gvg_castle)) { //Can't invite people inside castles. [Skotlex] - clif_guild_inviteack(sd,0); + clif->guild_inviteack(sd,0); return 0; } //search an empty spot in guild ARR_FIND( 0, g->max_member, i, g->member[i].account_id == 0 ); if(i==g->max_member){ - clif_guild_inviteack(sd,3); + clif->guild_inviteack(sd,3); return 0; } tsd->guild_invite=sd->status.guild_id; tsd->guild_invite_account=sd->status.account_id; - clif_guild_invite(tsd,g); + clif->guild_invite(tsd,g); return 0; } @@ -653,14 +697,14 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) if ( sd->status.guild_id > 0 ) // [Paradox924X] { // Already in another guild. - if ( tsd ) clif_guild_inviteack(tsd,0); + if ( tsd ) clif->guild_inviteack(tsd,0); return 0; } else if( flag == 0 ) {// rejected sd->guild_invite = 0; sd->guild_invite_account = 0; - if( tsd ) clif_guild_inviteack(tsd,1); + if( tsd ) clif->guild_inviteack(tsd,1); } else {// accepted @@ -668,7 +712,7 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) struct guild* g; int i; - if( (g=guild_search(guild_id)) == NULL ) + if( (g=guild->search(guild_id)) == NULL ) { sd->guild_invite = 0; sd->guild_invite_account = 0; @@ -680,7 +724,7 @@ int guild_reply_invite(struct map_session_data* sd, int guild_id, int flag) { sd->guild_invite = 0; sd->guild_invite_account = 0; - if( tsd ) clif_guild_inviteack(tsd,3); + if( tsd ) clif->guild_inviteack(tsd,3); return 0; } @@ -700,23 +744,40 @@ void guild_member_joined(struct map_session_data *sd) { struct guild* g; int i; - g=guild_search(sd->status.guild_id); + g=guild->search(sd->status.guild_id); if (!g) { - guild_request_info(sd->status.guild_id); + guild->request_info(sd->status.guild_id); return; } - if (strcmp(sd->status.name,g->master) == 0) - { // set the Guild Master flag + if (strcmp(sd->status.name,g->master) == 0) { // set the Guild Master flag sd->state.gmaster_flag = g; // prevent Guild Skills from being used directly after relog if( battle_config.guild_skill_relog_delay ) - guild_block_skill(sd, 300000); + guild->block_skill(sd, 300000); } - i = guild_getindex(g, sd->status.account_id, sd->status.char_id); + i = guild->getindex(g, sd->status.account_id, sd->status.char_id); if (i == -1) sd->status.guild_id = 0; - else + else { + g->member[i].sd = sd; + sd->guild = g; + + if( hChSys.ally && hChSys.ally_autojoin ) { + struct guild* sg = NULL; + struct hChSysCh *channel = (struct hChSysCh*)g->channel; + + if( !(channel->banned && idb_exists(channel->banned, sd->status.account_id) ) ) + clif->chsys_join(channel,sd); + for (i = 0; i < MAX_GUILDALLIANCE; i++) { + if( g->alliance[i].opposition == 0 && g->alliance[i].guild_id && (sg = guild->search(g->alliance[i].guild_id) ) ) { + if( !(((struct hChSysCh*)sg->channel)->banned && idb_exists(((struct hChSysCh*)sg->channel)->banned, sd->status.account_id))) + clif->chsys_join((struct hChSysCh*)sg->channel,sd); + } + } + } + + } } /*========================================== @@ -727,7 +788,7 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag) struct map_session_data *sd= map_id2sd(account_id),*sd2; struct guild *g; - if( (g=guild_search(guild_id))==NULL ) + if( (g=guild->search(guild_id))==NULL ) return 0; if(sd==NULL || sd->guild_invite==0){ @@ -744,24 +805,25 @@ int guild_member_added(int guild_id,int account_id,int char_id,int flag) if (flag == 1) { //failure if( sd2!=NULL ) - clif_guild_inviteack(sd2,3); + clif->guild_inviteack(sd2,3); return 0; } //if all ok add player to guild sd->status.guild_id = g->guild_id; sd->guild_emblem_id = g->emblem_id; + sd->guild = g; //Packets which were sent in the previous 'guild_sent' implementation. - clif_guild_belonginfo(sd,g); - clif_guild_notice(sd,g); + clif->guild_belonginfo(sd,g); + clif->guild_notice(sd,g); //TODO: send new emblem info to others if( sd2!=NULL ) - clif_guild_inviteack(sd2,2); + clif->guild_inviteack(sd2,2); //Next line commented because it do nothing, look at guild_recv_info [LuzZza] - //clif_charnameupdate(sd); //Update display name [Skotlex] + //clif->charnameupdate(sd); //Update display name [Skotlex] return 0; } @@ -775,7 +837,7 @@ int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int c nullpo_ret(sd); - g = guild_search(sd->status.guild_id); + g = sd->guild; if(g==NULL) return 0; @@ -800,7 +862,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i nullpo_ret(sd); - g = guild_search(sd->status.guild_id); + g = sd->guild; if(g==NULL) return 0; @@ -808,7 +870,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i if(sd->status.guild_id!=guild_id) return 0; - if( (ps=guild_getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) ) + if( (ps=guild->getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) ) return 0; //Expulsion permission //Can't leave inside guild castles. @@ -818,7 +880,7 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i return 0; // find the member and perform expulsion - i = guild_getindex(g, account_id, char_id); + i = guild->getindex(g, account_id, char_id); if( i != -1 && strcmp(g->member[i].name,g->master) != 0 ) //Can't expel the GL! intif_guild_leave(g->guild_id,account_id,char_id,1,mes); @@ -828,42 +890,44 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, const char* name, const char* mes) { int i; - struct guild* g = guild_search(guild_id); + struct guild* g = guild->search(guild_id); struct map_session_data* sd = map_charid2sd(char_id); struct map_session_data* online_member_sd; if(g == NULL) return 0; // no such guild (error!) - i = guild_getindex(g, account_id, char_id); + i = guild->getindex(g, account_id, char_id); if( i == -1 ) return 0; // not a member (inconsistency!) - online_member_sd = guild_getavailablesd(g); + online_member_sd = guild->getavailablesd(g); if(online_member_sd == NULL) return 0; // noone online to inform if(!flag) - clif_guild_leave(online_member_sd, name, mes); + clif->guild_leave(online_member_sd, name, mes); else - clif_guild_expulsion(online_member_sd, name, mes, account_id); + clif->guild_expulsion(online_member_sd, name, mes, account_id); // remove member from guild memset(&g->member[i],0,sizeof(struct guild_member)); - clif_guild_memberlist(online_member_sd); + clif->guild_memberlist(online_member_sd); // update char, if online - if(sd != NULL && sd->status.guild_id == guild_id) - { + if(sd != NULL && sd->status.guild_id == guild_id) { // do stuff that needs the guild_id first, BEFORE we wipe it if (sd->state.storage_flag == 2) //Close the guild storage. storage_guild_storageclose(sd); - guild_send_dot_remove(sd); - + guild->send_dot_remove(sd); + if( hChSys.ally ) { + clif->chsys_quitg(sd); + } sd->status.guild_id = 0; + sd->guild = NULL; sd->guild_emblem_id = 0; - clif_charnameupdate(sd); //Update display name [Skotlex] + clif->charnameupdate(sd); //Update display name [Skotlex] //TODO: send emblem update to self and people around } return 0; @@ -878,14 +942,14 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) if(sd->status.guild_id <= 0) return 0; - if(!(g = guild_search(sd->status.guild_id))) + if(!(g = sd->guild)) return 0; intif_guild_memberinfoshort(g->guild_id, sd->status.account_id,sd->status.char_id,online,sd->status.base_level,sd->status.class_); if(!online){ - int i=guild_getindex(g,sd->status.account_id,sd->status.char_id); + int i=guild->getindex(g,sd->status.account_id,sd->status.char_id); if(i>=0) g->member[i].sd=NULL; else @@ -895,8 +959,8 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online) if(sd->state.connect_new) { //Note that this works because it is invoked in parse_LoadEndAck before connect_new is cleared. - clif_guild_belonginfo(sd,g); - clif_guild_notice(sd,g); + clif->guild_belonginfo(sd,g); + clif->guild_notice(sd,g); sd->guild_emblem_id = g->emblem_id; } return 0; @@ -906,7 +970,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin { // cleaned up [LuzZza] int i,alv,c,idx=-1,om=0,oldonline=-1; - struct guild *g = guild_search(guild_id); + struct guild *g = guild->search(guild_id); if(g == NULL) return 0; @@ -945,7 +1009,7 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin g->member[idx].sd = guild_sd_check(guild_id, account_id, char_id); if(oldonline!=online) - clif_guild_memberlogin_notice(g, idx, online); + clif->guild_memberlogin_notice(g, idx, online); if(!g->member[idx].sd) return 0; @@ -958,8 +1022,8 @@ int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int onlin g->member[i].sd->bl.m != g->member[idx].sd->bl.m) continue; - clif_guild_xy_single(g->member[idx].sd->fd, g->member[i].sd); - clif_guild_xy_single(g->member[i].sd->fd, g->member[idx].sd); + clif->guild_xy_single(g->member[idx].sd->fd, g->member[i].sd); + clif->guild_xy_single(g->member[i].sd->fd, g->member[idx].sd); } return 0; @@ -975,10 +1039,10 @@ int guild_send_message(struct map_session_data *sd,const char *mes,int len) if(sd->status.guild_id==0) return 0; intif_guild_message(sd->status.guild_id,sd->status.account_id,mes,len); - guild_recv_message(sd->status.guild_id,sd->status.account_id,mes,len); + guild->recv_message(sd->status.guild_id,sd->status.account_id,mes,len); // Chat logging type 'G' / Guild Chat - log_chat(LOG_CHAT_GUILD, sd->status.guild_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); + logs->chat(LOG_CHAT_GUILD, sd->status.guild_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); return 0; } @@ -989,9 +1053,9 @@ int guild_send_message(struct map_session_data *sd,const char *mes,int len) int guild_recv_message(int guild_id,int account_id,const char *mes,int len) { struct guild *g; - if( (g=guild_search(guild_id))==NULL) + if( (g=guild->search(guild_id))==NULL) return 0; - clif_guild_message(g,account_id,mes,len); + clif->guild_message(g,account_id,mes,len); return 0; } @@ -1011,11 +1075,11 @@ int guild_memberposition_changed(struct guild *g,int idx,int pos) nullpo_ret(g); g->member[idx].position=pos; - clif_guild_memberpositionchanged(g,idx); + clif->guild_memberpositionchanged(g,idx); // Update char position in client [LuzZza] if(g->member[idx].sd != NULL) - clif_charnameupdate(g->member[idx].sd); + clif->charnameupdate(g->member[idx].sd); return 0; } @@ -1041,17 +1105,17 @@ int guild_change_position(int guild_id,int idx, *---------------------------------------------------*/ int guild_position_changed(int guild_id,int idx,struct guild_position *p) { - struct guild *g=guild_search(guild_id); + struct guild *g=guild->search(guild_id); int i; if(g==NULL) return 0; memcpy(&g->position[idx],p,sizeof(struct guild_position)); - clif_guild_positionchanged(g,idx); + clif->guild_positionchanged(g,idx); // Update char name in client [LuzZza] for(i=0;i<g->max_member;i++) if(g->member[i].position == idx && g->member[i].sd != NULL) - clif_charnameupdate(g->member[i].sd); + clif->charnameupdate(g->member[i].sd); return 0; } @@ -1074,7 +1138,7 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2) { int i; struct map_session_data *sd; - struct guild *g=guild_search(guild_id); + struct guild *g=guild->search(guild_id); if(g==NULL) return 0; @@ -1083,7 +1147,7 @@ int guild_notice_changed(int guild_id,const char *mes1,const char *mes2) for(i=0;i<g->max_member;i++){ if((sd=g->member[i].sd)!=NULL) - clif_guild_notice(sd,g); + clif->guild_notice(sd,g); } return 0; } @@ -1097,8 +1161,8 @@ int guild_change_emblem(struct map_session_data *sd,int len,const char *data) nullpo_ret(sd); if (battle_config.require_glory_guild && - !((g = guild_search(sd->status.guild_id)) && guild_checkskill(g, GD_GLORYGUILD)>0)) { - clif_skill_fail(sd,GD_GLORYGUILD,USESKILL_FAIL_LEVEL,0); + !((g = sd->guild) && guild->checkskill(g, GD_GLORYGUILD)>0)) { + clif->skill_fail(sd,GD_GLORYGUILD,USESKILL_FAIL_LEVEL,0); return 0; } @@ -1112,7 +1176,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) { int i; struct map_session_data *sd; - struct guild *g=guild_search(guild_id); + struct guild *g=guild->search(guild_id); if(g==NULL) return 0; @@ -1123,9 +1187,9 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) for(i=0;i<g->max_member;i++){ if((sd=g->member[i].sd)!=NULL){ sd->guild_emblem_id=emblem_id; - clif_guild_belonginfo(sd,g); - clif_guild_emblem(sd,g); - clif_guild_emblem_area(&sd->bl); + clif->guild_belonginfo(sd,g); + clif->guild_emblem(sd,g); + clif->guild_emblem_area(&sd->bl); } } {// update guardians (mobs) @@ -1142,7 +1206,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) if( md == NULL || md->guardian_data == NULL ) continue; md->guardian_data->emblem_id = emblem_id; - clif_guild_emblem_area(&md->bl); + clif->guild_emblem_area(&md->bl); } // update temporary guardians for( i = 0; i < gc->temp_guardians_max; ++i ) @@ -1151,7 +1215,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) if( md == NULL || md->guardian_data == NULL ) continue; md->guardian_data->emblem_id = emblem_id; - clif_guild_emblem_area(&md->bl); + clif->guild_emblem_area(&md->bl); } } dbi_destroy(iter); @@ -1159,7 +1223,7 @@ int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data) {// update npcs (flags or other npcs that used flagemblem to attach to this guild) for( i = 0; i < guild_flags_count; i++ ) { if( guild_flags[i] && guild_flags[i]->u.scr.guild_id == guild_id ) { - clif_guild_emblem_area(&guild_flags[i]->bl); + clif->guild_emblem_area(&guild_flags[i]->bl); } } } @@ -1179,14 +1243,13 @@ static DBData create_expcache(DBKey key, va_list args) c->account_id = sd->status.account_id; c->char_id = sd->status.char_id; c->exp = 0; - return db_ptr2data(c); + return DB->ptr2data(c); } /*==================================================== * Return taxed experience from player sd to guild *---------------------------------------------------*/ -unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) -{ +unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) { struct guild *g; struct guild_expcache *c; int per; @@ -1196,8 +1259,8 @@ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) if (!exp) return 0; if (sd->status.guild_id == 0 || - (g = guild_search(sd->status.guild_id)) == NULL || - (per = guild_getposition(g,sd)) < 0 || + (g = sd->guild) == NULL || + (per = guild->getposition(g,sd)) < 0 || (per = g->position[per].exp_mode) < 1) return 0; @@ -1206,7 +1269,7 @@ unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp) exp = exp * per / 100; //Otherwise tax everything. - c = db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); + c = DB->data2ptr(guild_expcache_db->ensure(guild_expcache_db, DB->i2key(sd->status.char_id), create_expcache, sd)); if (c->exp > UINT64_MAX - exp) c->exp = UINT64_MAX; @@ -1226,10 +1289,10 @@ int guild_getexp(struct map_session_data *sd,int exp) struct guild_expcache *c; nullpo_ret(sd); - if (sd->status.guild_id == 0 || guild_search(sd->status.guild_id) == NULL) + if (sd->status.guild_id == 0 || sd->guild == NULL) return 0; - c = db_data2ptr(guild_expcache_db->ensure(guild_expcache_db, db_i2key(sd->status.char_id), create_expcache, sd)); + c = DB->data2ptr(guild_expcache_db->ensure(guild_expcache_db, DB->i2key(sd->status.char_id), create_expcache, sd)); if (c->exp > UINT64_MAX - exp) c->exp = UINT64_MAX; else @@ -1244,12 +1307,12 @@ int guild_skillup(TBL_PC* sd, uint16 skill_id) { struct guild* g; int idx = skill_id - GD_SKILLBASE; - int max = guild_skill_get_max(skill_id); + int max = guild->skill_get_max(skill_id); nullpo_ret(sd); if( idx < 0 || idx >= MAX_GUILDSKILL || // not a guild skill - sd->status.guild_id == 0 || (g=guild_search(sd->status.guild_id)) == NULL || // no guild + sd->status.guild_id == 0 || (g=sd->guild) == NULL || // no guild strcmp(sd->status.name, g->master) ) // not the guild master return 0; @@ -1267,12 +1330,12 @@ int guild_skillup(TBL_PC* sd, uint16 skill_id) int guild_skillupack(int guild_id,uint16 skill_id,int account_id) { struct map_session_data *sd=map_id2sd(account_id); - struct guild *g=guild_search(guild_id); + struct guild *g=guild->search(guild_id); int i; if(g==NULL) return 0; if( sd != NULL ) { - clif_guild_skillup(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv); + clif->guild_skillup(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv); /* Guild Aura handling */ switch( skill_id ) { @@ -1280,7 +1343,7 @@ int guild_skillupack(int guild_id,uint16 skill_id,int account_id) case GD_GLORYWOUNDS: case GD_SOULCOLD: case GD_HAWKEYES: - guild_guildaura_refresh(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv); + guild->aura_refresh(sd,skill_id,g->skill[skill_id-GD_SKILLBASE].lv); break; } } @@ -1288,7 +1351,7 @@ int guild_skillupack(int guild_id,uint16 skill_id,int account_id) // Inform all members for(i=0;i<g->max_member;i++) if((sd=g->member[i].sd)!=NULL) - clif_guild_skillinfo(sd); + clif->guild_skillinfo(sd); return 0; } @@ -1301,11 +1364,11 @@ void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint1 return; if( !skill_lv ) return; - if( sd->sc.data[type] && (group = skill_id2group(sd->sc.data[type]->val4)) ) { - skill_delunitgroup(group); + if( sd->sc.data[type] && (group = skill->id2group(sd->sc.data[type]->val4)) ) { + skill->del_unitgroup(group,ALC_MARK); status_change_end(&sd->bl,type,INVALID_TIMER); } - group = skill_unitsetting(&sd->bl,skill_id,skill_lv,sd->bl.x,sd->bl.y,0); + group = skill->unitsetting(&sd->bl,skill_id,skill_lv,sd->bl.x,sd->bl.y,0); if( group ) { sc_start4(&sd->bl,type,100,(battle_config.guild_aura&16)?0:skill_lv,0,0,group->group_id,600000);//duration doesn't matter these status never end with val4 } @@ -1338,7 +1401,7 @@ void guild_block_skill(struct map_session_data *sd, int time) uint16 skill_id[] = { GD_BATTLEORDER, GD_REGENERATION, GD_RESTORE, GD_EMERGENCYCALL }; int i; for (i = 0; i < 4; i++) - skill_blockpc_start_(sd, skill_id[i], time , true); + skill->blockpc_start(sd, skill_id[i], time , true); } /*==================================================== @@ -1353,7 +1416,7 @@ int guild_check_alliance(int guild_id1, int guild_id2, int flag) struct guild *g; int i; - g = guild_search(guild_id1); + g = guild->search(guild_id1); if (g == NULL) return 0; @@ -1370,7 +1433,7 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) int i; if(agit_flag || agit2_flag) { // Disable alliance creation during woe [Valaris] - clif_displaymessage(sd->fd,msg_txt(676)); //"Alliances cannot be made during Guild Wars!" + clif->message(sd->fd,msg_txt(676)); //"Alliances cannot be made during Guild Wars!" return 0; } // end addition [Valaris] @@ -1380,8 +1443,8 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) if(tsd==NULL || tsd->status.guild_id<=0) return 0; - g[0]=guild_search(sd->status.guild_id); - g[1]=guild_search(tsd->status.guild_id); + g[0]=sd->guild; + g[1]=tsd->guild; if(g[0]==NULL || g[1]==NULL) return 0; @@ -1391,23 +1454,23 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) return 0; if( guild_get_alliance_count(g[0],0) >= battle_config.max_guild_alliance ) { - clif_guild_allianceack(sd,4); + clif->guild_allianceack(sd,4); return 0; } if( guild_get_alliance_count(g[1],0) >= battle_config.max_guild_alliance ) { - clif_guild_allianceack(sd,3); + clif->guild_allianceack(sd,3); return 0; } if( tsd->guild_alliance>0 ){ - clif_guild_allianceack(sd,1); + clif->guild_allianceack(sd,1); return 0; } for (i = 0; i < MAX_GUILDALLIANCE; i++) { // check if already allied if( g[0]->alliance[i].guild_id==tsd->status.guild_id && g[0]->alliance[i].opposition==0){ - clif_guild_allianceack(sd,0); + clif->guild_allianceack(sd,0); return 0; } } @@ -1415,7 +1478,7 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd) tsd->guild_alliance=sd->status.guild_id; tsd->guild_alliance_account=sd->status.account_id; - clif_guild_reqalliance(tsd,sd->status.account_id,g[0]->name); + clif->guild_reqalliance(tsd,sd->status.account_id,g[0]->name); return 0; } @@ -1429,7 +1492,7 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) nullpo_ret(sd); tsd= map_id2sd( account_id ); if (!tsd) { //Character left? Cancel alliance. - clif_guild_allianceack(sd,3); + clif->guild_allianceack(sd,3); return 0; } @@ -1440,17 +1503,17 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) int i; struct guild *g, *tg; // Reconfirm the number of alliance - g=guild_search(sd->status.guild_id); - tg=guild_search(tsd->status.guild_id); + g=sd->guild; + tg=tsd->guild; if(g==NULL || guild_get_alliance_count(g,0) >= battle_config.max_guild_alliance){ - clif_guild_allianceack(sd,4); - clif_guild_allianceack(tsd,3); + clif->guild_allianceack(sd,4); + clif->guild_allianceack(tsd,3); return 0; } if(tg==NULL || guild_get_alliance_count(tg,0) >= battle_config.max_guild_alliance){ - clif_guild_allianceack(sd,3); - clif_guild_allianceack(tsd,4); + clif->guild_allianceack(sd,3); + clif->guild_allianceack(tsd,4); return 0; } @@ -1475,7 +1538,7 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag) sd->guild_alliance=0; sd->guild_alliance_account=0; if(tsd!=NULL) - clif_guild_allianceack(tsd,3); + clif->guild_allianceack(tsd,3); } return 0; } @@ -1488,7 +1551,7 @@ int guild_delalliance(struct map_session_data *sd,int guild_id,int flag) nullpo_ret(sd); if(agit_flag || agit2_flag) { // Disable alliance breaking during woe [Valaris] - clif_displaymessage(sd->fd,msg_txt(677)); //"Alliances cannot be broken during Guild Wars!" + clif->message(sd->fd,msg_txt(677)); //"Alliances cannot be broken during Guild Wars!" return 0; } // end addition [Valaris] @@ -1506,7 +1569,7 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd) nullpo_ret(sd); - g=guild_search(sd->status.guild_id); + g=sd->guild; if(g==NULL || tsd==NULL) return 0; @@ -1515,14 +1578,14 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd) return 0; if( guild_get_alliance_count(g,1) >= battle_config.max_guild_alliance ) { - clif_guild_oppositionack(sd,1); + clif->guild_oppositionack(sd,1); return 0; } for (i = 0; i < MAX_GUILDALLIANCE; i++) { // checking relations if(g->alliance[i].guild_id==tsd->status.guild_id){ if (g->alliance[i].opposition == 1) { // check if not already hostile - clif_guild_oppositionack(sd,2); + clif->guild_oppositionack(sd,2); return 0; } if(agit_flag || agit2_flag) // Prevent the changing of alliances to oppositions during WoE. @@ -1557,8 +1620,8 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id sd[0] = map_id2sd(account_id1); sd[1] = map_id2sd(account_id2); - g[0]=guild_search(guild_id1); - g[1]=guild_search(guild_id2); + g[0]=guild->search(guild_id1); + g[1]=guild->search(guild_id2); if(sd[0]!=NULL && (flag&0x0f)==0){ sd[0]->guild_alliance=0; @@ -1568,18 +1631,24 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id if (flag & 0x70) { // failure for(i=0;i<2-(flag&1);i++) if( sd[i]!=NULL ) - clif_guild_allianceack(sd[i],((flag>>4)==i+1)?3:4); + clif->guild_allianceack(sd[i],((flag>>4)==i+1)?3:4); return 0; } + if( g[0] && g[1] && hChSys.ally && ( flag & 1 ) == 0 ) { + if( !(flag & 0x08) ) { + if( hChSys.ally_autojoin ) + clif->chsys_gjoin(g[0],g[1]); + } else { + clif->chsys_gleave(g[0],g[1]); + } + } + if (!(flag & 0x08)) { // new relationship - for(i=0;i<2-(flag&1);i++) - { - if(g[i]!=NULL) - { + for(i=0;i<2-(flag&1);i++) { + if(g[i]!=NULL) { ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == 0 ); - if( j < MAX_GUILDALLIANCE ) - { + if( j < MAX_GUILDALLIANCE ) { g[i]->alliance[j].guild_id=guild_id[1-i]; memcpy(g[i]->alliance[j].name,guild_name[1-i],NAME_LENGTH); g[i]->alliance[j].opposition=flag&1; @@ -1587,25 +1656,23 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id } } } else { // remove relationship - for(i=0;i<2-(flag&1);i++) - { - if(g[i]!=NULL) - { + for(i=0;i<2-(flag&1);i++) { + if( g[i] != NULL ) { ARR_FIND( 0, MAX_GUILDALLIANCE, j, g[i]->alliance[j].guild_id == guild_id[1-i] && g[i]->alliance[j].opposition == (flag&1) ); if( j < MAX_GUILDALLIANCE ) g[i]->alliance[j].guild_id = 0; } if (sd[i] != NULL) // notify players - clif_guild_delalliance(sd[i],guild_id[1-i],(flag&1)); + clif->guild_delalliance(sd[i],guild_id[1-i],(flag&1)); } } if ((flag & 0x0f) == 0) { // alliance notification if( sd[1]!=NULL ) - clif_guild_allianceack(sd[1],2); + clif->guild_allianceack(sd[1],2); } else if ((flag & 0x0f) == 1) { // enemy notification if( sd[0]!=NULL ) - clif_guild_oppositionack(sd[0],0); + clif->guild_oppositionack(sd[0],0); } @@ -1614,7 +1681,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id if(g[i]!=NULL) for(j=0;j<g[i]->max_member;j++) if((sd=g[i]->member[j].sd)!=NULL) - clif_guild_allianceinfo(sd); + clif->guild_allianceinfo(sd); } return 0; } @@ -1625,7 +1692,7 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id */ int guild_broken_sub(DBKey key, DBData *data, va_list ap) { - struct guild *g = db_data2ptr(data); + struct guild *g = DB->data2ptr(data); int guild_id=va_arg(ap,int); int i,j; struct map_session_data *sd=NULL; @@ -1636,7 +1703,7 @@ int guild_broken_sub(DBKey key, DBData *data, va_list ap) if(g->alliance[i].guild_id==guild_id){ for(j=0;j<g->max_member;j++) if( (sd=g->member[j].sd)!=NULL ) - clif_guild_delalliance(sd,guild_id,g->alliance[i].opposition); + clif->guild_delalliance(sd,guild_id,g->alliance[i].opposition); intif_guild_alliance(g->guild_id, guild_id,0,0,g->alliance[i].opposition|8); g->alliance[i].guild_id=0; } @@ -1650,20 +1717,20 @@ int guild_broken_sub(DBKey key, DBData *data, va_list ap) */ int castle_guild_broken_sub(DBKey key, DBData *data, va_list ap) { - char name[EVENT_NAME_LENGTH]; - struct guild_castle *gc = db_data2ptr(data); + struct guild_castle *gc = DB->data2ptr(data); int guild_id = va_arg(ap, int); nullpo_ret(gc); if (gc->guild_id == guild_id) { + char name[EVENT_NAME_LENGTH]; // We call castle_event::OnGuildBreak of all castles of the guild // You can set all castle_events in the 'db/castle_db.txt' safestrncpy(name, gc->castle_event, sizeof(name)); npc_event_do(strcat(name, "::OnGuildBreak")); //Save the new 'owner', this should invoke guardian clean up and other such things. - guild_castledatasave(gc->castle_id, 1, 0); + guild->castledatasave(gc->castle_id, 1, 0); } return 0; } @@ -1671,7 +1738,7 @@ int castle_guild_broken_sub(DBKey key, DBData *data, va_list ap) //Invoked on /breakguild "Guild name" int guild_broken(int guild_id,int flag) { - struct guild *g = guild_search(guild_id); + struct guild *g = guild->search(guild_id); struct map_session_data *sd = NULL; int i; @@ -1683,14 +1750,20 @@ int guild_broken(int guild_id,int flag) if(sd->state.storage_flag == 2) storage_guild_storage_quit(sd,1); sd->status.guild_id=0; - clif_guild_broken(g->member[i].sd,0); - clif_charnameupdate(sd); // [LuzZza] + sd->guild = NULL; + clif->guild_broken(g->member[i].sd,0); + clif->charnameupdate(sd); // [LuzZza] } } guild_db->foreach(guild_db,guild_broken_sub,guild_id); castle_db->foreach(castle_db,castle_guild_broken_sub,guild_id); guild_storage_delete(guild_id); + if( hChSys.ally ) { + if( g->channel != NULL ) { + clif->chsys_delete(( struct hChSysCh * )g->channel); + } + } idb_remove(guild_db,guild_id); return 0; } @@ -1704,7 +1777,7 @@ int guild_gm_change(int guild_id, struct map_session_data *sd) if (sd->status.guild_id != guild_id) return 0; - g=guild_search(guild_id); + g=guild->search(guild_id); nullpo_ret(g); @@ -1723,7 +1796,7 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) struct guild_member gm; int pos, i; - g=guild_search(guild_id); + g=guild->search(guild_id); if (!g) return 0; @@ -1743,18 +1816,16 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) g->member[0].position = 0; //Position 0: guild Master. strcpy(g->master, g->member[0].name); - if (g->member[pos].sd && g->member[pos].sd->fd) - { - clif_displaymessage(g->member[pos].sd->fd, msg_txt(678)); //"You no longer are the Guild Master." + if (g->member[pos].sd && g->member[pos].sd->fd) { + clif->message(g->member[pos].sd->fd, msg_txt(678)); //"You no longer are the Guild Master." g->member[pos].sd->state.gmaster_flag = 0; } - if (g->member[0].sd && g->member[0].sd->fd) - { - clif_displaymessage(g->member[0].sd->fd, msg_txt(679)); //"You have become the Guild Master!" + if (g->member[0].sd && g->member[0].sd->fd) { + clif->message(g->member[0].sd->fd, msg_txt(679)); //"You have become the Guild Master!" g->member[0].sd->state.gmaster_flag = g; //Block his skills for 5 minutes to prevent abuse. - guild_block_skill(g->member[0].sd, 300000); + guild->block_skill(g->member[0].sd, 300000); } // announce the change to all guild members @@ -1762,8 +1833,8 @@ int guild_gm_changed(int guild_id, int account_id, int char_id) { if( g->member[i].sd && g->member[i].sd->fd ) { - clif_guild_basicinfo(g->member[i].sd); - clif_guild_memberlist(g->member[i].sd); + clif->guild_basicinfo(g->member[i].sd); + clif->guild_memberlist(g->member[i].sd); } } @@ -1780,7 +1851,7 @@ int guild_break(struct map_session_data *sd,char *name) nullpo_ret(sd); - if( (g=guild_search(sd->status.guild_id))==NULL ) + if( (g=sd->guild)==NULL ) return 0; if(strcmp(g->name,name)!=0) return 0; @@ -1793,7 +1864,7 @@ int guild_break(struct map_session_data *sd,char *name) break; } if(i<g->max_member){ - clif_guild_broken(sd,2); + clif->guild_broken(sd,2); return 0; } @@ -1837,7 +1908,7 @@ void guild_castle_map_init(void) */ int guild_castledatasave(int castle_id, int index, int value) { - struct guild_castle *gc = guild_castle_search(castle_id); + struct guild_castle *gc = guild->castle_search(castle_id); if (gc == NULL) { ShowWarning("guild_castledatasave: guild castle '%d' not found\n", castle_id); @@ -1889,15 +1960,15 @@ int guild_castledatasave(int castle_id, int index, int value) } if (!intif_guild_castle_datasave(castle_id, index, value)) { - guild_castle_reconnect(castle_id, index, value); + guild->castle_reconnect(castle_id, index, value); } return 0; } void guild_castle_reconnect_sub(void *key, void *data, va_list ap) { - int castle_id = GetWord((int)__64BPRTSIZE(key), 0); - int index = GetWord((int)__64BPRTSIZE(key), 1); + int castle_id = GetWord((int)__64BPTRSIZE(key), 0); + int index = GetWord((int)__64BPTRSIZE(key), 1); intif_guild_castle_datasave(castle_id, index, *(int *)data); aFree(data); } @@ -1918,7 +1989,7 @@ void guild_castle_reconnect(int castle_id, int index, int value) int *data; CREATE(data, int, 1); *data = value; - linkdb_replace(&gc_save_pending, (void*)__64BPRTSIZE((MakeDWord(castle_id, index))), data); + linkdb_replace(&gc_save_pending, (void*)__64BPTRSIZE((MakeDWord(castle_id, index))), data); } } @@ -1938,26 +2009,24 @@ int guild_castledataloadack(int len, struct guild_castle *gc) if( ev < 0 ) { //No castles owned, invoke OnAgitInit as it is. npc_event_doall("OnAgitInit"); npc_event_doall("OnAgitInit2"); - } - else // load received castles into memory, one by one - for( i = 0; i < n; i++, gc++ ) - { - struct guild_castle *c = guild_castle_search(gc->castle_id); - if (!c) { - ShowError("guild_castledataloadack: castle id=%d not found.\n", gc->castle_id); - continue; - } + } else { // load received castles into memory, one by one + for( i = 0; i < n; i++, gc++ ) { + struct guild_castle *c = guild->castle_search(gc->castle_id); + if (!c) { + ShowError("guild_castledataloadack: castle id=%d not found.\n", gc->castle_id); + continue; + } - // update map-server castle data with new info - memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - offsetof(struct guild_castle, guild_id)); + // update map-server castle data with new info + memcpy(&c->guild_id, &gc->guild_id, sizeof(struct guild_castle) - offsetof(struct guild_castle, guild_id)); - if( c->guild_id ) - { - if( i != ev ) - guild_request_info(c->guild_id); - else { // last owned one - guild_npc_request_info(c->guild_id, "::OnAgitInit"); - guild_npc_request_info(c->guild_id, "::OnAgitInit2"); + if( c->guild_id ) { + if( i != ev ) + guild->request_info(c->guild_id); + else { // last owned one + guild->npc_request_info(c->guild_id, "::OnAgitInit"); + guild->npc_request_info(c->guild_id, "::OnAgitInit2"); + } } } } @@ -2021,7 +2090,7 @@ int guild_checkcastles(struct guild *g) bool guild_isallied(int guild_id, int guild_id2) { int i; - struct guild* g = guild_search(guild_id); + struct guild* g = guild->search(guild_id); nullpo_ret(g); ARR_FIND( 0, MAX_GUILDALLIANCE, i, g->alliance[i].guild_id == guild_id2 ); @@ -2076,7 +2145,7 @@ void guild_flag_remove(struct npc_data *nd) { */ static int eventlist_db_final(DBKey key, DBData *data, va_list ap) { struct eventlist *next = NULL; - struct eventlist *current = db_data2ptr(data); + struct eventlist *current = DB->data2ptr(data); while (current != NULL) { next = current->next; aFree(current); @@ -2089,7 +2158,7 @@ static int eventlist_db_final(DBKey key, DBData *data, va_list ap) { * @see DBApply */ static int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) { - ers_free(expcache_ers, db_data2ptr(data)); + ers_free(expcache_ers, DB->data2ptr(data)); return 0; } @@ -2097,7 +2166,7 @@ static int guild_expcache_db_final(DBKey key, DBData *data, va_list ap) { * @see DBApply */ static int guild_castle_db_final(DBKey key, DBData *data, va_list ap) { - struct guild_castle* gc = db_data2ptr(data); + struct guild_castle* gc = DB->data2ptr(data); if( gc->temp_guardians ) aFree(gc->temp_guardians); aFree(gc); @@ -2124,10 +2193,10 @@ void do_init_guild(void) { guild_flags_count = 0; - sv_readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb); + sv->readdb(db_path, "castle_db.txt", ',', 4, 5, -1, &guild_read_castledb); memset(guild_skill_tree,0,sizeof(guild_skill_tree)); - sv_readdb(db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db); //guild skill tree [Komurka] + sv->readdb(db_path, "guild_skill_tree.txt", ',', 2+MAX_GUILD_SKILL_REQUIRE*2, 2+MAX_GUILD_SKILL_REQUIRE*2, -1, &guild_read_guildskill_tree_db); //guild skill tree [Komurka] add_timer_func_list(guild_payexp_timer,"guild_payexp_timer"); add_timer_func_list(guild_send_xy_timer, "guild_send_xy_timer"); @@ -2136,6 +2205,15 @@ void do_init_guild(void) { } void do_final_guild(void) { + DBIterator *iter = db_iterator(guild_db); + struct guild *g; + + for( g = dbi_first(iter); dbi_exists(iter); g = dbi_next(iter) ) { + if( g->channel != NULL ) + clif->chsys_delete((struct hChSysCh *)g->channel); + } + + dbi_destroy(iter); db_destroy(guild_db); castle_db->destroy(castle_db,guild_castle_db_final); @@ -2145,3 +2223,86 @@ void do_final_guild(void) { aFree(guild_flags);/* never empty; created on boot */ } +void guild_defaults(void) { + guild = &guild_s; + + guild->init = do_init_guild; + guild->final = do_final_guild; + /* */ + guild->skill_get_max = guild_skill_get_max; + /* */ + guild->checkskill = guild_checkskill; + guild->check_skill_require = guild_check_skill_require; + guild->checkcastles = guild_checkcastles; + guild->isallied = guild_isallied; + /* */ + guild->search = guild_search; + guild->searchname = guild_searchname; + guild->castle_search = guild_castle_search; + /* */ + guild->mapname2gc = guild_mapname2gc; + guild->mapindex2gc = guild_mapindex2gc; + /* */ + guild->getavailablesd = guild_getavailablesd; + guild->getindex = guild_getindex; + guild->getposition = guild_getposition; + guild->payexp = guild_payexp; + guild->getexp = guild_getexp; + /* */ + guild->create = guild_create; + guild->created = guild_created; + guild->request_info = guild_request_info; + guild->recv_noinfo = guild_recv_noinfo; + guild->recv_info = guild_recv_info; + guild->npc_request_info = guild_npc_request_info; + guild->invite = guild_invite; + guild->reply_invite = guild_reply_invite; + guild->member_joined = guild_member_joined; + guild->member_added = guild_member_added; + guild->leave = guild_leave; + guild->member_withdraw = guild_member_withdraw; + guild->expulsion = guild_expulsion; + guild->skillup = guild_skillup; + guild->block_skill = guild_block_skill; + guild->reqalliance = guild_reqalliance; + guild->reply_reqalliance = guild_reply_reqalliance; + guild->allianceack = guild_allianceack; + guild->delalliance = guild_delalliance; + guild->opposition = guild_opposition; + guild->check_alliance = guild_check_alliance; + /* */ + guild->send_memberinfoshort = guild_send_memberinfoshort; + guild->recv_memberinfoshort = guild_recv_memberinfoshort; + guild->change_memberposition = guild_change_memberposition; + guild->memberposition_changed = guild_memberposition_changed; + guild->change_position = guild_change_position; + guild->position_changed = guild_position_changed; + guild->change_notice = guild_change_notice; + guild->notice_changed = guild_notice_changed; + guild->change_emblem = guild_change_emblem; + guild->emblem_changed = guild_emblem_changed; + guild->send_message = guild_send_message; + guild->recv_message = guild_recv_message; + guild->send_dot_remove = guild_send_dot_remove; + guild->skillupack = guild_skillupack; + guild->dobreak = guild_break; + guild->broken = guild_broken; + guild->gm_change = guild_gm_change; + guild->gm_changed = guild_gm_changed; + /* */ + guild->castle_map_init = guild_castle_map_init; + guild->castledatasave = guild_castledatasave; + guild->castledataloadack = guild_castledataloadack; + guild->castle_reconnect = guild_castle_reconnect; + /* */ + guild->agit_start = guild_agit_start; + guild->agit_end = guild_agit_end; + guild->agit2_start = guild_agit2_start; + guild->agit2_end = guild_agit2_end; + /* guild flag cachin */ + guild->flag_add = guild_flag_add; + guild->flag_remove = guild_flag_remove; + guild->flags_clear = guild_flags_clear; + /* guild aura */ + guild->aura_refresh = guild_guildaura_refresh; +} diff --git a/src/map/guild.h b/src/map/guild.h index 0df93d138..9841f5451 100644 --- a/src/map/guild.h +++ b/src/map/guild.h @@ -1,5 +1,6 @@ -// 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 _GUILD_H_ #define _GUILD_H_ @@ -23,90 +24,90 @@ struct guardian_data { struct guild_castle* castle; }; -int guild_skill_get_max(int id); - -int guild_checkskill(struct guild *g,int id); -int guild_check_skill_require(struct guild *g,int id); // [Komurka] -int guild_checkcastles(struct guild *g); // [MouseJstr] -bool guild_isallied(int guild_id, int guild_id2); //Checks alliance based on guild Ids. [Skotlex] - -void do_init_guild(void); -struct guild *guild_search(int guild_id); -struct guild *guild_searchname(char *str); -struct guild_castle *guild_castle_search(int gcid); - -struct guild_castle* guild_mapname2gc(const char* mapname); -struct guild_castle* guild_mapindex2gc(short mapindex); - -struct map_session_data *guild_getavailablesd(struct guild *g); -int guild_getindex(struct guild *g,int account_id,int char_id); -int guild_getposition(struct guild *g, struct map_session_data *sd); -unsigned int guild_payexp(struct map_session_data *sd,unsigned int exp); -int guild_getexp(struct map_session_data *sd,int exp); // [Celest] - -int guild_create(struct map_session_data *sd, const char *name); -int guild_created(int account_id,int guild_id); -int guild_request_info(int guild_id); -int guild_recv_noinfo(int guild_id); -int guild_recv_info(struct guild *sg); -int guild_npc_request_info(int guild_id,const char *ev); -int guild_invite(struct map_session_data *sd,struct map_session_data *tsd); -int guild_reply_invite(struct map_session_data *sd,int guild_id,int flag); -void guild_member_joined(struct map_session_data *sd); -int guild_member_added(int guild_id,int account_id,int char_id,int flag); -int guild_leave(struct map_session_data *sd,int guild_id, - int account_id,int char_id,const char *mes); -int guild_member_withdraw(int guild_id,int account_id,int char_id,int flag, - const char *name,const char *mes); -int guild_expulsion(struct map_session_data *sd,int guild_id, - int account_id,int char_id,const char *mes); -int guild_skillup(struct map_session_data* sd, uint16 skill_id); -void guild_block_skill(struct map_session_data *sd, int time); -int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd); -int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag); -int guild_alliance(int guild_id1,int guild_id2,int account_id1,int account_id2); -int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id2, - int flag,const char *name1,const char *name2); -int guild_delalliance(struct map_session_data *sd,int guild_id,int flag); -int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd); -int guild_check_alliance(int guild_id1, int guild_id2, int flag); - -int guild_send_memberinfoshort(struct map_session_data *sd,int online); -int guild_recv_memberinfoshort(int guild_id,int account_id,int char_id,int online,int lv,int class_); -int guild_change_memberposition(int guild_id,int account_id,int char_id,short idx); -int guild_memberposition_changed(struct guild *g,int idx,int pos); -int guild_change_position(int guild_id,int idx,int mode,int exp_mode,const char *name); -int guild_position_changed(int guild_id,int idx,struct guild_position *p); -int guild_change_notice(struct map_session_data *sd,int guild_id,const char *mes1,const char *mes2); -int guild_notice_changed(int guild_id,const char *mes1,const char *mes2); -int guild_change_emblem(struct map_session_data *sd,int len,const char *data); -int guild_emblem_changed(int len,int guild_id,int emblem_id,const char *data); -int guild_send_message(struct map_session_data *sd,const char *mes,int len); -int guild_recv_message(int guild_id,int account_id,const char *mes,int len); -int guild_send_dot_remove(struct map_session_data *sd); -int guild_skillupack(int guild_id,uint16 skill_id,int account_id); -int guild_break(struct map_session_data *sd,char *name); -int guild_broken(int guild_id,int flag); -int guild_gm_change(int guild_id, struct map_session_data *sd); -int guild_gm_changed(int guild_id, int account_id, int char_id); - -void guild_castle_map_init(void); -int guild_castledatasave(int castle_id,int index,int value); -int guild_castledataloadack(int len, struct guild_castle *gc); -void guild_castle_reconnect(int castle_id, int index, int value); - -void guild_agit_start(void); -void guild_agit_end(void); - -void guild_agit2_start(void); -void guild_agit2_end(void); -/* guild flag cachin */ -void guild_flag_add(struct npc_data *nd); -void guild_flag_remove(struct npc_data *nd); -void guild_flags_clear(void); - -void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); - -void do_final_guild(void); +struct guild_interface { + void (*init) (void); + void (*final) (void); + /* */ + int (*skill_get_max) (int id); + /* */ + int (*checkskill) (struct guild *g,int id); + int (*check_skill_require) (struct guild *g,int id); // [Komurka] + int (*checkcastles) (struct guild *g); // [MouseJstr] + bool (*isallied) (int guild_id, int guild_id2); //Checks alliance based on guild Ids. [Skotlex] + /* */ + struct guild *(*search) (int guild_id); + struct guild *(*searchname) (char *str); + struct guild_castle *(*castle_search) (int gcid); + /* */ + struct guild_castle *(*mapname2gc) (const char* mapname); + struct guild_castle *(*mapindex2gc) (short mapindex); + /* */ + struct map_session_data *(*getavailablesd) (struct guild *g); + int (*getindex) (struct guild *g,int account_id,int char_id); + int (*getposition) (struct guild *g, struct map_session_data *sd); + unsigned int (*payexp) (struct map_session_data *sd,unsigned int exp); + int (*getexp) (struct map_session_data *sd,int exp); // [Celest] + /* */ + int (*create) (struct map_session_data *sd, const char *name); + int (*created) (int account_id,int guild_id); + int (*request_info) (int guild_id); + int (*recv_noinfo) (int guild_id); + int (*recv_info) (struct guild *sg); + int (*npc_request_info) (int guild_id,const char *ev); + int (*invite) (struct map_session_data *sd,struct map_session_data *tsd); + int (*reply_invite) (struct map_session_data *sd,int guild_id,int flag); + void (*member_joined) (struct map_session_data *sd); + int (*member_added) (int guild_id,int account_id,int char_id,int flag); + int (*leave) (struct map_session_data *sd,int guild_id,int account_id,int char_id,const char *mes); + int (*member_withdraw) (int guild_id,int account_id,int char_id,int flag,const char *name,const char *mes); + int (*expulsion) (struct map_session_data *sd,int guild_id,int account_id,int char_id,const char *mes); + int (*skillup) (struct map_session_data* sd, uint16 skill_id); + void (*block_skill) (struct map_session_data *sd, int time); + int (*reqalliance) (struct map_session_data *sd,struct map_session_data *tsd); + int (*reply_reqalliance) (struct map_session_data *sd,int account_id,int flag); + int (*allianceack) (int guild_id1,int guild_id2,int account_id1,int account_id2,int flag,const char *name1,const char *name2); + int (*delalliance) (struct map_session_data *sd,int guild_id,int flag); + int (*opposition) (struct map_session_data *sd,struct map_session_data *tsd); + int (*check_alliance) (int guild_id1, int guild_id2, int flag); + /* */ + int (*send_memberinfoshort) (struct map_session_data *sd,int online); + int (*recv_memberinfoshort) (int guild_id,int account_id,int char_id,int online,int lv,int class_); + int (*change_memberposition) (int guild_id,int account_id,int char_id,short idx); + int (*memberposition_changed) (struct guild *g,int idx,int pos); + int (*change_position) (int guild_id,int idx,int mode,int exp_mode,const char *name); + int (*position_changed) (int guild_id,int idx,struct guild_position *p); + int (*change_notice) (struct map_session_data *sd,int guild_id,const char *mes1,const char *mes2); + int (*notice_changed) (int guild_id,const char *mes1,const char *mes2); + int (*change_emblem) (struct map_session_data *sd,int len,const char *data); + int (*emblem_changed) (int len,int guild_id,int emblem_id,const char *data); + int (*send_message) (struct map_session_data *sd,const char *mes,int len); + int (*recv_message) (int guild_id,int account_id,const char *mes,int len); + int (*send_dot_remove) (struct map_session_data *sd); + int (*skillupack) (int guild_id,uint16 skill_id,int account_id); + int (*dobreak) (struct map_session_data *sd,char *name); + int (*broken) (int guild_id,int flag); + int (*gm_change) (int guild_id, struct map_session_data *sd); + int (*gm_changed) (int guild_id, int account_id, int char_id); + /* */ + void (*castle_map_init) (void); + int (*castledatasave) (int castle_id,int index,int value); + int (*castledataloadack) (int len, struct guild_castle *gc); + void (*castle_reconnect) (int castle_id, int index, int value); + /* */ + void (*agit_start) (void); + void (*agit_end) (void); + void (*agit2_start) (void); + void (*agit2_end) (void); + /* guild flag cachin */ + void (*flag_add) (struct npc_data *nd); + void (*flag_remove) (struct npc_data *nd); + void (*flags_clear) (void); + /* guild aura */ + void (*aura_refresh) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); +} guild_s; + +struct guild_interface *guild; + +void guild_defaults(void); #endif /* _GUILD_H_ */ diff --git a/src/map/homunculus.c b/src/map/homunculus.c index 081287d8a..e306e7f60 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -39,50 +40,41 @@ #include <string.h> #include <math.h> -struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; //[orn] -struct homun_skill_tree_entry hskill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; - -static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data); - -static unsigned int hexptbl[MAX_LEVEL]; - -//For holding the view data of npc classes. [Skotlex] -static struct view_data hom_viewdb[MAX_HOMUNCULUS_CLASS]; - -struct view_data* merc_get_hom_viewdata(int class_) -{ //Returns the viewdata for homunculus +//Returns the viewdata for homunculus +struct view_data* homunculus_get_viewdata(int class_) { if (homdb_checkid(class_)) - return &hom_viewdb[class_-HM_CLASS_BASE]; + return &homun->viewdb[class_-HM_CLASS_BASE]; return NULL; } -int hom_class2mapid(int hom_class) -{ - switch(hom_class) - { +enum homun_type homunculus_class2type(int class_) { + switch(class_) { // Normal Homunculus - case 6001: case 6005: return MAPID_LIF; - case 6002: case 6006: return MAPID_AMISTR; - case 6003: case 6007: return MAPID_FILIR; - case 6004: case 6008: return MAPID_VANILMIRTH; + case 6001: case 6005: + case 6002: case 6006: + case 6003: case 6007: + case 6004: case 6008: + return HT_REG; // Evolved Homunculus - case 6009: case 6013: return MAPID_LIF_E; - case 6010: case 6014: return MAPID_AMISTR_E; - case 6011: case 6015: return MAPID_FILIR_E; - case 6012: case 6016: return MAPID_VANILMIRTH_E; + case 6009: case 6013: + case 6010: case 6014: + case 6011: case 6015: + case 6012: case 6016: + return HT_EVO; // Homunculus S - case 6048: return MAPID_EIRA; - case 6049: return MAPID_BAYERI; - case 6050: return MAPID_SERA; - case 6051: return MAPID_DIETER; - case 6052: return MAPID_ELANOR; - - default: return -1; + case 6048: + case 6049: + case 6050: + case 6051: + case 6052: + return HT_S; + default: + return -1; } } -int hom_addspiritball(TBL_HOM *hd, int max) { - nullpo_ret(hd); +void homunculus_addspiritball(struct homun_data *hd, int max) { + nullpo_retv(hd); if (max > MAX_SKILL_LEVEL) max = MAX_SKILL_LEVEL; @@ -95,20 +87,18 @@ int hom_addspiritball(TBL_HOM *hd, int max) { else hd->homunculus.spiritball++; - clif_spiritball(&hd->bl); - - return 0; + clif->spiritball(&hd->bl); } -int hom_delspiritball(TBL_HOM *hd, int count, int type) { - nullpo_ret(hd); +void homunculus_delspiritball(struct homun_data *hd, int count, int type) { + nullpo_retv(hd); if (hd->homunculus.spiritball <= 0) { hd->homunculus.spiritball = 0; - return 0; + return; } if (count <= 0) - return 0; + return; if (count > MAX_SKILL_LEVEL) count = MAX_SKILL_LEVEL; if (count > hd->homunculus.spiritball) @@ -116,37 +106,33 @@ int hom_delspiritball(TBL_HOM *hd, int count, int type) { hd->homunculus.spiritball -= count; if (!type) - clif_spiritball(&hd->bl); - - return 0; + clif->spiritball(&hd->bl); } -void merc_damage(struct homun_data *hd) { - clif_hominfo(hd->master,hd,0); +void homunculus_damaged(struct homun_data *hd) { + clif->hominfo(hd->master,hd,0); } -int merc_hom_dead(struct homun_data *hd) -{ +int homunculus_dead(struct homun_data *hd) { //There's no intimacy penalties on death (from Tharis) struct map_session_data *sd = hd->master; - clif_emotion(&hd->bl, E_WAH); + clif->emotion(&hd->bl, E_WAH); //Delete timers when dead. - merc_hom_hungry_timer_delete(hd); + homun->hunger_timer_delete(hd); hd->homunculus.hp = 0; if (!sd) //unit remove map will invoke unit free return 3; - clif_emotion(&sd->bl, E_SOB); + clif->emotion(&sd->bl, E_SOB); //Remove from map (if it has no intimacy, it is auto-removed from memory) return 3; } //Vaporize a character's homun. If flag, HP needs to be 80% or above. -int merc_hom_vaporize(struct map_session_data *sd, int flag) -{ +int homunculus_vaporize(struct map_session_data *sd, int flag) { struct homun_data *hd; nullpo_ret(sd); @@ -163,19 +149,18 @@ int merc_hom_vaporize(struct map_session_data *sd, int flag) hd->regen.state.block = 3; //Block regen while vaporized. //Delete timers when vaporized. - merc_hom_hungry_timer_delete(hd); + homun->hunger_timer_delete(hd); hd->homunculus.vaporize = 1; if(battle_config.hom_setting&0x40) memset(hd->blockskill, 0, sizeof(hd->blockskill)); - clif_hominfo(sd, sd->hd, 0); - merc_save(hd); + clif->hominfo(sd, sd->hd, 0); + homun->save(hd); return unit_remove_map(&hd->bl, CLR_OUTSIGHT); } //delete a homunculus, completely "killing it". //Emote is the emotion the master should use, send negative to disable. -int merc_hom_delete(struct homun_data *hd, int emote) -{ +int homunculus_delete(struct homun_data *hd, int emote) { struct map_session_data *sd; nullpo_ret(hd); sd = hd->master; @@ -184,18 +169,17 @@ int merc_hom_delete(struct homun_data *hd, int emote) return unit_free(&hd->bl,CLR_DEAD); if (emote >= 0) - clif_emotion(&sd->bl, emote); + clif->emotion(&sd->bl, emote); //This makes it be deleted right away. hd->homunculus.intimacy = 0; // Send homunculus_dead to client hd->homunculus.hp = 0; - clif_hominfo(sd, hd, 0); + clif->hominfo(sd, hd, 0); return unit_remove_map(&hd->bl,CLR_OUTSIGHT); } -int merc_hom_calc_skilltree(struct homun_data *hd, int flag_evolve) -{ +int homunculus_calc_skilltree(struct homun_data *hd, int flag_evolve) { int i, id = 0; int j, f = 1; int c = 0; @@ -205,13 +189,13 @@ int merc_hom_calc_skilltree(struct homun_data *hd, int flag_evolve) if( hd->homunculus.prev_class != 0 ) { c = hd->homunculus.prev_class - HM_CLASS_BASE; - for( i = 0; i < MAX_SKILL_TREE && ( id = hskill_tree[c][i].id ) > 0; i++ ) { + for( i = 0; i < MAX_SKILL_TREE && ( id = homun->skill_tree[c][i].id ) > 0; i++ ) { if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id ) continue; //Skill already known. if(!battle_config.skillfree) { for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { - if( hskill_tree[c][i].need[j].id && - merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv ) { + if( homun->skill_tree[c][i].need[j].id && + homun->checkskill(hd,homun->skill_tree[c][i].need[j].id) < homun->skill_tree[c][i].need[j].lv ) { f = 0; break; } @@ -226,16 +210,16 @@ int merc_hom_calc_skilltree(struct homun_data *hd, int flag_evolve) c = hd->homunculus.class_ - HM_CLASS_BASE; - for( i = 0; i < MAX_SKILL_TREE && ( id = hskill_tree[c][i].id ) > 0; i++ ) { + for( i = 0; i < MAX_SKILL_TREE && ( id = homun->skill_tree[c][i].id ) > 0; i++ ) { if( hd->homunculus.hskill[ id - HM_SKILLBASE ].id ) continue; //Skill already known. j = ( flag_evolve ) ? 10 : hd->homunculus.intimacy; - if( j < hskill_tree[c][i].intimacylv ) + if( j < homun->skill_tree[c][i].intimacylv ) continue; if(!battle_config.skillfree) { for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { - if( hskill_tree[c][i].need[j].id && - merc_hom_checkskill(hd,hskill_tree[c][i].need[j].id) < hskill_tree[c][i].need[j].lv ) { + if( homun->skill_tree[c][i].need[j].id && + homun->checkskill(hd,homun->skill_tree[c][i].need[j].id) < homun->skill_tree[c][i].need[j].lv ) { f = 0; break; } @@ -246,12 +230,11 @@ int merc_hom_calc_skilltree(struct homun_data *hd, int flag_evolve) } if( hd->master ) - clif_homskillinfoblock(hd->master); + clif->homskillinfoblock(hd->master); return 0; } -int merc_hom_checkskill(struct homun_data *hd,uint16 skill_id) -{ +int homunculus_checkskill(struct homun_data *hd,uint16 skill_id) { int i = skill_id - HM_SKILLBASE; if(!hd) return 0; @@ -262,17 +245,16 @@ int merc_hom_checkskill(struct homun_data *hd,uint16 skill_id) return 0; } -int merc_skill_tree_get_max(int id, int b_class){ +int homunculus_skill_tree_get_max(int id, int b_class) { int i, skill_id; b_class -= HM_CLASS_BASE; - for(i=0;(skill_id=hskill_tree[b_class][i].id)>0;i++) + for(i=0;(skill_id=homun->skill_tree[b_class][i].id)>0;i++) if (id == skill_id) - return hskill_tree[b_class][i].max; - return skill_get_max(id); + return homun->skill_tree[b_class][i].max; + return skill->get_max(id); } -void merc_hom_skillup(struct homun_data *hd,uint16 skill_id) -{ +void homunculus_skillup(struct homun_data *hd,uint16 skill_id) { int i = 0 ; nullpo_retv(hd); @@ -283,44 +265,54 @@ void merc_hom_skillup(struct homun_data *hd,uint16 skill_id) if(hd->homunculus.skillpts > 0 && hd->homunculus.hskill[i].id && hd->homunculus.hskill[i].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] - hd->homunculus.hskill[i].lv < merc_skill_tree_get_max(skill_id, hd->homunculus.class_) + hd->homunculus.hskill[i].lv < homun->skill_tree_get_max(skill_id, hd->homunculus.class_) ) { hd->homunculus.hskill[i].lv++; hd->homunculus.skillpts-- ; status_calc_homunculus(hd,0); if (hd->master) { - clif_homskillup(hd->master, skill_id); - clif_hominfo(hd->master,hd,0); - clif_homskillinfoblock(hd->master); + clif->homskillup(hd->master, skill_id); + clif->hominfo(hd->master,hd,0); + clif->homskillinfoblock(hd->master); } } } -int merc_hom_levelup(struct homun_data *hd) -{ +bool homunculus_levelup(struct homun_data *hd) { struct s_homunculus *hom; struct h_stats *min, *max; int growth_str, growth_agi, growth_vit, growth_int, growth_dex, growth_luk ; - int growth_max_hp, growth_max_sp ; - char output[256] ; - int m_class; + int growth_max_hp, growth_max_sp; + enum homun_type htype; - if((m_class = hom_class2mapid(hd->homunculus.class_)) == -1) { - ShowError("merc_hom_levelup: Invalid class %d. \n", hd->homunculus.class_); - return 0; + if((htype = homun->class2type(hd->homunculus.class_)) == -1) { + ShowError("homunculus_levelup: Invalid class %d. \n", hd->homunculus.class_); + return false; } - - if((m_class&HOM_REG) && (hd->homunculus.level >= battle_config.hom_max_level || ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) || !hd->exp_next || hd->homunculus.exp < hd->exp_next)) - return 0; - + + if( !hd->exp_next || hd->homunculus.exp < hd->exp_next ) + return false; + + switch( htype ) { + case HT_REG: + case HT_EVO: + if( hd->homunculus.level >= battle_config.hom_max_level ) + return false; + break; + case HT_S: + if( hd->homunculus.level >= battle_config.hom_S_max_level ) + return false; + break; + } + hom = &hd->homunculus; hom->level++ ; if (!(hom->level % 3)) - hom->skillpts++ ; //1 skillpoint each 3 base level + hom->skillpts++; //1 skillpoint each 3 base level - hom->exp -= hd->exp_next ; - hd->exp_next = hexptbl[hom->level - 1] ; + hom->exp -= hd->exp_next; + hd->exp_next = homun->exptable[hom->level - 1]; max = &hd->homunculusDB->gmax; min = &hd->homunculusDB->gmin; @@ -352,48 +344,47 @@ int merc_hom_levelup(struct homun_data *hd) hom->luk += growth_luk; if ( battle_config.homunculus_show_growth ) { + char output[256] ; sprintf(output, "Growth: hp:%d sp:%d str(%.2f) agi(%.2f) vit(%.2f) int(%.2f) dex(%.2f) luk(%.2f) ", growth_max_hp, growth_max_sp, growth_str/10.0, growth_agi/10.0, growth_vit/10.0, growth_int/10.0, growth_dex/10.0, growth_luk/10.0); - clif_disp_onlyself(hd->master,output,strlen(output)); + clif->disp_onlyself(hd->master,output,strlen(output)); } - return 1 ; + return true; } -int merc_hom_change_class(struct homun_data *hd, short class_) -{ +int homunculus_change_class(struct homun_data *hd, short class_) { int i; - i = search_homunculusDB_index(class_,HOMUNCULUS_CLASS); + i = homun->db_search(class_,HOMUNCULUS_CLASS); if(i < 0) return 0; - hd->homunculusDB = &homunculus_db[i]; + hd->homunculusDB = &homun->db[i]; hd->homunculus.class_ = class_; status_set_viewdata(&hd->bl, class_); - merc_hom_calc_skilltree(hd, 1); + homun->calc_skilltree(hd, 1); return 1; } -int merc_hom_evolution(struct homun_data *hd) -{ +bool homunculus_evolve(struct homun_data *hd) { struct s_homunculus *hom; struct h_stats *max, *min; struct map_session_data *sd; nullpo_ret(hd); - if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) - { - clif_emotion(&hd->bl, E_SWT); - return 0 ; - } sd = hd->master; if (!sd) - return 0; + return false; + + if(!hd->homunculusDB->evo_class || hd->homunculus.class_ == hd->homunculusDB->evo_class) { + clif->emotion(&hd->bl, E_SWT); + return false; + } - if (!merc_hom_change_class(hd, hd->homunculusDB->evo_class)) { - ShowError("merc_hom_evolution: Can't evolve homunc from %d to %d", hd->homunculus.class_, hd->homunculusDB->evo_class); - return 0; + if (!homun->change_class(hd, hd->homunculusDB->evo_class)) { + ShowError("homunculus_evolve: Can't evolve homunc from %d to %d", hd->homunculus.class_, hd->homunculusDB->evo_class); + return false; } //Apply evolution bonuses @@ -413,9 +404,9 @@ int merc_hom_evolution(struct homun_data *hd) unit_remove_map(&hd->bl, CLR_OUTSIGHT); map_addblock(&hd->bl); - clif_spawn(&hd->bl); - clif_emotion(&sd->bl, E_NO1); - clif_specialeffect(&hd->bl,568,AREA); + clif->spawn(&hd->bl); + clif->emotion(&sd->bl, E_NO1); + clif->specialeffect(&hd->bl,568,AREA); //status_Calc flag&1 will make current HP/SP be reloaded from hom structure hom->hp = hd->battle_status.hp; @@ -423,43 +414,43 @@ int merc_hom_evolution(struct homun_data *hd) status_calc_homunculus(hd,1); if (!(battle_config.hom_setting&0x2)) - skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately + skill->unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately - return 1 ; + return true; } -int hom_mutate(struct homun_data *hd, int homun_id) -{ +bool homunculus_mutate(struct homun_data *hd, int homun_id) { struct s_homunculus *hom; struct map_session_data *sd; - int m_class, m_id, prev_class = 0; + int prev_class = 0; + enum homun_type m_class, m_id; nullpo_ret(hd); - m_class = hom_class2mapid(hd->homunculus.class_); - m_id = hom_class2mapid(homun_id); - - if( m_class == -1 || m_id == -1 || !(m_class&HOM_EVO) || !(m_id&HOM_S) ) { - clif_emotion(&hd->bl, E_SWT); - return 0; - } - sd = hd->master; if (!sd) - return 0; + return false; + + m_class = homun->class2type(hd->homunculus.class_); + m_id = homun->class2type(homun_id); + + if( m_class == -1 || m_id == -1 || m_class != HT_EVO || m_id != HT_S ) { + clif->emotion(&hd->bl, E_SWT); + return false; + } prev_class = hd->homunculus.class_; - if (!merc_hom_change_class(hd, homun_id)) { - ShowError("hom_mutate: Can't evolve homunc from %d to %d", hd->homunculus.class_, homun_id); - return 0; + if (!homun->change_class(hd, homun_id)) { + ShowError("homunculus_mutate: Can't evolve homunc from %d to %d", hd->homunculus.class_, homun_id); + return false; } unit_remove_map(&hd->bl, CLR_OUTSIGHT); map_addblock(&hd->bl); - clif_spawn(&hd->bl); - clif_emotion(&sd->bl, E_NO1); - clif_specialeffect(&hd->bl,568,AREA); + clif->spawn(&hd->bl); + clif->emotion(&sd->bl, E_NO1); + clif->specialeffect(&hd->bl,568,AREA); //status_Calc flag&1 will make current HP/SP be reloaded from hom structure @@ -470,56 +461,55 @@ int hom_mutate(struct homun_data *hd, int homun_id) status_calc_homunculus(hd,1); if (!(battle_config.hom_setting&0x2)) - skill_unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately + skill->unit_move(&sd->hd->bl,gettick(),1); // apply land skills immediately - return 1; + return true; } -int merc_hom_gainexp(struct homun_data *hd,int exp) -{ - int m_class; +int homunculus_gainexp(struct homun_data *hd,unsigned int exp) { + enum homun_type htype; if(hd->homunculus.vaporize) return 1; - - if((m_class = hom_class2mapid(hd->homunculus.class_)) == -1) { - ShowError("merc_hom_gainexp: Invalid class %d. \n", hd->homunculus.class_); + + if((htype = homun->class2type(hd->homunculus.class_)) == -1) { + ShowError("homunculus_gainexp: Invalid class %d. \n", hd->homunculus.class_); return 0; } - - if( hd->exp_next == 0 || - ((m_class&HOM_REG) && hd->homunculus.level >= battle_config.hom_max_level) || - ((m_class&HOM_S) && hd->homunculus.level >= battle_config.hom_S_max_level) ) { - hd->homunculus.exp = 0; - return 0; + + switch( htype ) { + case HT_REG: + case HT_EVO: + if( hd->homunculus.level >= battle_config.hom_max_level ) + return 0; + break; + case HT_S: + if( hd->homunculus.level >= battle_config.hom_S_max_level ) + return 0; + break; } hd->homunculus.exp += exp; if(hd->homunculus.exp < hd->exp_next) { - clif_hominfo(hd->master,hd,0); + clif->hominfo(hd->master,hd,0); return 0; } //levelup - do - { - merc_hom_levelup(hd) ; - } - while(hd->homunculus.exp > hd->exp_next && hd->exp_next != 0 ); + while( hd->homunculus.exp > hd->exp_next && homun->levelup(hd) ); if( hd->exp_next == 0 ) - hd->homunculus.exp = 0 ; + hd->homunculus.exp = 0; - clif_specialeffect(&hd->bl,568,AREA); + clif->specialeffect(&hd->bl,568,AREA); status_calc_homunculus(hd,0); status_percent_heal(&hd->bl, 100, 100); return 0; } // Return the new value -int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value) -{ +unsigned int homunculus_add_intimacy(struct homun_data *hd, unsigned int value) { if (battle_config.homunculus_friendly_rate != 100) value = (value * battle_config.homunculus_friendly_rate) / 100; @@ -531,8 +521,7 @@ int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value) } // Return 0 if decrease fails or intimacy became 0 else the new value -int merc_hom_decrease_intimacy(struct homun_data * hd, unsigned int value) -{ +unsigned int homunculus_consume_intimacy(struct homun_data *hd, unsigned int value) { if (hd->homunculus.intimacy >= value) hd->homunculus.intimacy -= value; else @@ -541,12 +530,11 @@ int merc_hom_decrease_intimacy(struct homun_data * hd, unsigned int value) return hd->homunculus.intimacy; } -void merc_hom_heal(struct homun_data *hd) { - clif_hominfo(hd->master,hd,0); +void homunculus_healed (struct homun_data *hd) { + clif->hominfo(hd->master,hd,0); } -void merc_save(struct homun_data *hd) -{ +void homunculus_save(struct homun_data *hd) { // copy data that must be saved in homunculus struct ( hp / sp ) TBL_PC * sd = hd->master; //Do not check for max_hp/max_sp caps as current could be higher to max due @@ -557,57 +545,55 @@ void merc_save(struct homun_data *hd) intif_homunculus_requestsave(sd->status.account_id, &hd->homunculus); } -int merc_menu(struct map_session_data *sd,int menunum) -{ +unsigned char homunculus_menu(struct map_session_data *sd,unsigned char menu_num) { nullpo_ret(sd); if (sd->hd == NULL) return 1; - switch(menunum) { + switch(menu_num) { case 0: break; case 1: - merc_hom_food(sd, sd->hd); + homun->feed(sd, sd->hd); break; case 2: - merc_hom_delete(sd->hd, -1); + homun->delete(sd->hd, -1); break; default: - ShowError("merc_menu : unknown menu choice : %d\n", menunum) ; + ShowError("homunculus_menu : unknown menu choice : %d\n", menu_num) ; break; } return 0; } -int merc_hom_food(struct map_session_data *sd, struct homun_data *hd) -{ +bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) { int i, foodID, emotion; if(hd->homunculus.vaporize) - return 1 ; + return false; foodID = hd->homunculusDB->foodID; i = pc_search_inventory(sd,foodID); if(i < 0) { - clif_hom_food(sd,foodID,0); - return 1; + clif->hom_food(sd,foodID,0); + return false; } pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); if ( hd->homunculus.hunger >= 91 ) { - merc_hom_decrease_intimacy(hd, 50); + homun->consume_intimacy(hd, 50); emotion = E_WAH; } else if ( hd->homunculus.hunger >= 76 ) { - merc_hom_decrease_intimacy(hd, 5); + homun->consume_intimacy(hd, 5); emotion = E_SWT2; } else if ( hd->homunculus.hunger >= 26 ) { - merc_hom_increase_intimacy(hd, 75); + homun->add_intimacy(hd, 75); emotion = E_HO; } else if ( hd->homunculus.hunger >= 11 ) { - merc_hom_increase_intimacy(hd, 100); + homun->add_intimacy(hd, 100); emotion = E_HO; } else { - merc_hom_increase_intimacy(hd, 50); + homun->add_intimacy(hd, 50); emotion = E_HO; } @@ -615,32 +601,27 @@ int merc_hom_food(struct map_session_data *sd, struct homun_data *hd) if(hd->homunculus.hunger > 100) hd->homunculus.hunger = 100; - clif_emotion(&hd->bl,emotion); - clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); - clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); - clif_hom_food(sd,foodID,1); + clif->emotion(&hd->bl,emotion); + clif->send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); + clif->send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); + clif->hom_food(sd,foodID,1); // Too much food :/ if(hd->homunculus.intimacy == 0) - return merc_hom_delete(sd->hd, E_OMG); + return homun->delete(sd->hd, E_OMG); - return 0; + return true; } -static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data) -{ +int homunculus_hunger_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd; struct homun_data *hd; - sd=map_id2sd(id); - if(!sd) - return 1; - - if(!sd->status.hom_id || !(hd=sd->hd)) + if(!(sd=map_id2sd(id)) || !sd->status.hom_id || !(hd=sd->hd)) return 1; if(hd->hungry_timer != tid){ - ShowError("merc_hom_hungry_timer %d != %d\n",hd->hungry_timer,tid); + ShowError("homunculus_hunger_timer %d != %d\n",hd->hungry_timer,tid); return 0; } @@ -648,44 +629,41 @@ static int merc_hom_hungry(int tid, unsigned int tick, int id, intptr_t data) hd->homunculus.hunger-- ; if(hd->homunculus.hunger <= 10) { - clif_emotion(&hd->bl, E_AN); + clif->emotion(&hd->bl, E_AN); } else if(hd->homunculus.hunger == 25) { - clif_emotion(&hd->bl, E_HMM); + clif->emotion(&hd->bl, E_HMM); } else if(hd->homunculus.hunger == 75) { - clif_emotion(&hd->bl, E_OK); + clif->emotion(&hd->bl, E_OK); } if(hd->homunculus.hunger < 0) { hd->homunculus.hunger = 0; // Delete the homunculus if intimacy <= 100 - if ( !merc_hom_decrease_intimacy(hd, 100) ) - return merc_hom_delete(hd, E_OMG); - clif_send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); + if ( !homun->consume_intimacy(hd, 100) ) + return homun->delete(hd, E_OMG); + clif->send_homdata(sd,SP_INTIMATE,hd->homunculus.intimacy / 100); } - clif_send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); - hd->hungry_timer = add_timer(tick+hd->homunculusDB->hungryDelay,merc_hom_hungry,sd->bl.id,0); //simple Fix albator + clif->send_homdata(sd,SP_HUNGRY,hd->homunculus.hunger); + hd->hungry_timer = add_timer(tick+hd->homunculusDB->hungryDelay,homun->hunger_timer,sd->bl.id,0); //simple Fix albator return 0; } -int merc_hom_hungry_timer_delete(struct homun_data *hd) -{ - nullpo_ret(hd); +void homunculus_hunger_timer_delete(struct homun_data *hd) { + nullpo_retv(hd); if(hd->hungry_timer != INVALID_TIMER) { - delete_timer(hd->hungry_timer,merc_hom_hungry); + delete_timer(hd->hungry_timer,homun->hunger_timer); hd->hungry_timer = INVALID_TIMER; } - return 1; } -int merc_hom_change_name(struct map_session_data *sd,char *name) -{ +int homunculus_change_name(struct map_session_data *sd,char *name) { int i; struct homun_data *hd; nullpo_retr(1, sd); hd = sd->hd; - if (!merc_is_hom_active(hd)) + if (!homun_alive(hd)) return 1; if(hd->homunculus.rename_flag && !battle_config.hom_rename) return 1; @@ -698,39 +676,37 @@ int merc_hom_change_name(struct map_session_data *sd,char *name) return intif_rename_hom(sd, name); } -int merc_hom_change_name_ack(struct map_session_data *sd, char* name, int flag) -{ +bool homunculus_change_name_ack(struct map_session_data *sd, char* name, int flag) { struct homun_data *hd = sd->hd; - if (!merc_is_hom_active(hd)) return 0; + if (!homun_alive(hd)) return false; normalize_name(name," ");//bugreport:3032 if ( !flag || !strlen(name) ) { - clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name - return 0; + clif->message(sd->fd, msg_txt(280)); // You cannot use this name + return false; } - strncpy(hd->homunculus.name,name,NAME_LENGTH); - clif_charnameack (0,&hd->bl); + safestrncpy(hd->homunculus.name,name,NAME_LENGTH); + clif->charnameack (0,&hd->bl); hd->homunculus.rename_flag = 1; - clif_hominfo(sd,hd,0); - return 1; + clif->hominfo(sd,hd,0); + return true; } -int search_homunculusDB_index(int key,int type) -{ +int homunculus_db_search(int key,int type) { int i; for(i=0;i<MAX_HOMUNCULUS_CLASS;i++) { - if(homunculus_db[i].base_class <= 0) + if(homun->db[i].base_class <= 0) continue; switch(type) { case HOMUNCULUS_CLASS: - if(homunculus_db[i].base_class == key || - homunculus_db[i].evo_class == key) + if(homun->db[i].base_class == key || + homun->db[i].evo_class == key) return i; break; case HOMUNCULUS_FOOD: - if(homunculus_db[i].foodID == key) + if(homun->db[i].foodID == key) return i; break; default: @@ -741,30 +717,29 @@ int search_homunculusDB_index(int key,int type) } // Create homunc structure -int merc_hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) -{ +bool homunculus_create(struct map_session_data *sd, struct s_homunculus *hom) { struct homun_data *hd; int i = 0; - nullpo_retr(1, sd); + nullpo_retr(false, sd); Assert((sd->status.hom_id == 0 || sd->hd == 0) || sd->hd->master == sd); - i = search_homunculusDB_index(hom->class_,HOMUNCULUS_CLASS); + i = homun->db_search(hom->class_,HOMUNCULUS_CLASS); if(i < 0) { - ShowError("merc_hom_alloc: unknown class [%d] for homunculus '%s', requesting deletion.\n", hom->class_, hom->name); + ShowError("homunculus_create: unknown class [%d] for homunculus '%s', requesting deletion.\n", hom->class_, hom->name); sd->status.hom_id = 0; intif_homunculus_requestdelete(hom->hom_id); - return 1; + return false; } sd->hd = hd = (struct homun_data*)aCalloc(1,sizeof(struct homun_data)); hd->bl.type = BL_HOM; hd->bl.id = npc_get_new_npc_id(); hd->master = sd; - hd->homunculusDB = &homunculus_db[i]; + hd->homunculusDB = &homun->db[i]; memcpy(&hd->homunculus, hom, sizeof(struct s_homunculus)); - hd->exp_next = hexptbl[hd->homunculus.level - 1]; + hd->exp_next = homun->exptable[hd->homunculus.level - 1]; status_set_viewdata(&hd->bl, hd->homunculus.class_); status_change_init(&hd->bl); @@ -783,22 +758,20 @@ int merc_hom_alloc(struct map_session_data *sd, struct s_homunculus *hom) status_calc_homunculus(hd,1); hd->hungry_timer = INVALID_TIMER; - return 0; + return true; } -void merc_hom_init_timers(struct homun_data * hd) -{ +void homunculus_init_timers(struct homun_data * hd) { if (hd->hungry_timer == INVALID_TIMER) - hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,merc_hom_hungry,hd->master->bl.id,0); + hd->hungry_timer = add_timer(gettick()+hd->homunculusDB->hungryDelay,homun->hunger_timer,hd->master->bl.id,0); hd->regen.state.block = 0; //Restore HP/SP block. } -int merc_call_homunculus(struct map_session_data *sd) -{ +bool homunculus_call(struct map_session_data *sd) { struct homun_data *hd; if (!sd->status.hom_id) //Create a new homun. - return merc_create_homunculus_request(sd, HM_CLASS_BASE + rnd_value(0, 7)) ; + return homun->creation_request(sd, HM_CLASS_BASE + rnd_value(0, 7)); // If homunc not yet loaded, load it if (!sd->hd) @@ -807,116 +780,126 @@ int merc_call_homunculus(struct map_session_data *sd) hd = sd->hd; if (!hd->homunculus.vaporize) - return 0; //Can't use this if homun wasn't vaporized. + return false; //Can't use this if homun wasn't vaporized. - merc_hom_init_timers(hd); + homun->init_timers(hd); hd->homunculus.vaporize = 0; - if (hd->bl.prev == NULL) - { //Spawn him + if (hd->bl.prev == NULL) { //Spawn him hd->bl.x = sd->bl.x; hd->bl.y = sd->bl.y; hd->bl.m = sd->bl.m; map_addblock(&hd->bl); - clif_spawn(&hd->bl); - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,hd,1); - clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] - clif_homskillinfoblock(sd); + clif->spawn(&hd->bl); + clif->send_homdata(sd,SP_ACK,0); + clif->hominfo(sd,hd,1); + clif->hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] + clif->homskillinfoblock(sd); if (battle_config.slaves_inherit_speed&1) status_calc_bl(&hd->bl, SCB_SPEED); - merc_save(hd); + homun->save(hd); } else //Warp him to master. unit_warp(&hd->bl,sd->bl.m, sd->bl.x, sd->bl.y,CLR_OUTSIGHT); - return 1; + return true; } // Recv homunculus data from char server -int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag) -{ +bool homunculus_recv_data(int account_id, struct s_homunculus *sh, int flag) { struct map_session_data *sd; struct homun_data *hd; sd = map_id2sd(account_id); if(!sd) - return 0; - if (sd->status.char_id != sh->char_id) - { + return false; + if (sd->status.char_id != sh->char_id) { if (sd->status.hom_id == sh->hom_id) sh->char_id = sd->status.char_id; //Correct char id. else - return 0; + return false; } if(!flag) { // Failed to load sd->status.hom_id = 0; - return 0; + return false; } if (!sd->status.hom_id) //Hom just created. sd->status.hom_id = sh->hom_id; + if (sd->hd) //uh? Overwrite the data. memcpy(&sd->hd->homunculus, sh, sizeof(struct s_homunculus)); else - merc_hom_alloc(sd, sh); + homun->create(sd, sh); hd = sd->hd; - if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL) - { + if(hd && hd->homunculus.hp && !hd->homunculus.vaporize && hd->bl.prev == NULL && sd->bl.prev != NULL) { + enum homun_type htype = homun->class2type(hd->homunculus.class_); + map_addblock(&hd->bl); - clif_spawn(&hd->bl); - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,hd,1); - clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] - clif_homskillinfoblock(sd); - merc_hom_init_timers(hd); + clif->spawn(&hd->bl); + clif->send_homdata(sd,SP_ACK,0); + clif->hominfo(sd,hd,1); + clif->hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] + clif->homskillinfoblock(sd); + homun->init_timers(hd); + /* force shuffle if your level is higher than the allowed */ + switch( htype ) { + case HT_REG: + case HT_EVO: + if( hd->homunculus.level > battle_config.hom_max_level ) + homun->shuffle(hd); + break; + case HT_S: + if( hd->homunculus.level > battle_config.hom_S_max_level ) + homun->shuffle(hd); + break; + } + } - return 1; + return true; } // Ask homunculus creation to char server -int merc_create_homunculus_request(struct map_session_data *sd, int class_) -{ - struct s_homunculus homun; +bool homunculus_creation_request(struct map_session_data *sd, int class_) { + struct s_homunculus hom; struct h_stats *base; int i; - nullpo_retr(1, sd); + nullpo_retr(false, sd); - i = search_homunculusDB_index(class_,HOMUNCULUS_CLASS); - if(i < 0) return 0; + i = homun->db_search(class_,HOMUNCULUS_CLASS); + if(i < 0) return false; - memset(&homun, 0, sizeof(struct s_homunculus)); + memset(&hom, 0, sizeof(struct s_homunculus)); //Initial data - strncpy(homun.name, homunculus_db[i].name, NAME_LENGTH-1); - homun.class_ = class_; - homun.level = 1; - homun.hunger = 32; //32% - homun.intimacy = 2100; //21/1000 - homun.char_id = sd->status.char_id; - - homun.hp = 10 ; - base = &homunculus_db[i].base; - homun.max_hp = base->HP; - homun.max_sp = base->SP; - homun.str = base->str *10; - homun.agi = base->agi *10; - homun.vit = base->vit *10; - homun.int_= base->int_*10; - homun.dex = base->dex *10; - homun.luk = base->luk *10; + safestrncpy(hom.name, homun->db[i].name, NAME_LENGTH-1); + hom.class_ = class_; + hom.level = 1; + hom.hunger = 32; //32% + hom.intimacy = 2100; //21/1000 + hom.char_id = sd->status.char_id; + + hom.hp = 10 ; + base = &homun->db[i].base; + hom.max_hp = base->HP; + hom.max_sp = base->SP; + hom.str = base->str *10; + hom.agi = base->agi *10; + hom.vit = base->vit *10; + hom.int_= base->int_*10; + hom.dex = base->dex *10; + hom.luk = base->luk *10; // Request homunculus creation - intif_homunculus_create(sd->status.account_id, &homun); - return 1; + intif_homunculus_create(sd->status.account_id, &hom); + return true; } -int merc_resurrect_homunculus(struct map_session_data* sd, unsigned char per, short x, short y) -{ +bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short x, short y) { struct homun_data* hd; - nullpo_ret(sd); + nullpo_retr(false,sd); if (!sd->status.hom_id) - return 0; // no homunculus + return false; // no homunculus if (!sd->hd) //Load homun data; return intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); @@ -924,39 +907,37 @@ int merc_resurrect_homunculus(struct map_session_data* sd, unsigned char per, sh hd = sd->hd; if (hd->homunculus.vaporize) - return 0; // vaporized homunculi need to be 'called' + return false; // vaporized homunculi need to be 'called' if (!status_isdead(&hd->bl)) - return 0; // already alive + return false; // already alive - merc_hom_init_timers(hd); + homun->init_timers(hd); - if (!hd->bl.prev) - { //Add it back to the map. + if (!hd->bl.prev) { + //Add it back to the map. hd->bl.m = sd->bl.m; hd->bl.x = x; hd->bl.y = y; map_addblock(&hd->bl); - clif_spawn(&hd->bl); + clif->spawn(&hd->bl); } status_revive(&hd->bl, per, 0); - return 1; + return true; } -void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp) -{ +void homunculus_revive(struct homun_data *hd, unsigned int hp, unsigned int sp) { struct map_session_data *sd = hd->master; hd->homunculus.hp = hd->battle_status.hp; if (!sd) return; - clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,hd,1); - clif_hominfo(sd,hd,0); - clif_homskillinfoblock(sd); + clif->send_homdata(sd,SP_ACK,0); + clif->hominfo(sd,hd,1); + clif->hominfo(sd,hd,0); + clif->homskillinfoblock(sd); } - -void merc_reset_stats(struct homun_data *hd) -{ //Resets a homunc stats back to zero (but doesn't touches hunger or intimacy) +//Resets a homunc stats back to zero (but doesn't touches hunger or intimacy) +void homunculus_stat_reset(struct homun_data *hd) { struct s_homunculus_db *db; struct s_homunculus *hom; struct h_stats *base; @@ -974,33 +955,33 @@ void merc_reset_stats(struct homun_data *hd) hom->dex = base->dex *10; hom->luk = base->luk *10; hom->exp = 0; - hd->exp_next = hexptbl[0]; + hd->exp_next = homun->exptable[0]; memset(&hd->homunculus.hskill, 0, sizeof hd->homunculus.hskill); hd->homunculus.skillpts = 0; } -int merc_hom_shuffle(struct homun_data *hd) -{ +bool homunculus_shuffle(struct homun_data *hd) { struct map_session_data *sd; - int lv, i, skillpts; + int lv, skillpts; unsigned int exp; struct s_skill b_skill[MAX_HOMUNSKILL]; - if (!merc_is_hom_active(hd)) - return 0; + if (!homun_alive(hd)) + return false; sd = hd->master; lv = hd->homunculus.level; exp = hd->homunculus.exp; memcpy(&b_skill, &hd->homunculus.hskill, sizeof(b_skill)); skillpts = hd->homunculus.skillpts; + //Reset values to level 1. - merc_reset_stats(hd); + homun->stat_reset(hd); + //Level it back up - for (i = 1; i < lv && hd->exp_next; i++){ + do { hd->homunculus.exp += hd->exp_next; - merc_hom_levelup(hd); - } + } while( hd->homunculus.level < lv && homun->levelup(hd) ); if(hd->homunculus.class_ == hd->homunculusDB->evo_class) { //Evolved bonuses @@ -1019,38 +1000,35 @@ int merc_hom_shuffle(struct homun_data *hd) hd->homunculus.exp = exp; memcpy(&hd->homunculus.hskill, &b_skill, sizeof(b_skill)); hd->homunculus.skillpts = skillpts; - clif_homskillinfoblock(sd); + clif->homskillinfoblock(sd); status_calc_homunculus(hd,0); status_percent_heal(&hd->bl, 100, 100); - clif_specialeffect(&hd->bl,568,AREA); + clif->specialeffect(&hd->bl,568,AREA); - return 1; + return true; } -static bool read_homunculusdb_sub(char* str[], int columns, int current) -{ +bool homunculus_read_db_sub(char* str[], int columns, int current) { int classid; struct s_homunculus_db *db; //Base Class,Evo Class classid = atoi(str[0]); - if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) - { - ShowError("read_homunculusdb : Invalid class %d\n", classid); + if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) { + ShowError("homunculus_read_db_sub : Invalid class %d\n", classid); return false; } - db = &homunculus_db[current]; + db = &homun->db[current]; db->base_class = classid; classid = atoi(str[1]); - if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) - { + if (classid < HM_CLASS_BASE || classid > HM_CLASS_MAX) { db->base_class = 0; - ShowError("read_homunculusdb : Invalid class %d\n", classid); + ShowError("homunculus_read_db_sub : Invalid class %d\n", classid); return false; } db->evo_class = classid; //Name, Food, Hungry Delay, Base Size, Evo Size, Race, Element, ASPD - strncpy(db->name,str[2],NAME_LENGTH-1); + safestrncpy(db->name,str[2],NAME_LENGTH-1); db->foodID = atoi(str[3]); db->hungryDelay = atoi(str[4]); db->base_size = atoi(str[5]); @@ -1140,34 +1118,28 @@ static bool read_homunculusdb_sub(char* str[], int columns, int current) return true; } -int read_homunculusdb(void) -{ +void homunculus_read_db(void) { int i; const char *filename[]={"homunculus_db.txt","homunculus_db2.txt"}; - memset(homunculus_db,0,sizeof(homunculus_db)); - for(i = 0; i<ARRAYLENGTH(filename); i++) - { - char path[256]; + memset(homun->db,0,sizeof(homun->db)); + for(i = 0; i<ARRAYLENGTH(filename); i++) { + if( i > 0 ) { + char path[256]; - if( i > 0 ) - { sprintf(path, "%s/%s", db_path, filename[i]); - if( !exists(path) ) - { + if( !exists(path) ) { continue; } } - sv_readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, &read_homunculusdb_sub); + sv->readdb(db_path, filename[i], ',', 50, 50, MAX_HOMUNCULUS_CLASS, homun->read_db_sub); } - return 0; } - -static bool read_homunculus_skilldb_sub(char* split[], int columns, int current) -{// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req> +// <hom class>,<skill id>,<max level>[,<job level>],<req id1>,<req lv1>,<req id2>,<req lv2>,<req id3>,<req lv3>,<req id4>,<req lv4>,<req id5>,<req lv5>,<intimacy lv req> +bool homunculus_read_skill_db_sub(char* split[], int columns, int current) { int k, classid; int j; int minJobLevelPresent = 0; @@ -1177,47 +1149,42 @@ static bool read_homunculus_skilldb_sub(char* split[], int columns, int current) // check for bounds [celest] classid = atoi(split[0]) - HM_CLASS_BASE; - if ( classid >= MAX_HOMUNCULUS_CLASS ) - { - ShowWarning("read_homunculus_skilldb: Invalud homunculus class %d.\n", atoi(split[0])); + + if ( classid >= MAX_HOMUNCULUS_CLASS ) { + ShowWarning("homunculus_read_skill_db_sub: Invalud homunculus class %d.\n", atoi(split[0])); return false; } k = atoi(split[1]); //This is to avoid adding two lines for the same skill. [Skotlex] // Search an empty line or a line with the same skill_id (stored in j) - ARR_FIND( 0, MAX_SKILL_TREE, j, !hskill_tree[classid][j].id || hskill_tree[classid][j].id == k ); - if (j == MAX_SKILL_TREE) - { + ARR_FIND( 0, MAX_SKILL_TREE, j, !homun->skill_tree[classid][j].id || homun->skill_tree[classid][j].id == k ); + if (j == MAX_SKILL_TREE) { ShowWarning("Unable to load skill %d into homunculus %d's tree. Maximum number of skills per class has been reached.\n", k, classid); return false; } - hskill_tree[classid][j].id = k; - hskill_tree[classid][j].max = atoi(split[2]); + homun->skill_tree[classid][j].id = k; + homun->skill_tree[classid][j].max = atoi(split[2]); if (minJobLevelPresent) - hskill_tree[classid][j].joblv = atoi(split[3]); + homun->skill_tree[classid][j].joblv = atoi(split[3]); - for( k = 0; k < MAX_PC_SKILL_REQUIRE; k++ ) - { - hskill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); - hskill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); + for( k = 0; k < MAX_PC_SKILL_REQUIRE; k++ ) { + homun->skill_tree[classid][j].need[k].id = atoi(split[3+k*2+minJobLevelPresent]); + homun->skill_tree[classid][j].need[k].lv = atoi(split[3+k*2+minJobLevelPresent+1]); } - hskill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); + homun->skill_tree[classid][j].intimacylv = atoi(split[13+minJobLevelPresent]); return true; } -int read_homunculus_skilldb(void) -{ - memset(hskill_tree,0,sizeof(hskill_tree)); - sv_readdb(db_path, "homun_skill_tree.txt", ',', 13, 15, -1, &read_homunculus_skilldb_sub); +void homunculus_skill_db_read(void) { + memset(homun->skill_tree,0,sizeof(homun->skill_tree)); + sv->readdb(db_path, "homun_skill_tree.txt", ',', 13, 15, -1, homun->read_skill_db_sub); - return 0; } -void read_homunculus_expdb(void) -{ +void homunculus_exp_db_read(void) { FILE *fp; char line[1024]; int i, j=0; @@ -1225,60 +1192,105 @@ void read_homunculus_expdb(void) DBPATH"exp_homun.txt", "exp_homun2.txt"}; - memset(hexptbl,0,sizeof(hexptbl)); - for(i=0; i<2; i++){ + memset(homun->exptable,0,sizeof(homun->exptable)); + for(i = 0; i < 2; i++) { sprintf(line, "%s/%s", db_path, filename[i]); - fp=fopen(line,"r"); - if(fp == NULL){ + if( (fp=fopen(line,"r")) == NULL) { if(i != 0) continue; ShowError("can't read %s\n",line); return; } - while(fgets(line, sizeof(line), fp) && j < MAX_LEVEL) - { + while(fgets(line, sizeof(line), fp) && j < MAX_LEVEL) { if(line[0] == '/' && line[1] == '/') continue; - hexptbl[j] = strtoul(line, NULL, 10); - if (!hexptbl[j++]) + if (!(homun->exptable[j++] = strtoul(line, NULL, 10))) break; } - if (hexptbl[MAX_LEVEL - 1]) // Last permitted level have to be 0! - { - ShowWarning("read_hexptbl: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_LEVEL); - hexptbl[MAX_LEVEL - 1] = 0; + // Last permitted level have to be 0! + if (homun->exptable[MAX_LEVEL - 1]) { + ShowWarning("homunculus_exp_db_read: Reached max level in exp_homun [%d]. Remaining lines were not read.\n ", MAX_LEVEL); + homun->exptable[MAX_LEVEL - 1] = 0; } fclose(fp); ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' levels in '"CL_WHITE"%s"CL_RESET"'.\n", j, filename[i]); } } -void merc_reload(void) -{ - read_homunculusdb(); - read_homunculus_expdb(); +void homunculus_reload(void) { + homun->read_db(); + homun->exp_db_read(); } -void merc_skill_reload(void) -{ - read_homunculus_skilldb(); +void homunculus_skill_reload(void) { + homun->skill_db_read(); } -int do_init_merc(void) -{ +void do_init_homunculus(void) { int class_; - read_homunculusdb(); - read_homunculus_expdb(); - read_homunculus_skilldb(); + homun->read_db(); + homun->exp_db_read(); + homun->skill_db_read(); // Add homunc timer function to timer func list [Toms] - add_timer_func_list(merc_hom_hungry, "merc_hom_hungry"); + add_timer_func_list(homun->hunger_timer, "homunculus_hunger_timer"); //Stock view data for homuncs - memset(&hom_viewdb, 0, sizeof(hom_viewdb)); - for (class_ = 0; class_ < ARRAYLENGTH(hom_viewdb); class_++) - hom_viewdb[class_].class_ = HM_CLASS_BASE+class_; - return 0; + memset(&homun->viewdb, 0, sizeof(homun->viewdb)); + for (class_ = 0; class_ < ARRAYLENGTH(homun->viewdb); class_++) + homun->viewdb[class_].class_ = HM_CLASS_BASE+class_; } -int do_final_merc(void); +void do_final_homunculus(void) { + +} + +void homunculus_defaults(void) { + homun = &homunculus_s; + + homun->init = do_init_homunculus; + homun->final = do_final_homunculus; + homun->reload = homunculus_reload; + homun->reload_skill = homunculus_skill_reload; + /* */ + homun->get_viewdata = homunculus_get_viewdata; + homun->class2type = homunculus_class2type; + homun->damaged = homunculus_damaged; + homun->dead = homunculus_dead; + homun->vaporize = homunculus_vaporize; + homun->delete = homunculus_delete; + homun->checkskill = homunculus_checkskill; + homun->calc_skilltree = homunculus_calc_skilltree; + homun->skill_tree_get_max = homunculus_skill_tree_get_max; + homun->skillup = homunculus_skillup; + homun->levelup = homunculus_levelup; + homun->change_class = homunculus_change_class; + homun->evolve = homunculus_evolve; + homun->mutate = homunculus_mutate; + homun->gainexp = homunculus_gainexp; + homun->add_intimacy = homunculus_add_intimacy; + homun->consume_intimacy = homunculus_consume_intimacy; + homun->healed = homunculus_healed; + homun->save = homunculus_save; + homun->menu = homunculus_menu; + homun->feed = homunculus_feed; + homun->hunger_timer = homunculus_hunger_timer; + homun->hunger_timer_delete = homunculus_hunger_timer_delete; + homun->change_name = homunculus_change_name; + homun->change_name_ack = homunculus_change_name_ack; + homun->db_search = homunculus_db_search; + homun->create = homunculus_create; + homun->init_timers = homunculus_init_timers; + homun->call = homunculus_call; + homun->recv_data = homunculus_recv_data; + homun->creation_request = homunculus_creation_request; + homun->ressurect = homunculus_ressurect; + homun->revive = homunculus_revive; + homun->stat_reset = homunculus_stat_reset; + homun->shuffle = homunculus_shuffle; + homun->read_db_sub = homunculus_read_db_sub; + homun->read_db = homunculus_read_db; + homun->read_skill_db_sub = homunculus_read_skill_db_sub; + homun->skill_db_read = homunculus_skill_db_read; + homun->exp_db_read = homunculus_exp_db_read; +} diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 50e82eeac..86d437e73 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -1,11 +1,17 @@ -// 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 _HOMUNCULUS_H_ #define _HOMUNCULUS_H_ #include "status.h" // struct status_data, struct status_change #include "unit.h" // struct unit_data +#include "pc.h" + +#define MAX_HOM_SKILL_REQUIRE 5 +#define homdb_checkid(id) (id >= HM_CLASS_BASE && id <= HM_CLASS_MAX) +#define homun_alive(x) ((x) && (x)->homunculus.vaporize != 1 && (x)->battle_status.hp > 0) struct h_stats { unsigned int HP, SP; @@ -23,9 +29,16 @@ struct s_homunculus_db { }; extern struct s_homunculus_db homunculus_db[MAX_HOMUNCULUS_CLASS]; -enum { HOMUNCULUS_CLASS, HOMUNCULUS_FOOD }; -enum { MH_MD_FIGHTING=1, MH_MD_GRAPPLING }; +enum { + HOMUNCULUS_CLASS, + HOMUNCULUS_FOOD +}; + +enum { + MH_MD_FIGHTING = 1, + MH_MD_GRAPPLING +}; enum { SP_ACK = 0x0, @@ -49,7 +62,6 @@ struct homun_data { char blockskill[MAX_SKILL]; // [orn] }; -#define MAX_HOM_SKILL_REQUIRE 5 struct homun_skill_tree_entry { short id; unsigned char max; @@ -61,72 +73,70 @@ struct homun_skill_tree_entry { } need[MAX_HOM_SKILL_REQUIRE]; }; // Celest -#define HOM_EVO 0x100 //256 -#define HOM_S 0x200 //512 - -#define HOM_REG 0x1000 //4096 - -enum { -// Normal Homunculus - MAPID_LIF = HOM_REG|0x0, - MAPID_AMISTR, - MAPID_FILIR, - MAPID_VANILMIRTH, -// Evolved Homunulus - MAPID_LIF_E = HOM_REG|HOM_EVO|0x0, - MAPID_AMISTR_E, - MAPID_FILIR_E, - MAPID_VANILMIRTH_E, -// Homunculus S - MAPID_EIRA = HOM_S|0x0, - MAPID_BAYERI, - MAPID_SERA, - MAPID_DIETER, - MAPID_ELANOR, +enum homun_type { + HT_REG = 0x1, + HT_EVO = 0x2, + HT_S = 0x4, }; -#define homdb_checkid(id) (id >= HM_CLASS_BASE && id <= HM_CLASS_MAX) - -// merc_is_hom_alive(struct homun_data *) -#define merc_is_hom_active(x) (x && x->homunculus.vaporize != 1 && x->battle_status.hp > 0) -int do_init_merc(void); -int merc_hom_recv_data(int account_id, struct s_homunculus *sh, int flag); //albator -struct view_data* merc_get_hom_viewdata(int class_); -int hom_class2mapid(int hom_class); -void merc_damage(struct homun_data *hd); -int merc_hom_dead(struct homun_data *hd); -void merc_hom_skillup(struct homun_data *hd,uint16 skill_id); -int merc_hom_calc_skilltree(struct homun_data *hd, int flag_evolve); -int merc_hom_checkskill(struct homun_data *hd,uint16 skill_id); -int merc_hom_gainexp(struct homun_data *hd,int exp); -int merc_hom_levelup(struct homun_data *hd); -int merc_hom_evolution(struct homun_data *hd); -int hom_mutate(struct homun_data *hd,int homun_id); -void merc_hom_heal(struct homun_data *hd); -int merc_hom_vaporize(struct map_session_data *sd, int flag); -int merc_resurrect_homunculus(struct map_session_data *sd, unsigned char per, short x, short y); -void merc_hom_revive(struct homun_data *hd, unsigned int hp, unsigned int sp); -void merc_reset_stats(struct homun_data *hd); -int merc_hom_shuffle(struct homun_data *hd); // [Zephyrus] -void merc_save(struct homun_data *hd); -int merc_call_homunculus(struct map_session_data *sd); -int merc_create_homunculus_request(struct map_session_data *sd, int class_); -int search_homunculusDB_index(int key,int type); -int merc_menu(struct map_session_data *sd,int menunum); -int merc_hom_food(struct map_session_data *sd, struct homun_data *hd); -int merc_hom_hungry_timer_delete(struct homun_data *hd); -int merc_hom_change_name(struct map_session_data *sd,char *name); -int merc_hom_change_name_ack(struct map_session_data *sd, char* name, int flag); -#define merc_stop_walking(hd, type) unit_stop_walking(&(hd)->bl, type) -#define merc_stop_attack(hd) unit_stop_attack(&(hd)->bl) -int merc_hom_increase_intimacy(struct homun_data * hd, unsigned int value); -int merc_hom_decrease_intimacy(struct homun_data * hd, unsigned int value); -int merc_skill_tree_get_max(int id, int b_class); -void merc_hom_init_timers(struct homun_data * hd); -void merc_skill_reload(void); -void merc_reload(void); - -int hom_addspiritball(TBL_HOM *hd, int max); -int hom_delspiritball(TBL_HOM *hd, int count, int type); +/* homunculus.c interface */ +struct homunculus_interface { + unsigned int exptable[MAX_LEVEL]; + struct view_data viewdb[MAX_HOMUNCULUS_CLASS]; + struct s_homunculus_db db[MAX_HOMUNCULUS_CLASS]; + struct homun_skill_tree_entry skill_tree[MAX_HOMUNCULUS_CLASS][MAX_SKILL_TREE]; + /* */ + void (*init) (void); + void (*final) (void); + void (*reload) (void); + void (*reload_skill) (void); + /* */ + struct view_data* (*get_viewdata) (int class_); + enum homun_type (*class2type) (int class_); + void (*damaged) (struct homun_data *hd); + int (*dead) (struct homun_data *hd); + int (*vaporize) (struct map_session_data *sd, int flag); + int (*delete) (struct homun_data *hd, int emote); + int (*checkskill) (struct homun_data *hd, uint16 skill_id); + int (*calc_skilltree) (struct homun_data *hd, int flag_evolve); + int (*skill_tree_get_max) (int id, int b_class); + void (*skillup) (struct homun_data *hd, uint16 skill_id); + bool (*levelup) (struct homun_data *hd); + int (*change_class) (struct homun_data *hd, short class_); + bool (*evolve) (struct homun_data *hd); + bool (*mutate) (struct homun_data *hd, int homun_id); + int (*gainexp) (struct homun_data *hd, unsigned int exp); + unsigned int (*add_intimacy) (struct homun_data * hd, unsigned int value); + unsigned int (*consume_intimacy) (struct homun_data *hd, unsigned int value); + void (*healed) (struct homun_data *hd); + void (*save) (struct homun_data *hd); + unsigned char (*menu) (struct map_session_data *sd,unsigned char menu_num); + bool (*feed) (struct map_session_data *sd, struct homun_data *hd); + int (*hunger_timer) (int tid, unsigned int tick, int id, intptr_t data); + void (*hunger_timer_delete) (struct homun_data *hd); + int (*change_name) (struct map_session_data *sd,char *name); + bool (*change_name_ack) (struct map_session_data *sd, char* name, int flag); + int (*db_search) (int key,int type); + bool (*create) (struct map_session_data *sd, struct s_homunculus *hom); + void (*init_timers) (struct homun_data * hd); + bool (*call) (struct map_session_data *sd); + bool (*recv_data) (int account_id, struct s_homunculus *sh, int flag); + bool (*creation_request) (struct map_session_data *sd, int class_); + bool (*ressurect) (struct map_session_data* sd, unsigned char per, short x, short y); + void (*revive) (struct homun_data *hd, unsigned int hp, unsigned int sp); + void (*stat_reset) (struct homun_data *hd); + bool (*shuffle) (struct homun_data *hd); + bool (*read_db_sub) (char* str[], int columns, int current); + void (*read_db) (void); + bool (*read_skill_db_sub) (char* split[], int columns, int current); + void (*skill_db_read) (void); + void (*exp_db_read) (void); + void (*addspiritball) (struct homun_data *hd, int max); + void (*delspiritball) (struct homun_data *hd, int count, int type); +} homunculus_s; + +struct homunculus_interface *homun; + +void homunculus_defaults(void); #endif /* _HOMUNCULUS_H_ */ diff --git a/src/map/instance.c b/src/map/instance.c index 44a208866..8ddde8b3e 100644 --- a/src/map/instance.c +++ b/src/map/instance.c @@ -88,7 +88,7 @@ int instance_create(int party_id, const char *name) memset( instance[i].map, 0x00, sizeof(instance[i].map) ); p->instance_id = i; - clif_instance(i, 1, 0); // Start instancing window + clif->instance(i, 1, 0); // Start instancing window ShowInfo("[Instance] Created: %s.\n", name); return i; } @@ -275,7 +275,7 @@ int instance_cleanup_sub(struct block_list *bl, va_list ap) { map_clearflooritem(bl); break; case BL_SKILL: - skill_delunit((struct skill_unit *) bl); + skill->delunit((struct skill_unit *) bl); break; } @@ -357,7 +357,7 @@ void instance_destroy(int instance_id) else type = 3; - clif_instance(instance_id, 5, type); // Report users this instance has been destroyed + clif->instance(instance_id, 5, type); // Report users this instance has been destroyed while( instance[instance_id].num_map && last != instance[instance_id].map[0] ) { // Remove all maps from instance @@ -403,13 +403,13 @@ void instance_check_idle(int instance_id) delete_timer(instance[instance_id].idle_timer, instance_destroy_timer); instance[instance_id].idle_timer = INVALID_TIMER; instance[instance_id].idle_timeout = 0; - clif_instance(instance_id, 3, 0); // Notify instance users normal instance expiration + clif->instance(instance_id, 3, 0); // Notify instance users normal instance expiration } else if( instance[instance_id].idle_timer == INVALID_TIMER && idle ) { instance[instance_id].idle_timeout = now + instance[instance_id].idle_timeoutval; instance[instance_id].idle_timer = add_timer( gettick() + (unsigned int)instance[instance_id].idle_timeoutval * 1000, instance_destroy_timer, instance_id, 0); - clif_instance(instance_id, 4, 0); // Notify instance users it will be destroyed of no user join it again in "X" time + clif->instance(instance_id, 4, 0); // Notify instance users it will be destroyed of no user join it again in "X" time } } @@ -453,7 +453,7 @@ void instance_set_timeout(int instance_id, unsigned int progress_timeout, unsign } if( instance[instance_id].idle_timer == INVALID_TIMER && instance[instance_id].progress_timer != INVALID_TIMER ) - clif_instance(instance_id, 3, 0); + clif->instance(instance_id, 3, 0); } /*-------------------------------------- @@ -463,7 +463,7 @@ void instance_check_kick(struct map_session_data *sd) { int16 m = sd->bl.m; - clif_instance_leave(sd->fd); + clif->instance_leave(sd->fd); if( map[m].instance_id ) { // User was on the instance map if( map[m].save.map ) diff --git a/src/map/intif.c b/src/map/intif.c index 9391e0275..93bb8add7 100644 --- a/src/map/intif.c +++ b/src/map/intif.c @@ -142,7 +142,7 @@ int intif_broadcast(const char* mes, int len, int type) int lp = type ? 4 : 0; // Send to the local players - clif_broadcast(NULL, mes, len, type, ALL_CLIENT); + clif->broadcast(NULL, mes, len, type, ALL_CLIENT); if (CheckForCharServer()) return 0; @@ -170,10 +170,7 @@ int intif_broadcast(const char* mes, int len, int type) int intif_broadcast2(const char* mes, int len, unsigned long fontColor, short fontType, short fontSize, short fontAlign, short fontY) { // Send to the local players - if (fontColor == 0xFE000000) // This is main chat message [LuzZza] - clif_MainChatMessage(mes); - else - clif_broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); + clif->broadcast2(NULL, mes, len, fontColor, fontType, fontSize, fontAlign, fontY, ALL_CLIENT); if (CheckForCharServer()) return 0; @@ -210,7 +207,7 @@ int intif_main_message(struct map_session_data* sd, const char* message) intif_broadcast2( output, strlen(output) + 1, 0xFE000000, 0, 0, 0, 0 ); // log the chat message - log_chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message ); + logs->chat( LOG_CHAT_MAINCHAT, 0, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, message ); return 0; } @@ -224,7 +221,7 @@ int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, int me if (other_mapserver_count < 1) { //Character not found. - clif_wis_end(sd->fd, 1); + clif->wis_end(sd->fd, 1); return 0; } @@ -813,16 +810,15 @@ int intif_homunculus_create(int account_id, struct s_homunculus *sh) return 0; } -int intif_homunculus_requestload(int account_id, int homun_id) -{ +bool intif_homunculus_requestload(int account_id, int homun_id) { if (CheckForCharServer()) - return 0; + return false; WFIFOHEAD(inter_fd, 10); WFIFOW(inter_fd,0) = 0x3091; WFIFOL(inter_fd,2) = account_id; WFIFOL(inter_fd,6) = homun_id; WFIFOSET(inter_fd, 10); - return 1; + return true; } int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh) @@ -888,7 +884,7 @@ int intif_parse_WisMessage(int fd) return 0; } //Success to send whisper. - clif_wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); + clif->wis_message(sd->fd, wisp_source, (char*)RFIFOP(fd,56),RFIFOW(fd,2)-56); intif_wis_replay(id,0); // succes return 0; } @@ -902,7 +898,7 @@ int intif_parse_WisEnd(int fd) ShowInfo("intif_parse_wisend: player: %s, flag: %d\n", RFIFOP(fd,2), RFIFOB(fd,26)); // flag: 0: success to send wisper, 1: target character is not loged in?, 2: ignored by target sd = (struct map_session_data *)map_nick2sd((char *) RFIFOP(fd,2)); if (sd != NULL) - clif_wis_end(sd->fd, RFIFOB(fd,26)); + clif->wis_end(sd->fd, RFIFOB(fd,26)); return 0; } @@ -919,7 +915,7 @@ static int mapif_parse_WisToGM_sub(struct map_session_data* sd,va_list va) wisp_name = va_arg(va, char*); message = va_arg(va, char*); len = va_arg(va, int); - clif_wis_message(sd->fd, wisp_name, message, len); + clif->wis_message(sd->fd, wisp_name, message, len); return 1; } @@ -1119,7 +1115,7 @@ int intif_parse_PartyMessage(int fd) // ACK guild creation int intif_parse_GuildCreated(int fd) { - guild_created(RFIFOL(fd,2),RFIFOL(fd,6)); + guild->created(RFIFOL(fd,2),RFIFOL(fd,6)); return 0; } @@ -1128,12 +1124,12 @@ int intif_parse_GuildInfo(int fd) { if(RFIFOW(fd,2) == 8) { ShowWarning("intif: guild noinfo %d\n",RFIFOL(fd,4)); - guild_recv_noinfo(RFIFOL(fd,4)); + guild->recv_noinfo(RFIFOL(fd,4)); return 0; } if( RFIFOW(fd,2)!=sizeof(struct guild)+4 ) ShowError("intif: guild info : data size error Gid: %d recv size: %d Expected size: %d\n",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild)+4); - guild_recv_info((struct guild *)RFIFOP(fd,4)); + guild->recv_info((struct guild *)RFIFOP(fd,4)); return 0; } @@ -1142,28 +1138,28 @@ int intif_parse_GuildMemberAdded(int fd) { if(battle_config.etc_log) ShowInfo("intif: guild member added %d %d %d %d\n",RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); - guild_member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); + guild->member_added(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14)); return 0; } // ACK member leaving guild int intif_parse_GuildMemberWithdraw(int fd) { - guild_member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); + guild->member_withdraw(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),(char *)RFIFOP(fd,55),(char *)RFIFOP(fd,15)); return 0; } // ACK guild member basic info int intif_parse_GuildMemberInfoShort(int fd) { - guild_recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); + guild->recv_memberinfoshort(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOB(fd,14),RFIFOW(fd,15),RFIFOW(fd,17)); return 0; } // ACK guild break int intif_parse_GuildBroken(int fd) { - guild_broken(RFIFOL(fd,2),RFIFOB(fd,6)); + guild->broken(RFIFOL(fd,2),RFIFOB(fd,6)); return 0; } @@ -1176,7 +1172,7 @@ int intif_parse_GuildBasicInfoChanged(int fd) int type = RFIFOW(fd,8); //void* data = RFIFOP(fd,10); - struct guild* g = guild_search(guild_id); + struct guild* g = guild->search(guild_id); if( g == NULL ) return 0; @@ -1203,16 +1199,16 @@ int intif_parse_GuildMemberInfoChanged(int fd) struct guild* g; int idx; - g = guild_search(guild_id); + g = guild->search(guild_id); if( g == NULL ) return 0; - idx = guild_getindex(g,account_id,char_id); + idx = guild->getindex(g,account_id,char_id); if( idx == -1 ) return 0; switch( type ) { - case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild_memberposition_changed(g,idx,RFIFOW(fd,18)); break; + case GMI_POSITION: g->member[idx].position = RFIFOW(fd,18); guild->memberposition_changed(g,idx,RFIFOW(fd,18)); break; case GMI_EXP: g->member[idx].exp = RFIFOQ(fd,18); break; case GMI_HAIR: g->member[idx].hair = RFIFOW(fd,18); break; case GMI_HAIR_COLOR: g->member[idx].hair_color = RFIFOW(fd,18); break; @@ -1228,55 +1224,55 @@ int intif_parse_GuildPosition(int fd) { if( RFIFOW(fd,2)!=sizeof(struct guild_position)+12 ) ShowError("intif: guild info : data size error\n %d %d %d",RFIFOL(fd,4),RFIFOW(fd,2),sizeof(struct guild_position)+12); - guild_position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); + guild->position_changed(RFIFOL(fd,4),RFIFOL(fd,8),(struct guild_position *)RFIFOP(fd,12)); return 0; } // ACK change of guild skill update int intif_parse_GuildSkillUp(int fd) { - guild_skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + guild->skillupack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); return 0; } // ACK change of guild relationship int intif_parse_GuildAlliance(int fd) { - guild_allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); + guild->allianceack(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10),RFIFOL(fd,14),RFIFOB(fd,18),(char *) RFIFOP(fd,19),(char *) RFIFOP(fd,43)); return 0; } // ACK change of guild notice int intif_parse_GuildNotice(int fd) { - guild_notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); + guild->notice_changed(RFIFOL(fd,2),(char *) RFIFOP(fd,6),(char *) RFIFOP(fd,66)); return 0; } // ACK change of guild emblem int intif_parse_GuildEmblem(int fd) { - guild_emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); + guild->emblem_changed(RFIFOW(fd,2)-12,RFIFOL(fd,4),RFIFOL(fd,8), (char *)RFIFOP(fd,12)); return 0; } // ACK guild message int intif_parse_GuildMessage(int fd) { - guild_recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); + guild->recv_message(RFIFOL(fd,4),RFIFOL(fd,8),(char *) RFIFOP(fd,12),RFIFOW(fd,2)-12); return 0; } // Reply guild castle data request int intif_parse_GuildCastleDataLoad(int fd) { - return guild_castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); + return guild->castledataloadack(RFIFOW(fd,2), (struct guild_castle *)RFIFOP(fd,4)); } // ACK change of guildmaster int intif_parse_GuildMasterChanged(int fd) { - return guild_gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); + return guild->gm_changed(RFIFOL(fd,2),RFIFOL(fd,6),RFIFOL(fd,10)); } // Request pet creation @@ -1337,7 +1333,7 @@ int intif_parse_ChangeNameOk(int fd) pet_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); break; case 2: //Hom - merc_hom_change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); + homun->change_name_ack(sd, (char*)RFIFOP(fd,12), RFIFOB(fd,11)); break; } return 0; @@ -1355,7 +1351,7 @@ int intif_parse_CreateHomunculus(int fd) ShowError("intif: create homun data: data size error %d != %d\n",sizeof(struct s_homunculus),len); return 0; } - merc_hom_recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; + homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)) ; return 0; } @@ -1370,7 +1366,7 @@ int intif_parse_RecvHomunculusData(int fd) ShowError("intif: homun data: data size error %d %d\n",sizeof(struct s_homunculus),len); return 0; } - merc_hom_recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); + homun->recv_data(RFIFOL(fd,4), (struct s_homunculus*)RFIFOP(fd,9), RFIFOB(fd,8)); return 0; } @@ -1523,12 +1519,12 @@ int intif_parse_Mail_inboxreceived(int fd) sd->mail.changed = false; // cache is now in sync if (flag) - clif_Mail_refreshinbox(sd); + clif->mail_refreshinbox(sd); else if( battle_config.mail_show_status && ( battle_config.mail_show_status == 1 || sd->mail.inbox.unread ) ) { char output[128]; sprintf(output, msg_txt(510), sd->mail.inbox.unchecked, sd->mail.inbox.unread + sd->mail.inbox.unchecked); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } return 0; } @@ -1633,7 +1629,7 @@ int intif_parse_Mail_delete(int fd) intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails } - clif_Mail_delete(sd->fd, mail_id, failed); + clif->mail_delete(sd->fd, mail_id, failed); return 0; } /*------------------------------------------ @@ -1679,7 +1675,7 @@ int intif_parse_Mail_return(int fd) intif_Mail_requestinbox(sd->status.char_id, 1); // Free space is available for new mails } - clif_Mail_return(sd->fd, mail_id, fail); + clif->mail_return(sd->fd, mail_id, fail); return 0; } /*------------------------------------------ @@ -1725,7 +1721,7 @@ static void intif_parse_Mail_send(int fd) mail_deliveryfail(sd, &msg); else { - clif_Mail_send(sd->fd, false); + clif->mail_send(sd->fd, false); if( save_settings&16 ) chrif_save(sd, 0); } @@ -1743,7 +1739,7 @@ static void intif_parse_Mail_new(int fd) return; sd->mail.changed = true; - clif_Mail_new(sd->fd, mail_id, sender_name, title); + clif->mail_new(sd->fd, mail_id, sender_name, title); } /*========================================== @@ -1780,7 +1776,7 @@ static void intif_parse_Auction_results(int fd) if( sd == NULL ) return; - clif_Auction_results(sd, count, pages, data); + clif->auction_results(sd, count, pages, data); } int intif_Auction_register(struct auction_data *auction) @@ -1816,7 +1812,7 @@ static void intif_parse_Auction_register(int fd) if( auction.auction_id > 0 ) { - clif_Auction_message(sd->fd, 1); // Confirmation Packet ?? + clif->auction_message(sd->fd, 1); // Confirmation Packet ?? if( save_settings&32 ) chrif_save(sd,0); } @@ -1824,7 +1820,7 @@ static void intif_parse_Auction_register(int fd) { int zeny = auction.hours*battle_config.auction_feeperhour; - clif_Auction_message(sd->fd, 4); + clif->auction_message(sd->fd, 4); pc_additem(sd, &auction.item, auction.item.amount, LOG_TYPE_AUCTION); pc_getzeny(sd, zeny, LOG_TYPE_AUCTION, NULL); @@ -1855,10 +1851,10 @@ static void intif_parse_Auction_cancel(int fd) switch( result ) { - case 0: clif_Auction_message(sd->fd, 2); break; - case 1: clif_Auction_close(sd->fd, 2); break; - case 2: clif_Auction_close(sd->fd, 1); break; - case 3: clif_Auction_message(sd->fd, 3); break; + case 0: clif->auction_message(sd->fd, 2); break; + case 1: clif->auction_close(sd->fd, 2); break; + case 2: clif->auction_close(sd->fd, 1); break; + case 3: clif->auction_message(sd->fd, 3); break; } } @@ -1884,11 +1880,11 @@ static void intif_parse_Auction_close(int fd) if( sd == NULL ) return; - clif_Auction_close(sd->fd, result); + clif->auction_close(sd->fd, result); if( result == 0 ) { // FIXME: Leeching off a parse function - clif_parse_Auction_cancelreg(fd, sd); + clif->pAuction_cancelreg(fd, sd); intif_Auction_requestlist(sd->status.char_id, 6, 0, "", 1); } } @@ -1921,14 +1917,12 @@ static void intif_parse_Auction_bid(int fd) if( sd == NULL ) return; - clif_Auction_message(sd->fd, result); - if( bid > 0 ) - { + clif->auction_message(sd->fd, result); + if( bid > 0 ) { pc_getzeny(sd, bid, LOG_TYPE_AUCTION,NULL); } - if( result == 1 ) - { // To update the list, display your buy list - clif_parse_Auction_cancelreg(fd, sd); + if( result == 1 ) { // To update the list, display your buy list + clif->pAuction_cancelreg(fd, sd); intif_Auction_requestlist(sd->status.char_id, 7, 0, "", 1); } } @@ -1942,7 +1936,7 @@ static void intif_parse_Auction_message(int fd) if( sd == NULL ) return; - clif_Auction_message(sd->fd, result); + clif->auction_message(sd->fd, result); } /*========================================== @@ -2121,7 +2115,7 @@ int intif_parse_elemental_saved(int fd) return 0; } -void intif_request_accinfo( int u_fd, int aid, int group_id, char* query ) { +void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) { WFIFOHEAD(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); @@ -2129,7 +2123,7 @@ void intif_request_accinfo( int u_fd, int aid, int group_id, char* query ) { WFIFOW(inter_fd,0) = 0x3007; WFIFOL(inter_fd,2) = u_fd; WFIFOL(inter_fd,6) = aid; - WFIFOL(inter_fd,10) = group_id; + WFIFOL(inter_fd,10) = group_lv; safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH); WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH); @@ -2147,7 +2141,7 @@ void intif_parse_MessageToFD(int fd) { if( sd->bl.id == aid ) { char msg[512]; safestrncpy(msg, (char*)RFIFOP(fd,12), RFIFOW(fd,2) - 12); - clif_displaymessage(u_fd,msg); + clif->message(u_fd,msg); } } @@ -2182,11 +2176,9 @@ int intif_parse(int fd) switch(cmd){ case 0x3800: if (RFIFOL(fd,4) == 0xFF000000) //Normal announce. - clif_broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); - else if (RFIFOL(fd,4) == 0xFE000000) //Main chat message [LuzZza] - clif_MainChatMessage((char *)RFIFOP(fd,16)); + clif->broadcast(NULL, (char *) RFIFOP(fd,16), packet_len-16, 0, ALL_CLIENT); else //Color announce. - clif_broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); + clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT); break; case 0x3801: intif_parse_WisMessage(fd); break; case 0x3802: intif_parse_WisEnd(fd); break; diff --git a/src/map/intif.h b/src/map/intif.h index 65cc19830..43bbc0859 100644 --- a/src/map/intif.h +++ b/src/map/intif.h @@ -71,7 +71,7 @@ int intif_rename(struct map_session_data *sd, int type, char *name); #define intif_rename_pet(sd, name) intif_rename(sd, 1, name) #define intif_rename_hom(sd, name) intif_rename(sd, 2, name) int intif_homunculus_create(int account_id, struct s_homunculus *sh); -int intif_homunculus_requestload(int account_id, int homun_id); +bool intif_homunculus_requestload(int account_id, int homun_id); int intif_homunculus_requestsave(int account_id, struct s_homunculus* sh); int intif_homunculus_requestdelete(int homun_id); @@ -105,7 +105,7 @@ int intif_elemental_delete(int ele_id); int intif_elemental_save(struct s_elemental *ele); /* @accinfo */ -void intif_request_accinfo( int u_fd, int aid, int group_id, char* query ); +void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ); int CheckForCharServer(void); diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c new file mode 100644 index 000000000..0e155011e --- /dev/null +++ b/src/map/irc-bot.c @@ -0,0 +1,288 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Base Author: shennetsind @ http://hercules.ws + +#include "../common/cbasetypes.h" +#include "../common/malloc.h" +#include "../common/strlib.h" +#include "../common/showmsg.h" +#include "../common/socket.h" +#include "../common/timer.h" +#include "../common/random.h" + +#include "map.h" +#include "pc.h" +#include "clif.h" +#include "irc-bot.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +char send_string[200]; + +int irc_connect_timer(int tid, unsigned int tick, int id, intptr_t data) { + if( ircbot->isOn || ++ircbot->fails >= 3 ) + return 0; + + ircbot->last_try = gettick(); + + if( ( ircbot->fd = make_connection(ircbot->ip,hChSys.irc_server_port,true) ) > 0 ){ + session[ircbot->fd]->func_parse = ircbot->parse; + session[ircbot->fd]->flag.server = 1; + add_timer(gettick() + 3000, ircbot->identify_timer, 0, 0); + ircbot->isOn = true; + } + return 0; +} + +int irc_identify_timer(int tid, unsigned int tick, int id, intptr_t data) { + if( !ircbot->isOn ) + return 0; + + sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rand()%777); + ircbot->send(send_string); + sprintf(send_string, "NICK %s", hChSys.irc_nick); + ircbot->send(send_string); + + add_timer(gettick() + 3000, ircbot->join_timer, 0, 0); + + return 0; +} + +int irc_join_timer(int tid, unsigned int tick, int id, intptr_t data) { + if( !ircbot->isOn ) + return 0; + + if( hChSys.irc_nick_pw[0] != '\0' ) { + sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", hChSys.irc_nick_pw); + ircbot->send(send_string); + } + + sprintf(send_string, "JOIN %s", hChSys.irc_channel); + ircbot->send(send_string); + ircbot->isIn = true; + + return 0; +} + +struct irc_func* irc_func_search(char* function_name) { + int i; + for(i = 0; i < ircbot->funcs.size; i++) { + if( strcmpi(ircbot->funcs.list[i]->name, function_name) == 0 ) { + return ircbot->funcs.list[i]; + } + } + return NULL; +} + +int irc_parse(int fd) { + char *parse_string = NULL, *str_safe = NULL; + + if (session[fd]->flag.eof) { + do_close(fd); + ircbot->fd = 0; + ircbot->isOn = false; + ircbot->isIn = false; + ircbot->fails = 0; + ircbot->ip = host2ip(hChSys.irc_server); + add_timer(gettick() + 120000, ircbot->connect_timer, 0, 0); + return 0; + } + + if( !RFIFOREST(fd) ) + return 0; + + parse_string = (char*)RFIFOP(fd,0); + parse_string[ RFIFOREST(fd) - 1 ] = '\0'; + + parse_string = strtok_r(parse_string,"\r\n",&str_safe); + + while (parse_string != NULL) { + ircbot->parse_sub(fd,parse_string); + parse_string = strtok_r(NULL,"\r\n",&str_safe); + } + + RFIFOSKIP(fd, RFIFOREST(fd)); + RFIFOFLUSH(fd); + return 0; +} + +void irc_parse_source(char *source, char *nick, char *ident, char *host) { + int i, len = strlen(source), pos = 0; + unsigned char stage = 0; + + for(i = 0; i < len; i++) { + if( stage == 0 && source[i] == '!' ) { + memcpy(nick, &source[0], len - i); + nick[i] = '\0'; + pos = i+1; + stage = 1; + } else if( stage == 1 && source[i] == '@' ) { + memcpy(ident, &source[pos], i - pos); + ident[i-pos] = '\0'; + memcpy(host, &source[i+1], len); + host[len] = '\0'; + break; + } + } +} +void irc_parse_sub(int fd, char *str) { + char source[180], command[60], target[60], message[200]; + struct irc_func *func; + + source[0] = command[0] = target[0] = message[0] = '\0'; + + if( str[0] == ':' ) + str++; + + sscanf(str, "%179s %59s %59s :%199[^\r\n]", source, command, target, message); + + if( command[0] == '\0' ) + return; + + if( !(func = ircbot->func_search(command)) && !(func = ircbot->func_search(source)) ) { + //ShowWarning("Unknown command received %s from %s\n",command,source); + return; + } + func->func(fd,command,source,target,message); + +} + +void irc_send(char *str) { + int len = strlen(str) + 2; + WFIFOHEAD(ircbot->fd, len); + snprintf((char*)WFIFOP(ircbot->fd,0),200, "%s\r\n", str); + WFIFOSET(ircbot->fd, len); +} + +void irc_pong(int fd, char *cmd, char *source, char *target, char *msg) { + sprintf(send_string, "PONG %s", cmd); + ircbot->send(send_string); +} + +void irc_join(int fd, char *cmd, char *source, char *target, char *msg) { + if( ircbot->isIn ) + return; + sprintf(send_string, "JOIN %s", hChSys.irc_channel); + ircbot->send(send_string); + ircbot->isIn = true; +} + +void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) { + if( strcmpi(target,hChSys.irc_nick) == 0 ) { + if( msg[0] == ':' ) msg++; + if( strcmpi(msg,"VERSION") == 0 ) { + char source_nick[40], source_ident[40], source_host[100]; + + source_nick[0] = source_ident[0] = source_host[0] = '\0'; + + if( source[0] != '\0' ) + ircbot->parse_source(source,source_nick,source_ident,source_host); + + sprintf(send_string, "NOTICE %s :Hercules.ws IRC Bridge",source_nick); + ircbot->send(send_string); + return; + } + } else if( strcmpi(target,hChSys.irc_channel) == 0 ) { + char source_nick[40], source_ident[40], source_host[100]; + + source_nick[0] = source_ident[0] = source_host[0] = '\0'; + + if( source[0] != '\0' ) + ircbot->parse_source(source,source_nick,source_ident,source_host); + + if( ircbot->channel ) { + snprintf(send_string, 150, "[ #%s ] IRC.%s : %s",ircbot->channel->name,source_nick,msg); + clif->chsys_msg2(ircbot->channel,send_string); + } + } +} + +void irc_relay (char *name, char *msg) { + if( !ircbot->isIn ) + return; + sprintf(send_string,"PRIVMSG %s :[ %s ] : %s",hChSys.irc_channel,name,msg); + ircbot->send(send_string); +} +void irc_bot_init(void) { + const struct irc_func irc_func_base[] = { + { "PING" , ircbot->pong }, + { "PRIVMSG", ircbot->privmsg }, + }; + struct irc_func* function; + int i; + + if( !hChSys.irc ) + return; + + if (!(ircbot->ip = host2ip(hChSys.irc_server))) { + ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", hChSys.irc_server); + hChSys.irc = false; + return; + } + + ircbot->funcs.size = ARRAYLENGTH(irc_func_base); + + CREATE(ircbot->funcs.list,struct irc_func*,ircbot->funcs.size); + + for( i = 0; i < ircbot->funcs.size; i++ ) { + + CREATE(function, struct irc_func, 1); + + safestrncpy(function->name, irc_func_base[i].name, sizeof(function->name)); + function->func = irc_func_base[i].func; + + ircbot->funcs.list[i] = function; + } + + ircbot->fails = 0; + ircbot->fd = 0; + ircbot->isIn = false; + ircbot->isOn = false; + + add_timer_func_list(ircbot->connect_timer, "irc_connect_timer"); + add_timer(gettick() + 7000, ircbot->connect_timer, 0, 0); +} + +void irc_bot_final(void) { + int i; + + if( !hChSys.irc ) + return; + if( ircbot->isOn ) { + ircbot->send("QUIT :Hercules is shutting down"); + do_close(ircbot->fd); + } + + for( i = 0; i < ircbot->funcs.size; i++ ) { + aFree(ircbot->funcs.list[i]); + } + aFree(ircbot->funcs.list); +} + +void ircbot_defaults(void) { + ircbot = &irc_bot_s; + + ircbot->channel = NULL; + + ircbot->init = irc_bot_init; + ircbot->final = irc_bot_final; + + ircbot->parse = irc_parse; + ircbot->parse_sub = irc_parse_sub; + ircbot->parse_source = irc_parse_source; + + ircbot->func_search = irc_func_search; + + ircbot->connect_timer = irc_connect_timer; + ircbot->identify_timer = irc_identify_timer; + ircbot->join_timer = irc_join_timer; + + ircbot->send = irc_send; + ircbot->relay = irc_relay; + + ircbot->pong = irc_pong; + ircbot->join = irc_join; + ircbot->privmsg = irc_privmsg; +} diff --git a/src/map/irc-bot.h b/src/map/irc-bot.h new file mode 100644 index 000000000..f4244e024 --- /dev/null +++ b/src/map/irc-bot.h @@ -0,0 +1,58 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Base Author: shennetsind @ http://hercules.ws + + +#ifndef _IRC_BOT_H_ +#define _IRC_BOT_H_ + +#define IRC_FUNC_LENGTH 30 + +struct hChSysCh; + +struct irc_func { + char name[IRC_FUNC_LENGTH]; + void (*func)(int, char*, char*, char*, char*); +}; + +struct irc_bot_interface { + int fd; + bool isIn, isOn; + unsigned int last_try; + unsigned char fails; + unsigned long ip; + unsigned short port; + /* */ + struct hChSysCh *channel; + /* */ + struct { + struct irc_func **list; + unsigned int size; + } funcs; + /* */ + void (*init) (void); + void (*final) (void); + /* */ + int (*parse) (int fd); + void (*parse_sub) (int fd, char *str); + void (*parse_source) (char *source, char *nick, char *ident, char *host); + /* */ + struct irc_func* (*func_search) (char* function_name); + /* */ + int (*connect_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*identify_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*join_timer) (int tid, unsigned int tick, int id, intptr_t data); + /* */ + void (*send)(char *str); + void (*relay) (char *name, char *msg); + /* */ + void (*pong) (int fd, char *cmd, char *source, char *target, char *msg); + void (*join) (int fd, char *cmd, char *source, char *target, char *msg); + void (*privmsg) (int fd, char *cmd, char *source, char *target, char *msg); +} irc_bot_s; + +struct irc_bot_interface *ircbot; + +void ircbot_defaults(void); + +#endif /* _IRC_BOT_H_ */ diff --git a/src/map/itemdb.c b/src/map/itemdb.c index 68baae1e1..2a5fa48de 100644 --- a/src/map/itemdb.c +++ b/src/map/itemdb.c @@ -1,5 +1,6 @@ -// 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 #include "../common/nullpo.h" #include "../common/malloc.h" @@ -20,8 +21,6 @@ static struct item_data* itemdb_array[MAX_ITEMDB]; static DBMap* itemdb_other;// int nameid -> struct item_data* -static struct item_group itemgroup_db[MAX_ITEMGROUP]; - struct item_data dummy_item; //This is the default dummy item used for non-existant items. [Skotlex] /** @@ -31,7 +30,7 @@ struct item_data dummy_item; //This is the default dummy item used for non-exist */ static int itemdb_searchname_sub(DBKey key, DBData *data, va_list ap) { - struct item_data *item = db_data2ptr(data), **dst, **dst2; + struct item_data *item = DB->data2ptr(data), **dst, **dst2; char *str; str=va_arg(ap,char *); dst=va_arg(ap,struct item_data **); @@ -84,7 +83,7 @@ struct item_data* itemdb_searchname(const char *str) */ static int itemdb_searchname_array_sub(DBKey key, DBData data, va_list ap) { - struct item_data *item = db_data2ptr(&data); + struct item_data *item = DB->data2ptr(&data); char *str; str=va_arg(ap,char *); if (item == &dummy_item) @@ -128,7 +127,7 @@ int itemdb_searchname_array(struct item_data** data, int size, const char *str) size -= count; db_count = itemdb_other->getall(itemdb_other, (DBData**)&db_data, size, itemdb_searchname_array_sub, str); for (i = 0; i < db_count; i++) - data[count++] = db_data2ptr(db_data[i]); + data[count++] = DB->data2ptr(db_data[i]); count += db_count; } return count; @@ -466,8 +465,7 @@ int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(stru /*========================================== * Specifies if item-type should drop unidentified. *------------------------------------------*/ -int itemdb_isidentified(int nameid) -{ +int itemdb_isidentified(int nameid) { int type=itemdb_type(nameid); switch (type) { case IT_WEAPON: @@ -478,6 +476,18 @@ int itemdb_isidentified(int nameid) return 1; } } +/* same as itemdb_isidentified but without a lookup */ +int itemdb_isidentified2(struct item_data *data) { + switch (data->type) { + case IT_WEAPON: + case IT_ARMOR: + case IT_PETARMOR: + return 0; + default: + return 1; + } +} + /*========================================== * Search by name for the override flags available items @@ -514,18 +524,18 @@ static bool itemdb_read_itemavail(char* str[], int columns, int current) /*========================================== * read item group data *------------------------------------------*/ -static void itemdb_read_itemgroup_sub(const char* filename) -{ +static unsigned int itemdb_read_itemgroup_sub(const char* filename) { FILE *fp; char line[1024]; int ln=0; + unsigned int count = 0; int groupid,j,k,nameid; char *str[3],*p; char w1[1024], w2[1024]; if( (fp=fopen(filename,"r"))==NULL ){ ShowError("can't read %s\n", filename); - return; + return 0; } while(fgets(line, sizeof(line), fp)) @@ -536,7 +546,7 @@ static void itemdb_read_itemgroup_sub(const char* filename) if(strstr(line,"import")) { if (sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 && strcmpi(w1, "import") == 0) { - itemdb_read_itemgroup_sub(w2); + count += itemdb_read_itemgroup_sub(w2); continue; } } @@ -570,43 +580,24 @@ static void itemdb_read_itemgroup_sub(const char* filename) } for(j=0;j<k;j++) itemgroup_db[groupid].nameid[itemgroup_db[groupid].qty++] = nameid; + count++; } fclose(fp); - return; + return count; } static void itemdb_read_itemgroup(void) { char path[256]; + unsigned int count; snprintf(path, 255, "%s/"DBPATH"item_group_db.txt", db_path); memset(&itemgroup_db, 0, sizeof(itemgroup_db)); - itemdb_read_itemgroup_sub(path); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", "item_group_db.txt"); + count = itemdb_read_itemgroup_sub(path); + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, "item_group_db.txt"); return; } /*========================================== - * Read item forbidden by mapflag (can't equip item) - *------------------------------------------*/ -static bool itemdb_read_noequip(char* str[], int columns, int current) -{// <nameid>,<mode> - int nameid; - struct item_data *id; - - nameid = atoi(str[0]); - - if( ( id = itemdb_exists(nameid) ) == NULL ) - { - ShowWarning("itemdb_read_noequip: Invalid item id %d.\n", nameid); - return false; - } - - id->flag.no_equip |= atoi(str[1]); - - return true; -} - -/*========================================== * Reads item trade restrictions [Skotlex] *------------------------------------------*/ static bool itemdb_read_itemtrade(char* str[], int columns, int current) @@ -737,6 +728,31 @@ static bool itemdb_read_buyingstore(char* fields[], int columns, int current) return true; } + +/******************************************* +** Item usage restriction (item_nouse.txt) +********************************************/ +static bool itemdb_read_nouse(char* fields[], int columns, int current) +{// <nameid>,<flag>,<override> + int nameid, flag, override; + struct item_data* id; + + nameid = atoi(fields[0]); + + if( ( id = itemdb_exists(nameid) ) == NULL ) { + ShowWarning("itemdb_read_nouse: Invalid item id %d.\n", nameid); + return false; + } + + flag = atoi(fields[1]); + override = atoi(fields[2]); + + id->item_usage.flag = flag; + id->item_usage.override = override; + + return true; +} + /** * @return: amount of retrieved entries. **/ @@ -867,7 +883,7 @@ void itemdb_read_combos() { /* populate the children to refer to this combo */ for( v = 1; v < retcount; v++ ) { - struct item_data * it = NULL; + struct item_data * it; int index; it = itemdb_exists(items[v]); @@ -1221,19 +1237,19 @@ static int itemdb_read_sqldb(void) { uint32 lines = 0, count = 0; // retrieve all rows from the item database - if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) { + if( SQL_ERROR == SQL->Query(mmysql_handle, "SELECT * FROM `%s`", item_db_name[fi]) ) { Sql_ShowDebug(mmysql_handle); continue; } // process rows one by one - while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) {// wrap the result into a TXT-compatible format + while( SQL_SUCCESS == SQL->NextRow(mmysql_handle) ) {// wrap the result into a TXT-compatible format char* str[22]; char* dummy = ""; int i; ++lines; for( i = 0; i < 22; ++i ) { - Sql_GetData(mmysql_handle, i, &str[i], NULL); + SQL->GetData(mmysql_handle, i, &str[i], NULL); if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns } @@ -1244,7 +1260,7 @@ static int itemdb_read_sqldb(void) { } // free the query result - Sql_FreeResult(mmysql_handle); + SQL->FreeResult(mmysql_handle); ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, item_db_name[fi]); } @@ -1280,19 +1296,19 @@ uint64 itemdb_unique_id(int8 flag, int64 value) { int itemdb_uid_load(){ char * uid; - if (SQL_ERROR == Sql_Query(mmysql_handle, "SELECT `value` FROM `interreg` WHERE `varname`='unique_id'")) + if (SQL_ERROR == SQL->Query(mmysql_handle, "SELECT `value` FROM `interreg` WHERE `varname`='unique_id'")) Sql_ShowDebug(mmysql_handle); - if( SQL_SUCCESS != Sql_NextRow(mmysql_handle) ) + if( SQL_SUCCESS != SQL->NextRow(mmysql_handle) ) { ShowError("itemdb_uid_load: Unable to fetch unique_id data\n"); - Sql_FreeResult(mmysql_handle); + SQL->FreeResult(mmysql_handle); return -1; } - Sql_GetData(mmysql_handle, 0, &uid, NULL); + SQL->GetData(mmysql_handle, 0, &uid, NULL); itemdb_unique_id(1, (uint64)strtoull(uid, NULL, 10)); - Sql_FreeResult(mmysql_handle); + SQL->FreeResult(mmysql_handle); return 0; } @@ -1309,12 +1325,12 @@ static void itemdb_read(void) { itemdb_read_combos(); itemdb_read_itemgroup(); - sv_readdb(db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail); - sv_readdb(db_path, DBPATH"item_noequip.txt", ',', 2, 2, -1, &itemdb_read_noequip); - sv_readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade); - sv_readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay); - sv_readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack); - sv_readdb(db_path, DBPATH"item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore); + sv->readdb(db_path, "item_avail.txt", ',', 2, 2, -1, &itemdb_read_itemavail); + sv->readdb(db_path, DBPATH"item_trade.txt", ',', 3, 3, -1, &itemdb_read_itemtrade); + sv->readdb(db_path, "item_delay.txt", ',', 2, 2, -1, &itemdb_read_itemdelay); + sv->readdb(db_path, "item_stack.txt", ',', 3, 3, -1, &itemdb_read_stack); + sv->readdb(db_path, DBPATH"item_buyingstore.txt", ',', 1, 1, -1, &itemdb_read_buyingstore); + sv->readdb(db_path, "item_nouse.txt", ',', 3, 3, -1, &itemdb_read_nouse); itemdb_uid_load(); } @@ -1360,7 +1376,7 @@ static void destroy_item_data(struct item_data* self, int free_self) */ static int itemdb_final_sub(DBKey key, DBData *data, va_list ap) { - struct item_data *id = db_data2ptr(data); + struct item_data *id = DB->data2ptr(data); if( id != &dummy_item ) destroy_item_data(id, 1); @@ -1417,7 +1433,7 @@ void itemdb_reload(void) // readjust itemdb pointer cache for each player iter = mapit_geteachpc(); - for( sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); sd = (struct map_session_data*)mapit_next(iter) ) { + for( sd = (struct map_session_data*)mapit->first(iter); mapit->exists(iter); sd = (struct map_session_data*)mapit->next(iter) ) { memset(sd->item_delay, 0, sizeof(sd->item_delay)); // reset item delays pc_setinventorydata(sd); /* clear combo bonuses */ @@ -1432,7 +1448,7 @@ void itemdb_reload(void) } } - mapit_free(iter); + mapit->free(iter); } void do_final_itemdb(void) @@ -1452,6 +1468,7 @@ int do_init_itemdb(void) { itemdb_other = idb_alloc(DB_OPT_BASE); create_dummy_data(); //Dummy data item. itemdb_read(); + clif->cashshop_load(); return 0; } diff --git a/src/map/itemdb.h b/src/map/itemdb.h index e308b248b..c441de26a 100644 --- a/src/map/itemdb.h +++ b/src/map/itemdb.h @@ -66,7 +66,11 @@ enum { ITEMID_CAMOUFLAGE_GENERATOR, ITEMID_HIGH_QUALITY_COOLER, ITEMID_SPECIAL_COOLER, - } mecha_item_list; +} mecha_item_list; + +enum { + NOUSE_SITTING = 0x01, +} item_nouse_list; //The only item group required by the code to be known. See const.txt for the full list. #define IG_FINDINGORE 6 @@ -123,7 +127,6 @@ struct item_data { struct script_code *unequip_script;//Script executed once when unequipping. struct { unsigned available : 1; - short no_equip; unsigned no_refine : 1; // [celest] unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex] unsigned trade_restriction : 9; //Item restrictions mask [Skotlex] @@ -137,6 +140,10 @@ struct item_data { unsigned int storage:1; unsigned int guildstorage:1; } stack; + struct {// used by item_nouse.txt + unsigned int flag; + unsigned short override; + } item_usage; short gm_lv_trade_override; //GM-level to override trade_restriction /* bugreport:309 */ struct item_combo **combos; @@ -156,6 +163,8 @@ struct item_combo { bool isRef;/* whether this struct is a reference or the master */ }; +struct item_group itemgroup_db[MAX_ITEMGROUP]; + struct item_data* itemdb_searchname(const char *name); int itemdb_searchname_array(struct item_data** data, int size, const char *str); struct item_data* itemdb_load(int nameid); @@ -217,6 +226,7 @@ int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(stru int itemdb_isequip(int); int itemdb_isequip2(struct item_data *); int itemdb_isidentified(int); +int itemdb_isidentified2(struct item_data *data); int itemdb_isstackable(int); int itemdb_isstackable2(struct item_data *); uint64 itemdb_unique_id(int8 flag, int64 value); // Unique Item ID diff --git a/src/map/log.c b/src/map/log.c index ca10c97ab..f57b91a2a 100644 --- a/src/map/log.c +++ b/src/map/log.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/sql.h" // SQL_INNODB @@ -19,8 +20,7 @@ /// filters for item logging -typedef enum e_log_filter -{ +typedef enum e_log_filter { LOG_FILTER_NONE = 0x000, LOG_FILTER_ALL = 0x001, // bits @@ -38,10 +38,6 @@ typedef enum e_log_filter } e_log_filter; - -struct Log_Config log_config; - - #ifdef SQL_INNODB // database is using an InnoDB engine so do not use DELAYED #define LOG_QUERY "INSERT" @@ -52,10 +48,8 @@ struct Log_Config log_config; /// obtain log type character for item/zeny logs -static char log_picktype2char(e_log_pick_type type) -{ - switch( type ) - { +static char log_picktype2char(e_log_pick_type type) { + switch( type ) { case LOG_TYPE_TRADE: return 'T'; // (T)rade case LOG_TYPE_VENDING: return 'V'; // (V)ending case LOG_TYPE_PICKDROP_PLAYER: return 'P'; // (P)player @@ -83,10 +77,8 @@ static char log_picktype2char(e_log_pick_type type) /// obtain log type character for chat logs -static char log_chattype2char(e_log_chat_type type) -{ - switch( type ) - { +static char log_chattype2char(e_log_chat_type type) { + switch( type ) { case LOG_CHAT_GLOBAL: return 'O'; // Gl(O)bal case LOG_CHAT_WHISPER: return 'W'; // (W)hisper case LOG_CHAT_PARTY: return 'P'; // (P)arty @@ -101,12 +93,10 @@ static char log_chattype2char(e_log_chat_type type) /// check if this item should be logged according the settings -static bool should_log_item(int nameid, int amount, int refine) -{ - int filter = log_config.filter; - struct item_data* id; +static bool should_log_item(int nameid, int amount, int refine, struct item_data *id) { + int filter = logs->config.filter; - if( ( id = itemdb_exists(nameid) ) == NULL ) + if( id == NULL ) return false; if( ( filter&LOG_FILTER_ALL ) || @@ -117,360 +107,289 @@ static bool should_log_item(int nameid, int amount, int refine) ( filter&LOG_FILTER_ARMOR && id->type == IT_ARMOR ) || ( filter&LOG_FILTER_CARD && id->type == IT_CARD ) || ( filter&LOG_FILTER_PETITEM && ( id->type == IT_PETEGG || id->type == IT_PETARMOR ) ) || - ( filter&LOG_FILTER_PRICE && id->value_buy >= log_config.price_items_log ) || - ( filter&LOG_FILTER_AMOUNT && abs(amount) >= log_config.amount_items_log ) || - ( filter&LOG_FILTER_REFINE && refine >= log_config.refine_items_log ) || - ( filter&LOG_FILTER_CHANCE && ( ( id->maxchance != -1 && id->maxchance <= log_config.rare_items_log ) || id->nameid == ITEMID_EMPERIUM ) ) + ( filter&LOG_FILTER_PRICE && id->value_buy >= logs->config.price_items_log ) || + ( filter&LOG_FILTER_AMOUNT && abs(amount) >= logs->config.amount_items_log ) || + ( filter&LOG_FILTER_REFINE && refine >= logs->config.refine_items_log ) || + ( filter&LOG_FILTER_CHANCE && ( ( id->maxchance != -1 && id->maxchance <= logs->config.rare_items_log ) || id->nameid == ITEMID_EMPERIUM ) ) ) return true; return false; } - +void log_branch_sub_sql(struct map_session_data* sd) { + SqlStmt* stmt; + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', ?, '%s')", logs->config.log_branch, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) + { + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; + } + SqlStmt_Free(stmt); +} +void log_branch_sub_txt(struct map_session_data* sd) { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(logs->config.log_branch, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %s[%d:%d]\t%s\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)); + fclose(logfp); +} /// logs items, that summon monsters -void log_branch(struct map_session_data* sd) -{ +void log_branch(struct map_session_data* sd) { nullpo_retv(sd); - if( !log_config.branch ) + if( !logs->config.branch ) return; - if( log_config.sql_logs ) { -#ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', '%s', '%s')", log_config.log_branch, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex)); - queryThread_log(entry,e_length); -#else - SqlStmt* stmt; - stmt = SqlStmt_Malloc(logmysql_handle); - if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`branch_date`, `account_id`, `char_id`, `char_name`, `map`) VALUES (NOW(), '%d', '%d', ?, '%s')", log_config.log_branch, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } - SqlStmt_Free(stmt); -#endif - } - else + logs->branch_sub(sd); +} +void log_pick_sub_sql(int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) { + if( SQL_ERROR == SQL->Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%"PRIu64"')", + logs->config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id) ) { - char timestring[255]; - time_t curtime; - FILE* logfp; - - if( ( logfp = fopen(log_config.log_branch, "a") ) == NULL ) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d:%d]\t%s\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex)); - fclose(logfp); + Sql_ShowDebug(logmysql_handle); + return; } } - +void log_pick_sub_txt(int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(logs->config.log_pick, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %d\t%c\t%d,%d,%d,%d,%d,%d,%d,%s,'%"PRIu64"'\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id); + fclose(logfp); +} /// logs item transactions (generic) -void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* itm) -{ +void log_pick(int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) { nullpo_retv(itm); - if( ( log_config.enable_logs&type ) == 0 ) - {// disabled + if( ( logs->config.enable_logs&type ) == 0 ) {// disabled return; } - if( !should_log_item(itm->nameid, amount, itm->refine) ) + if( !should_log_item(itm->nameid, amount, itm->refine, data) ) return; //we skip logging this item set - it doesn't meet our logging conditions [Lupus] - if( log_config.sql_logs ) - { -#ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%"PRIu64"')", - log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id); - queryThread_log(entry,e_length); -#else - if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `type`, `nameid`, `amount`, `refine`, `card0`, `card1`, `card2`, `card3`, `map`, `unique_id`) VALUES (NOW(), '%d', '%c', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%s', '%"PRIu64"')", - log_config.log_pick, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id) ) - { - Sql_ShowDebug(logmysql_handle); - return; - } -#endif - } - else - { - char timestring[255]; - time_t curtime; - FILE* logfp; - - if( ( logfp = fopen(log_config.log_pick, "a") ) == NULL ) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %d\t%c\t%d,%d,%d,%d,%d,%d,%d,%s,'%"PRIu64"'\n", timestring, id, log_picktype2char(type), itm->nameid, amount, itm->refine, itm->card[0], itm->card[1], itm->card[2], itm->card[3], map[m].name?map[m].name:"", itm->unique_id); - fclose(logfp); - } + logs->pick_sub(id,m,type,amount,itm,data); } /// logs item transactions (players) -void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm) -{ +void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) { nullpo_retv(sd); - log_pick(sd->status.char_id, sd->bl.m, type, amount, itm); + log_pick(sd->status.char_id, sd->bl.m, type, amount, itm, data ? data : itemdb_exists(itm->nameid)); } /// logs item transactions (monsters) -void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm) -{ +void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data) { nullpo_retv(md); - log_pick(md->class_, md->bl.m, type, amount, itm); + log_pick(md->class_, md->bl.m, type, amount, itm, data ? data : itemdb_exists(itm->nameid)); +} +void log_zeny_sub_sql(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) { + if( SQL_ERROR == SQL->Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", + logs->config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)) ) + { + Sql_ShowDebug(logmysql_handle); + return; + } +} +void log_zeny_sub_txt(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(logs->config.log_zeny, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]\t%s[%d]\t%d\t\n", timestring, src_sd->status.name, src_sd->status.account_id, sd->status.name, sd->status.account_id, amount); + fclose(logfp); } - /// logs zeny transactions void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount) { nullpo_retv(sd); - if( !log_config.zeny || ( log_config.zeny != 1 && abs(amount) < log_config.zeny ) ) + if( !logs->config.zeny || ( logs->config.zeny != 1 && abs(amount) < logs->config.zeny ) ) return; - if( log_config.sql_logs ) - { -#ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", - log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)); - queryThread_log(entry,e_length); -#else - if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`time`, `char_id`, `src_id`, `type`, `amount`, `map`) VALUES (NOW(), '%d', '%d', '%c', '%d', '%s')", - log_config.log_zeny, sd->status.char_id, src_sd->status.char_id, log_picktype2char(type), amount, mapindex_id2name(sd->mapindex)) ) - { - Sql_ShowDebug(logmysql_handle); - return; - } -#endif - } - else + logs->zeny_sub(sd,type,src_sd,amount); +} +void log_mvpdrop_sub_sql(struct map_session_data* sd, int monster_id, int* log_mvp) { + if( SQL_ERROR == SQL->Query(logmysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", + logs->config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)) ) { - char timestring[255]; - time_t curtime; - FILE* logfp; - - if( ( logfp = fopen(log_config.log_zeny, "a") ) == NULL ) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %s[%d]\t%s[%d]\t%d\t\n", timestring, src_sd->status.name, src_sd->status.account_id, sd->status.name, sd->status.account_id, amount); - fclose(logfp); + Sql_ShowDebug(logmysql_handle); + return; } } - - +void log_mvpdrop_sub_txt(struct map_session_data* sd, int monster_id, int* log_mvp) { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(logs->config.log_mvpdrop,"a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1]); + fclose(logfp); +} /// logs MVP monster rewards void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp) { nullpo_retv(sd); - if( !log_config.mvpdrop ) + if( !logs->config.mvpdrop ) return; - if( log_config.sql_logs ) - { -#ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", - log_config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)); - queryThread_log(entry,e_length); -#else - if( SQL_ERROR == Sql_Query(logmysql_handle, LOG_QUERY " INTO `%s` (`mvp_date`, `kill_char_id`, `monster_id`, `prize`, `mvpexp`, `map`) VALUES (NOW(), '%d', '%d', '%d', '%d', '%s') ", - log_config.log_mvpdrop, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1], mapindex_id2name(sd->mapindex)) ) - { - Sql_ShowDebug(logmysql_handle); - return; - } -#endif - } - else + logs->mvpdrop_sub(sd,monster_id,log_mvp); +} + +void log_atcommand_sub_sql(struct map_session_data* sd, const char* message) { + SqlStmt* stmt; + + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { - char timestring[255]; - time_t curtime; - FILE* logfp; - - if( ( logfp = fopen(log_config.log_mvpdrop,"a") ) == NULL ) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp,"%s - %s[%d:%d]\t%d\t%d,%d\n", timestring, sd->status.name, sd->status.account_id, sd->status.char_id, monster_id, log_mvp[0], log_mvp[1]); - fclose(logfp); + SqlStmt_ShowDebug(stmt); + SqlStmt_Free(stmt); + return; } + SqlStmt_Free(stmt); +} +void log_atcommand_sub_txt(struct map_session_data* sd, const char* message) { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(logs->config.log_gm, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); + fclose(logfp); } - - /// logs used atcommands void log_atcommand(struct map_session_data* sd, const char* message) { nullpo_retv(sd); - if( !log_config.commands || + if( !logs->config.commands || !pc_should_log_commands(sd) ) return; - if( log_config.sql_logs ) + logs->atcommand_sub(sd,message); +} + +void log_npc_sub_sql(struct map_session_data *sd, const char *message) { + SqlStmt* stmt; + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", logs->config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { -#ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', '%s', '%s', '%s')", log_config.log_gm, sd->status.account_id, sd->status.char_id, sd->status.name ,mapindex_id2name(sd->mapindex), message); - queryThread_log(entry,e_length); -#else - SqlStmt* stmt; - - stmt = SqlStmt_Malloc(logmysql_handle); - if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`atcommand_date`, `account_id`, `char_id`, `char_name`, `map`, `command`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_gm, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255)) - || SQL_SUCCESS != SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } + SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); -#endif - } - else - { - char timestring[255]; - time_t curtime; - FILE* logfp; - - if( ( logfp = fopen(log_config.log_gm, "a") ) == NULL ) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); - fclose(logfp); + return; } + SqlStmt_Free(stmt); +} +void log_npc_sub_txt(struct map_session_data *sd, const char *message) { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(logs->config.log_npc, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); + fclose(logfp); } - - /// logs messages passed to script command 'logmes' void log_npc(struct map_session_data* sd, const char* message) { nullpo_retv(sd); - if( !log_config.npc ) + if( !logs->config.npc ) return; - if( log_config.sql_logs ) + logs->npc_sub(sd,message); +} + +void log_chat_sub_sql(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message) { + SqlStmt* stmt; + + stmt = SqlStmt_Malloc(logmysql_handle); + if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", logs->config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH)) + || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE_MAX)) + || SQL_SUCCESS != SqlStmt_Execute(stmt) ) { -#ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', '%s', '%s', '%s')", log_config.log_npc, sd->status.account_id, sd->status.char_id, sd->status.name, mapindex_id2name(sd->mapindex), message ); - queryThread_log(entry,e_length); -#else - SqlStmt* stmt; - stmt = SqlStmt_Malloc(logmysql_handle); - if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`npc_date`, `account_id`, `char_id`, `char_name`, `map`, `mes`) VALUES (NOW(), '%d', '%d', ?, '%s', ?)", log_config.log_npc, sd->status.account_id, sd->status.char_id, mapindex_id2name(sd->mapindex) ) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, sd->status.name, strnlen(sd->status.name, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, 255)) - || SQL_SUCCESS != SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } + SqlStmt_ShowDebug(stmt); SqlStmt_Free(stmt); -#endif - } - else - { - char timestring[255]; - time_t curtime; - FILE* logfp; - - if( ( logfp = fopen(log_config.log_npc, "a") ) == NULL ) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %s[%d]: %s\n", timestring, sd->status.name, sd->status.account_id, message); - fclose(logfp); + return; } + SqlStmt_Free(stmt); +} +void log_chat_sub_txt(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message) { + char timestring[255]; + time_t curtime; + FILE* logfp; + + if( ( logfp = fopen(logs->config.log_chat, "a") ) == NULL ) + return; + time(&curtime); + strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); + fprintf(logfp, "%s - %c,%d,%d,%d,%s,%d,%d,%s,%s\n", timestring, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message); + fclose(logfp); } - /// logs chat void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message) { - if( ( log_config.chat&type ) == 0 ) + if( ( logs->config.chat&type ) == 0 ) {// disabled return; } - if( log_config.log_chat_woe_disable && ( agit_flag || agit2_flag ) ) + if( logs->config.log_chat_woe_disable && ( agit_flag || agit2_flag ) ) {// no chat logging during woe return; } - if( log_config.sql_logs ) { -#ifdef BETA_THREAD_TEST - char entry[512]; - int e_length = 0; - e_length = sprintf(entry, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', '%s', '%s')", log_config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message ); - queryThread_log(entry,e_length); -#else - SqlStmt* stmt; - - stmt = SqlStmt_Malloc(logmysql_handle); - if( SQL_SUCCESS != SqlStmt_Prepare(stmt, LOG_QUERY " INTO `%s` (`time`, `type`, `type_id`, `src_charid`, `src_accountid`, `src_map`, `src_map_x`, `src_map_y`, `dst_charname`, `message`) VALUES (NOW(), '%c', '%d', '%d', '%d', '%s', '%d', '%d', ?, ?)", log_config.log_chat, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 0, SQLDT_STRING, (char*)dst_charname, safestrnlen(dst_charname, NAME_LENGTH)) - || SQL_SUCCESS != SqlStmt_BindParam(stmt, 1, SQLDT_STRING, (char*)message, safestrnlen(message, CHAT_SIZE_MAX)) - || SQL_SUCCESS != SqlStmt_Execute(stmt) ) - { - SqlStmt_ShowDebug(stmt); - SqlStmt_Free(stmt); - return; - } - SqlStmt_Free(stmt); -#endif - } - else - { - char timestring[255]; - time_t curtime; - FILE* logfp; - - if( ( logfp = fopen(log_config.log_chat, "a") ) == NULL ) - return; - time(&curtime); - strftime(timestring, sizeof(timestring), "%m/%d/%Y %H:%M:%S", localtime(&curtime)); - fprintf(logfp, "%s - %c,%d,%d,%d,%s,%d,%d,%s,%s\n", timestring, log_chattype2char(type), type_id, src_charid, src_accid, map, x, y, dst_charname, message); - fclose(logfp); - } + logs->chat_sub(type,type_id,src_charid,src_accid,map,x,y,dst_charname,message); } -void log_set_defaults(void) -{ - memset(&log_config, 0, sizeof(log_config)); +void log_set_defaults(void) { + memset(&logs->config, 0, sizeof(logs->config)); //LOG FILTER Default values - log_config.refine_items_log = 5; // log refined items, with refine >= +5 - log_config.rare_items_log = 100; // log rare items. drop chance <= 1% - log_config.price_items_log = 1000; // 1000z - log_config.amount_items_log = 100; + logs->config.refine_items_log = 5; // log refined items, with refine >= +5 + logs->config.rare_items_log = 100; // log rare items. drop chance <= 1% + logs->config.price_items_log = 1000; // 1000z + logs->config.amount_items_log = 100; } -int log_config_read(const char* cfgName) -{ +int log_config_read(const char* cfgName) { static int count = 0; char line[1024], w1[1024], w2[1024]; FILE *fp; @@ -478,63 +397,60 @@ int log_config_read(const char* cfgName) if( count++ == 0 ) log_set_defaults(); - if( ( fp = fopen(cfgName, "r") ) == NULL ) - { + if( ( fp = fopen(cfgName, "r") ) == NULL ) { ShowError("Log configuration file not found at: %s\n", cfgName); return 1; } - while( fgets(line, sizeof(line), fp) ) - { + while( fgets(line, sizeof(line), fp) ) { if( line[0] == '/' && line[1] == '/' ) continue; - if( sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 ) - { + if( sscanf(line, "%[^:]: %[^\r\n]", w1, w2) == 2 ) { if( strcmpi(w1, "enable_logs") == 0 ) - log_config.enable_logs = (e_log_pick_type)config_switch(w2); + logs->config.enable_logs = (e_log_pick_type)config_switch(w2); else if( strcmpi(w1, "sql_logs") == 0 ) - log_config.sql_logs = (bool)config_switch(w2); + logs->config.sql_logs = (bool)config_switch(w2); //start of common filter settings else if( strcmpi(w1, "rare_items_log") == 0 ) - log_config.rare_items_log = atoi(w2); + logs->config.rare_items_log = atoi(w2); else if( strcmpi(w1, "refine_items_log") == 0 ) - log_config.refine_items_log = atoi(w2); + logs->config.refine_items_log = atoi(w2); else if( strcmpi(w1, "price_items_log") == 0 ) - log_config.price_items_log = atoi(w2); + logs->config.price_items_log = atoi(w2); else if( strcmpi(w1, "amount_items_log") == 0 ) - log_config.amount_items_log = atoi(w2); + logs->config.amount_items_log = atoi(w2); //end of common filter settings else if( strcmpi(w1, "log_branch") == 0 ) - log_config.branch = config_switch(w2); + logs->config.branch = config_switch(w2); else if( strcmpi(w1, "log_filter") == 0 ) - log_config.filter = config_switch(w2); + logs->config.filter = config_switch(w2); else if( strcmpi(w1, "log_zeny") == 0 ) - log_config.zeny = config_switch(w2); + logs->config.zeny = config_switch(w2); else if( strcmpi(w1, "log_commands") == 0 ) - log_config.commands = config_switch(w2); + logs->config.commands = config_switch(w2); else if( strcmpi(w1, "log_npc") == 0 ) - log_config.npc = config_switch(w2); + logs->config.npc = config_switch(w2); else if( strcmpi(w1, "log_chat") == 0 ) - log_config.chat = config_switch(w2); + logs->config.chat = config_switch(w2); else if( strcmpi(w1, "log_mvpdrop") == 0 ) - log_config.mvpdrop = config_switch(w2); + logs->config.mvpdrop = config_switch(w2); else if( strcmpi(w1, "log_chat_woe_disable") == 0 ) - log_config.log_chat_woe_disable = (bool)config_switch(w2); + logs->config.log_chat_woe_disable = (bool)config_switch(w2); else if( strcmpi(w1, "log_branch_db") == 0 ) - safestrncpy(log_config.log_branch, w2, sizeof(log_config.log_branch)); + safestrncpy(logs->config.log_branch, w2, sizeof(logs->config.log_branch)); else if( strcmpi(w1, "log_pick_db") == 0 ) - safestrncpy(log_config.log_pick, w2, sizeof(log_config.log_pick)); + safestrncpy(logs->config.log_pick, w2, sizeof(logs->config.log_pick)); else if( strcmpi(w1, "log_zeny_db") == 0 ) - safestrncpy(log_config.log_zeny, w2, sizeof(log_config.log_zeny)); + safestrncpy(logs->config.log_zeny, w2, sizeof(logs->config.log_zeny)); else if( strcmpi(w1, "log_mvpdrop_db") == 0 ) - safestrncpy(log_config.log_mvpdrop, w2, sizeof(log_config.log_mvpdrop)); + safestrncpy(logs->config.log_mvpdrop, w2, sizeof(logs->config.log_mvpdrop)); else if( strcmpi(w1, "log_gm_db") == 0 ) - safestrncpy(log_config.log_gm, w2, sizeof(log_config.log_gm)); + safestrncpy(logs->config.log_gm, w2, sizeof(logs->config.log_gm)); else if( strcmpi(w1, "log_npc_db") == 0 ) - safestrncpy(log_config.log_npc, w2, sizeof(log_config.log_npc)); + safestrncpy(logs->config.log_npc, w2, sizeof(logs->config.log_npc)); else if( strcmpi(w1, "log_chat_db") == 0 ) - safestrncpy(log_config.log_chat, w2, sizeof(log_config.log_chat)); + safestrncpy(logs->config.log_chat, w2, sizeof(logs->config.log_chat)); //support the import command, just like any other config else if( strcmpi(w1,"import") == 0 ) log_config_read(w2); @@ -545,39 +461,67 @@ int log_config_read(const char* cfgName) fclose(fp); - if( --count == 0 ) - {// report final logging state - const char* target = log_config.sql_logs ? "table" : "file"; + if( --count == 0 ) {// report final logging state + const char* target = logs->config.sql_logs ? "table" : "file"; - if( log_config.enable_logs && log_config.filter ) - { - ShowInfo("Logging item transactions to %s '%s'.\n", target, log_config.log_pick); + if( logs->config.enable_logs && logs->config.filter ) { + ShowInfo("Logging item transactions to %s '%s'.\n", target, logs->config.log_pick); } - if( log_config.branch ) - { - ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, log_config.log_pick); + if( logs->config.branch ) { + ShowInfo("Logging monster summon item usage to %s '%s'.\n", target, logs->config.log_pick); } - if( log_config.chat ) - { - ShowInfo("Logging chat to %s '%s'.\n", target, log_config.log_chat); + if( logs->config.chat ) { + ShowInfo("Logging chat to %s '%s'.\n", target, logs->config.log_chat); } - if( log_config.commands ) - { - ShowInfo("Logging commands to %s '%s'.\n", target, log_config.log_gm); + if( logs->config.commands ) { + ShowInfo("Logging commands to %s '%s'.\n", target, logs->config.log_gm); } - if( log_config.mvpdrop ) - { - ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, log_config.log_mvpdrop); + if( logs->config.mvpdrop ) { + ShowInfo("Logging MVP monster rewards to %s '%s'.\n", target, logs->config.log_mvpdrop); } - if( log_config.npc ) - { - ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, log_config.log_npc); + if( logs->config.npc ) { + ShowInfo("Logging 'logmes' messages to %s '%s'.\n", target, logs->config.log_npc); } - if( log_config.zeny ) - { - ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, log_config.log_zeny); + if( logs->config.zeny ) { + ShowInfo("Logging Zeny transactions to %s '%s'.\n", target, logs->config.log_zeny); } + logs->config_done(); } return 0; } +void log_config_complete(void) { + if( logs->config.sql_logs ) { + logs->pick_sub = log_pick_sub_sql; + logs->zeny_sub = log_zeny_sub_sql; + logs->npc_sub = log_npc_sub_sql; + logs->chat_sub = log_chat_sub_sql; + logs->atcommand_sub = log_atcommand_sub_sql; + logs->branch_sub = log_branch_sub_sql; + logs->mvpdrop_sub = log_mvpdrop_sub_sql; + } +} +void log_defaults(void) { + logs = &log_s; + + logs->pick_pc = log_pick_pc; + logs->pick_mob = log_pick_mob; + logs->zeny = log_zeny; + logs->npc = log_npc; + logs->chat = log_chat; + logs->atcommand = log_atcommand; + logs->branch = log_branch; + logs->mvpdrop = log_mvpdrop; + logs->config_read = log_config_read; + logs->config_done = log_config_complete; + + /* will be modified in a few seconds once loading is complete. */ + logs->pick_sub = log_pick_sub_txt; + logs->zeny_sub = log_zeny_sub_txt; + logs->npc_sub = log_npc_sub_txt; + logs->chat_sub = log_chat_sub_txt; + logs->atcommand_sub = log_atcommand_sub_txt; + logs->branch_sub = log_branch_sub_txt; + logs->mvpdrop_sub = log_mvpdrop_sub_txt; + +} diff --git a/src/map/log.h b/src/map/log.h index a40a3fcf4..462a12ff5 100644 --- a/src/map/log.h +++ b/src/map/log.h @@ -1,18 +1,18 @@ -// 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 _LOG_H_ #define _LOG_H_ -//#include "map.h" struct block_list; struct map_session_data; struct mob_data; struct item; +struct item_data; -typedef enum e_log_chat_type -{ +typedef enum e_log_chat_type { LOG_CHAT_GLOBAL = 0x01, LOG_CHAT_WHISPER = 0x02, LOG_CHAT_PARTY = 0x04, @@ -20,12 +20,10 @@ typedef enum e_log_chat_type LOG_CHAT_MAINCHAT = 0x10, // all LOG_CHAT_ALL = 0xFF, -} -e_log_chat_type; +} e_log_chat_type; -typedef enum e_log_pick_type -{ +typedef enum e_log_pick_type { LOG_TYPE_NONE = 0, LOG_TYPE_TRADE = 0x00001, LOG_TYPE_VENDING = 0x00002, @@ -48,42 +46,42 @@ typedef enum e_log_pick_type LOG_TYPE_LOOT = LOG_TYPE_PICKDROP_MONSTER|LOG_TYPE_CONSUME, // all LOG_TYPE_ALL = 0xFFFFF, -} -e_log_pick_type; +} e_log_pick_type; +struct log_interface { + struct { + e_log_pick_type enable_logs; + int filter; + bool sql_logs; + bool log_chat_woe_disable; + int rare_items_log,refine_items_log,price_items_log,amount_items_log; + int branch, mvpdrop, zeny, commands, npc, chat; + char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64]; + } config; + /* */ + void (*pick_pc) (struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm, struct item_data *data); + void (*pick_mob) (struct mob_data* md, e_log_pick_type type, int amount, struct item* itm, struct item_data *data); + void (*zeny) (struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount); + void (*npc) (struct map_session_data* sd, const char *message); + void (*chat) (e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message); + void (*atcommand) (struct map_session_data* sd, const char* message); + void (*branch) (struct map_session_data* sd); + void (*mvpdrop) (struct map_session_data* sd, int monster_id, int* log_mvp); + + void (*pick_sub) (int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data); + void (*zeny_sub) (struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount); + void (*npc_sub) (struct map_session_data* sd, const char *message); + void (*chat_sub) (e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message); + void (*atcommand_sub) (struct map_session_data* sd, const char* message); + void (*branch_sub) (struct map_session_data* sd); + void (*mvpdrop_sub) (struct map_session_data* sd, int monster_id, int* log_mvp); + + int (*config_read) (const char* cfgName); + void (*config_done) (void); +} log_s; -/// new logs -void log_pick_pc(struct map_session_data* sd, e_log_pick_type type, int amount, struct item* itm); -void log_pick_mob(struct mob_data* md, e_log_pick_type type, int amount, struct item* itm); -void log_zeny(struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount); - -void log_npc(struct map_session_data* sd, const char *message); -void log_chat(e_log_chat_type type, int type_id, int src_charid, int src_accid, const char* map, int x, int y, const char* dst_charname, const char* message); -void log_atcommand(struct map_session_data* sd, const char* message); - -/// old, but useful logs -void log_branch(struct map_session_data* sd); -void log_mvpdrop(struct map_session_data* sd, int monster_id, int* log_mvp); - -int log_config_read(const char* cfgName); - -extern struct Log_Config -{ - e_log_pick_type enable_logs; - int filter; - bool sql_logs; - bool log_chat_woe_disable; - int rare_items_log,refine_items_log,price_items_log,amount_items_log; //for filter - int branch, mvpdrop, zeny, commands, npc, chat; - char log_branch[64], log_pick[64], log_zeny[64], log_mvpdrop[64], log_gm[64], log_npc[64], log_chat[64]; -} -log_config; +struct log_interface *logs; -#ifdef BETA_THREAD_TEST - struct { - char** entry; - int count; - } logThreadData; -#endif +void log_defaults(void); #endif /* _LOG_H_ */ diff --git a/src/map/mail.c b/src/map/mail.c index 03b8227b5..fa842b70f 100644 --- a/src/map/mail.c +++ b/src/map/mail.c @@ -33,7 +33,7 @@ int mail_removeitem(struct map_session_data *sd, short flag) if (flag) // Item send pc_delitem(sd, sd->mail.index, sd->mail.amount, 1, 0, LOG_TYPE_MAIL); else - clif_additem(sd, sd->mail.index, sd->mail.amount, 0); + clif->additem(sd, sd->mail.index, sd->mail.amount, 0); } sd->mail.nameid = 0; @@ -68,7 +68,7 @@ unsigned char mail_setitem(struct map_session_data *sd, int idx, int amount) { amount = sd->status.zeny; sd->mail.zeny = amount; - // clif_updatestatus(sd, SP_ZENY); + // clif->updatestatus(sd, SP_ZENY); return 0; } else { // Item Transfer idx -= 2; @@ -132,7 +132,7 @@ void mail_getattachment(struct map_session_data* sd, int zeny, struct item* item if( item->nameid > 0 && item->amount > 0 ) { pc_additem(sd, item, item->amount, LOG_TYPE_MAIL); - clif_Mail_getattachment(sd->fd, 0); + clif->mail_getattachment(sd->fd, 0); } if( zeny > 0 ) @@ -148,7 +148,7 @@ int mail_openmail(struct map_session_data *sd) if( sd->state.storage_flag || sd->state.vending || sd->state.buyingstore || sd->state.trading ) return 0; - clif_Mail_window(sd->fd, 0); + clif->mail_window(sd->fd, 0); return 1; } @@ -169,15 +169,15 @@ void mail_deliveryfail(struct map_session_data *sd, struct mail_message *msg) pc_getzeny(sd,msg->zeny,LOG_TYPE_MAIL, NULL); //Zeny receive (due to failure) } - clif_Mail_send(sd->fd, true); + clif->mail_send(sd->fd, true); } // This function only check if the mail operations are valid bool mail_invalid_operation(struct map_session_data *sd) { - if( !map[sd->bl.m].flag.town && !pc_can_use_command(sd, "mail", COMMAND_ATCOMMAND) ) + if( !map[sd->bl.m].flag.town && !pc_can_use_command(sd, "@mail") ) { - ShowWarning("clif_parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name); + ShowWarning("clif->parse_Mail: char '%s' trying to do invalid mail operations.\n", sd->status.name); return true; } diff --git a/src/map/map.c b/src/map/map.c index a8521de7d..6f61375fe 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1,9 +1,11 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/core.h" #include "../common/timer.h" +#include "../common/ers.h" #include "../common/grfio.h" #include "../common/malloc.h" #include "../common/socket.h" // WFIFO*() @@ -12,6 +14,9 @@ #include "../common/random.h" #include "../common/strlib.h" #include "../common/utils.h" +#include "../common/conf.h" +#include "../common/console.h" +#include "../common/HPM.h" #include "map.h" #include "path.h" @@ -45,6 +50,8 @@ #include "atcommand.h" #include "log.h" #include "mail.h" +#include "irc-bot.h" + #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -80,10 +87,6 @@ char log_db_pw[32] = "ragnarok"; char log_db_db[32] = "log"; Sql* logmysql_handle; -// This param using for sending mainchat -// messages like whispers to this nick. [LuzZza] -char main_chat_nick[16] = "Main"; - char *INTER_CONF_NAME; char *LOG_CONF_NAME; char *MAP_CONF_NAME; @@ -114,7 +117,6 @@ static int block_free_count = 0, block_free_lock = 0; static struct block_list *bl_list[BL_LIST_MAX]; static int bl_list_count = 0; -struct map_data map[MAX_MAP_PER_SERVER]; int map_num = 0; int map_port=0; @@ -156,10 +158,12 @@ char charhelp_txt[256] = "conf/charhelp.txt"; char wisp_server_name[NAME_LENGTH] = "Server"; // can be modified in char-server configuration file -int console = 0; int enable_spy = 0; //To enable/disable @spy commands, which consume too much cpu time when sending packets. [Skotlex] int enable_grf = 0; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89] +/* [Ind/Hercules] */ +struct eri *map_iterator_ers; + /*========================================== * server player count (of all mapservers) *------------------------------------------*/ @@ -365,7 +369,7 @@ int map_delblock(struct block_list* bl) /*========================================== * Moves a block a x/y target position. [Skotlex] - * Pass flag as 1 to prevent doing skill_unit_move checks + * Pass flag as 1 to prevent doing skill->unit_move checks * (which are executed by default on BL_CHAR types) *------------------------------------------*/ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) @@ -385,14 +389,14 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) if (bl->type&BL_CHAR) { sc = status_get_sc(bl); - skill_unit_move(bl,tick,2); + skill->unit_move(bl,tick,2); status_change_end(bl, SC_CLOSECONFINE, INVALID_TIMER); status_change_end(bl, SC_CLOSECONFINE2, INVALID_TIMER); // status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure... status_change_end(bl, SC_TATAMIGAESHI, INVALID_TIMER); status_change_end(bl, SC_MAGICROD, INVALID_TIMER); if (sc->data[SC_PROPERTYWALK] && - sc->data[SC_PROPERTYWALK]->val3 >= skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) + sc->data[SC_PROPERTYWALK]->val3 >= skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) status_change_end(bl,SC_PROPERTYWALK,INVALID_TIMER); } else if (bl->type == BL_NPC) @@ -411,11 +415,11 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) if (bl->type&BL_CHAR) { - skill_unit_move(bl,tick,3); + skill->unit_move(bl,tick,3); if( bl->type == BL_PC && ((TBL_PC*)bl)->shadowform_id ) {//Shadow Form Target Moving struct block_list *d_bl; - if( (d_bl = map_id2bl(((TBL_PC*)bl)->shadowform_id)) == NULL || bl->m != d_bl->m || !check_distance_bl(bl,d_bl,10) ) { + if( (d_bl = map_id2bl(((TBL_PC*)bl)->shadowform_id)) == NULL || !check_distance_bl(bl,d_bl,10) ) { if( d_bl ) status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER); ((TBL_PC*)bl)->shadowform_id = 0; @@ -424,31 +428,31 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) if (sc && sc->count) { if (sc->data[SC_DANCING]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_DANCING]->val2), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_DANCING]->val2), bl->m, x1-x0, y1-y0); else { if (sc->data[SC_CLOAKING]) - skill_check_cloaking(bl, sc->data[SC_CLOAKING]); + skill->check_cloaking(bl, sc->data[SC_CLOAKING]); if (sc->data[SC_WARM]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_WARM]->val4), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_WARM]->val4), bl->m, x1-x0, y1-y0); if (sc->data[SC_BANDING]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_BANDING]->val4), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_BANDING]->val4), bl->m, x1-x0, y1-y0); if (sc->data[SC_NEUTRALBARRIER_MASTER]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_NEUTRALBARRIER_MASTER]->val2), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_NEUTRALBARRIER_MASTER]->val2), bl->m, x1-x0, y1-y0); else if (sc->data[SC_STEALTHFIELD_MASTER]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_STEALTHFIELD_MASTER]->val2), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_STEALTHFIELD_MASTER]->val2), bl->m, x1-x0, y1-y0); if( sc->data[SC__SHADOWFORM] ) {//Shadow Form Caster Moving struct block_list *d_bl; - if( (d_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2)) == NULL || bl->m != d_bl->m || !check_distance_bl(bl,d_bl,10) ) + if( (d_bl = map_id2bl(sc->data[SC__SHADOWFORM]->val2)) == NULL || !check_distance_bl(bl,d_bl,10) ) status_change_end(bl,SC__SHADOWFORM,INVALID_TIMER); } if (sc->data[SC_PROPERTYWALK] - && sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) + && sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) && map_find_skill_unit_oncell(bl,bl->x,bl->y,SO_ELECTRICWALK,NULL,0) == NULL && map_find_skill_unit_oncell(bl,bl->x,bl->y,SO_FIREWALK,NULL,0) == NULL - && skill_unitsetting(bl,sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2,x0, y0,0)) { + && skill->unitsetting(bl,sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2,x0, y0,0)) { sc->data[SC_PROPERTYWALK]->val3++; } @@ -457,13 +461,13 @@ int map_moveblock(struct block_list *bl, int x1, int y1, unsigned int tick) /* Guild Aura Moving */ if( bl->type == BL_PC && ((TBL_PC*)bl)->state.gmaster_flag ) { if (sc->data[SC_LEADERSHIP]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_LEADERSHIP]->val4), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_LEADERSHIP]->val4), bl->m, x1-x0, y1-y0); if (sc->data[SC_GLORYWOUNDS]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_GLORYWOUNDS]->val4), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_GLORYWOUNDS]->val4), bl->m, x1-x0, y1-y0); if (sc->data[SC_SOULCOLD]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_SOULCOLD]->val4), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_SOULCOLD]->val4), bl->m, x1-x0, y1-y0); if (sc->data[SC_HAWKEYES]) - skill_unit_move_unit_group(skill_id2group(sc->data[SC_HAWKEYES]->val4), bl->m, x1-x0, y1-y0); + skill->unit_move_unit_group(skill->id2group(sc->data[SC_HAWKEYES]->val4), bl->m, x1-x0, y1-y0); } } } else @@ -524,7 +528,7 @@ struct skill_unit* map_find_skill_unit_oncell(struct block_list* target,int16 x, unit = (struct skill_unit *) bl; if( unit == out_unit || !unit->alive || !unit->group || unit->group->skill_id != skill_id ) continue; - if( !(flag&1) || battle_check_target(&unit->bl,target,unit->group->target_flag) > 0 ) + if( !(flag&1) || battle->check_target(&unit->bl,target,unit->group->target_flag) > 0 ) return unit; } return NULL; @@ -1280,7 +1284,7 @@ int map_clearflooritem_timer(int tid, unsigned int tick, int id, intptr_t data) if (search_petDB_index(fitem->item_data.nameid, PET_EGG) >= 0) intif_delete_petdata(MakeDWord(fitem->item_data.card[1], fitem->item_data.card[2])); - clif_clearflooritem(fitem, 0); + clif->clearflooritem(fitem, 0); map_deliddb(&fitem->bl); map_delblock(&fitem->bl); map_freeblock(&fitem->bl); @@ -1296,7 +1300,7 @@ void map_clearflooritem(struct block_list *bl) { if( fitem->cleartimer ) delete_timer(fitem->cleartimer,map_clearflooritem_timer); - clif_clearflooritem(fitem, 0); + clif->clearflooritem(fitem, 0); map_deliddb(&fitem->bl); map_delblock(&fitem->bl); map_freeblock(&fitem->bl); @@ -1463,7 +1467,7 @@ int map_addflooritem(struct item *item_data,int amount,int16 m,int16 x,int16 y,i map_addiddb(&fitem->bl); map_addblock(&fitem->bl); - clif_dropflooritem(fitem); + clif->dropflooritem(fitem); return fitem->bl.id; } @@ -1475,7 +1479,7 @@ static DBData create_charid2nick(DBKey key, va_list args) { struct charid2nick *p; CREATE(p, struct charid2nick, 1); - return db_ptr2data(p); + return DB->ptr2data(p); } /// Adds(or replaces) the nick of charid to nick_db and fullfils pending requests. @@ -1492,13 +1496,12 @@ void map_addnickdb(int charid, const char* nick) p = idb_ensure(nick_db, charid, create_charid2nick); safestrncpy(p->nick, nick, sizeof(p->nick)); - while( p->requests ) - { + while( p->requests ) { req = p->requests; p->requests = req->next; sd = map_charid2sd(req->charid); if( sd ) - clif_solved_charname(sd->fd, charid, p->nick); + clif->solved_charname(sd->fd, charid, p->nick); aFree(req); } } @@ -1512,16 +1515,15 @@ void map_delnickdb(int charid, const char* name) struct map_session_data* sd; DBData data; - if (!nick_db->remove(nick_db, db_i2key(charid), &data) || (p = db_data2ptr(&data)) == NULL) + if (!nick_db->remove(nick_db, DB->i2key(charid), &data) || (p = DB->data2ptr(&data)) == NULL) return; - while( p->requests ) - { + while( p->requests ) { req = p->requests; p->requests = req->next; sd = map_charid2sd(req->charid); if( sd ) - clif_solved_charname(sd->fd, charid, name); + clif->solved_charname(sd->fd, charid, name); aFree(req); } aFree(p); @@ -1539,16 +1541,14 @@ void map_reqnickdb(struct map_session_data * sd, int charid) nullpo_retv(sd); tsd = map_charid2sd(charid); - if( tsd ) - { - clif_solved_charname(sd->fd, charid, tsd->status.name); + if( tsd ) { + clif->solved_charname(sd->fd, charid, tsd->status.name); return; } p = idb_ensure(nick_db, charid, create_charid2nick); - if( *p->nick ) - { - clif_solved_charname(sd->fd, charid, p->nick); + if( *p->nick ) { + clif->solved_charname(sd->fd, charid, p->nick); return; } // not in cache, request it @@ -1698,15 +1698,22 @@ int map_quit(struct map_session_data *sd) { if( sd->state.storage_flag == 1 ) sd->state.storage_flag = 0; // No need to Double Save Storage on Quit. + if (sd->state.permanent_speed == 1) sd->state.permanent_speed = 0; // Remove lock so speed is set back to normal at login. + if( sd->ed ) { elemental_clean_effect(sd->ed); unit_remove_map(&sd->ed->bl,CLR_TELEPORT); } + if( hChSys.local && map[sd->bl.m].channel && idb_exists(map[sd->bl.m].channel->users, sd->status.char_id) ) { + clif->chsys_left(map[sd->bl.m].channel,sd); + } + + clif->chsys_quit(sd); + unit_remove_map_pc(sd,CLR_TELEPORT); - if( map[sd->bl.m].instance_id ) - { // Avoid map conflicts and warnings on next login + if( map[sd->bl.m].instance_id ) { // Avoid map conflicts and warnings on next login int16 m; struct point *pt; if( map[sd->bl.m].save.map ) @@ -1818,7 +1825,7 @@ struct map_session_data * map_nick2sd(const char *nick) iter = mapit_getallusers(); found_sd = NULL; - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if( battle_config.partial_name_scan ) {// partial name search @@ -1841,7 +1848,7 @@ struct map_session_data * map_nick2sd(const char *nick) break; } } - mapit_free(iter); + mapit->free(iter); if( battle_config.partial_name_scan && qty != 1 ) found_sd = NULL; @@ -1894,8 +1901,7 @@ struct mob_data * map_id2boss(int id) /// Applies func to all the players in the db. /// Stops iterating if func returns -1. -void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...) -{ +void map_map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...) { DBIterator* iter; struct map_session_data* sd; @@ -1916,7 +1922,7 @@ void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...) /// Applies func to all the mobs in the db. /// Stops iterating if func returns -1. -void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) +void map_map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) { DBIterator* iter; struct mob_data* md; @@ -1938,7 +1944,7 @@ void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...) /// Applies func to all the npcs in the db. /// Stops iterating if func returns -1. -void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) +void map_map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) { DBIterator* iter; struct block_list* bl; @@ -1964,7 +1970,7 @@ void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...) /// Applies func to everything in the db. /// Stops iteratin gif func returns -1. -void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) +void map_map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) { DBIterator* iter; struct block_list* bl; @@ -1986,7 +1992,7 @@ void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...) /// Applies func to everything in the db. /// Stops iterating if func returns -1. -void map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...) +void map_map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...) { DBIterator* iter; struct block_list* bl; @@ -2037,7 +2043,7 @@ struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types) { struct s_mapiterator* mapit; - CREATE(mapit, struct s_mapiterator, 1); + mapit = ers_alloc(map_iterator_ers, struct s_mapiterator); mapit->flags = flags; mapit->types = types; if( types == BL_PC ) mapit->dbi = db_iterator(pc_db); @@ -2054,7 +2060,7 @@ void mapit_free(struct s_mapiterator* mapit) nullpo_retv(mapit); dbi_destroy(mapit->dbi); - aFree(mapit); + ers_free(map_iterator_ers, mapit); } /// Returns the first block_list that matches the description. @@ -2308,7 +2314,7 @@ int16 map_mapindex2mapid(unsigned short mapindex) *------------------------------------------*/ int map_mapname2ipport(unsigned short name, uint32* ip, uint16* port) { - struct map_data_other_server *mdos=NULL; + struct map_data_other_server *mdos; mdos = (struct map_data_other_server*)uidb_get(map_db,(unsigned int)name); if(mdos==NULL || mdos->cell) //If gat isn't null, this is a local map. @@ -2633,7 +2639,7 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable map_setcell(m, x1, y1, CELL_WALKABLE, false); map_setcell(m, x1, y1, CELL_SHOOTABLE, shootable); - clif_changemapcell(0, m, x1, y1, map_getcell(m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); + clif->changemapcell(0, m, x1, y1, map_getcell(m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); } iwall->size = i; @@ -2644,8 +2650,7 @@ bool map_iwall_set(int16 m, int16 x, int16 y, int size, int8 dir, bool shootable return true; } -void map_iwall_get(struct map_session_data *sd) -{ +void map_iwall_get(struct map_session_data *sd) { struct iwall_data *iwall; DBIterator* iter; int16 x1, y1; @@ -2655,15 +2660,13 @@ void map_iwall_get(struct map_session_data *sd) return; iter = db_iterator(iwall_db); - for( iwall = dbi_first(iter); dbi_exists(iter); iwall = dbi_next(iter) ) - { + for( iwall = dbi_first(iter); dbi_exists(iter); iwall = dbi_next(iter) ) { if( iwall->m != sd->bl.m ) continue; - for( i = 0; i < iwall->size; i++ ) - { + for( i = 0; i < iwall->size; i++ ) { map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1); - clif_changemapcell(sd->fd, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), SELF); + clif->changemapcell(sd->fd, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), SELF); } } dbi_destroy(iter); @@ -2677,14 +2680,13 @@ void map_iwall_remove(const char *wall_name) if( (iwall = (struct iwall_data *)strdb_get(iwall_db, wall_name)) == NULL ) return; // Nothing to do - for( i = 0; i < iwall->size; i++ ) - { + for( i = 0; i < iwall->size; i++ ) { map_iwall_nextxy(iwall->x, iwall->y, iwall->dir, i, &x1, &y1); map_setcell(iwall->m, x1, y1, CELL_SHOOTABLE, true); map_setcell(iwall->m, x1, y1, CELL_WALKABLE, true); - clif_changemapcell(0, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); + clif->changemapcell(0, iwall->m, x1, y1, map_getcell(iwall->m, x1, y1, CELL_GETTYPE), ALL_SAMEMAP); } map[iwall->m].iwall_num--; @@ -2701,7 +2703,7 @@ static DBData create_map_data_other_server(DBKey key, va_list args) mdos=(struct map_data_other_server *)aCalloc(1,sizeof(struct map_data_other_server)); mdos->index = mapindex; memcpy(mdos->name, mapindex_id2name(mapindex), MAP_NAME_LENGTH); - return db_ptr2data(mdos); + return DB->ptr2data(mdos); } /*========================================== @@ -2709,13 +2711,13 @@ static DBData create_map_data_other_server(DBKey key, va_list args) *------------------------------------------*/ int map_setipport(unsigned short mapindex, uint32 ip, uint16 port) { - struct map_data_other_server *mdos=NULL; + struct map_data_other_server *mdos; mdos= uidb_ensure(map_db,(unsigned int)mapindex, create_map_data_other_server); if(mdos->cell) //Local map,Do nothing. Give priority to our own local maps over ones from another server. [Skotlex] return 0; - if(ip == clif_getip() && port == clif_getport()) { + if(ip == clif->map_ip && port == clif->map_port) { //That's odd, we received info that we are the ones with this map, but... we don't have it. ShowFatalError("map_setipport : received info that this map-server SHOULD have map '%s', but it is not loaded.\n",mapindex_id2name(mapindex)); exit(EXIT_FAILURE); @@ -2731,7 +2733,7 @@ int map_setipport(unsigned short mapindex, uint32 ip, uint16 port) */ int map_eraseallipport_sub(DBKey key, DBData *data, va_list va) { - struct map_data_other_server *mdos = db_data2ptr(data); + struct map_data_other_server *mdos = DB->data2ptr(data); if(mdos->cell == NULL) { db_remove(map_db,key); aFree(mdos); @@ -2892,27 +2894,186 @@ int map_delmap(char* mapname) } return 0; } +void map_zone_db_clear(void) { + struct map_zone_data *zone; + int i; + + DBIterator *iter = db_iterator(zone_db); + for(zone = dbi_first(iter); dbi_exists(iter); zone = dbi_next(iter)) { + for(i = 0; i < zone->disabled_skills_count; i++) { + aFree(zone->disabled_skills[i]); + } + aFree(zone->disabled_skills); + aFree(zone->disabled_items); + for(i = 0; i < zone->mapflags_count; i++) { + aFree(zone->mapflags[i]); + } + aFree(zone->mapflags); + for(i = 0; i < zone->disabled_commands_count; i++) { + aFree(zone->disabled_commands[i]); + } + aFree(zone->disabled_commands); + for(i = 0; i < zone->capped_skills_count; i++) { + aFree(zone->capped_skills[i]); + } + aFree(zone->capped_skills); + } + dbi_destroy(iter); + + db_destroy(zone_db);/* will aFree(zone) */ + + /* clear the pk zone stuff */ + for(i = 0; i < map_zone_pk.disabled_skills_count; i++) { + aFree(map_zone_pk.disabled_skills[i]); + } + aFree(map_zone_pk.disabled_skills); + aFree(map_zone_pk.disabled_items); + for(i = 0; i < map_zone_pk.mapflags_count; i++) { + aFree(map_zone_pk.mapflags[i]); + } + aFree(map_zone_pk.mapflags); + for(i = 0; i < map_zone_pk.disabled_commands_count; i++) { + aFree(map_zone_pk.disabled_commands[i]); + } + aFree(map_zone_pk.disabled_commands); + for(i = 0; i < map_zone_pk.capped_skills_count; i++) { + aFree(map_zone_pk.capped_skills[i]); + } + aFree(map_zone_pk.capped_skills); + /* clear the main zone stuff */ + for(i = 0; i < map_zone_all.disabled_skills_count; i++) { + aFree(map_zone_all.disabled_skills[i]); + } + aFree(map_zone_all.disabled_skills); + aFree(map_zone_all.disabled_items); + for(i = 0; i < map_zone_all.mapflags_count; i++) { + aFree(map_zone_all.mapflags[i]); + } + aFree(map_zone_all.mapflags); + for(i = 0; i < map_zone_all.disabled_commands_count; i++) { + aFree(map_zone_all.disabled_commands[i]); + } + aFree(map_zone_all.disabled_commands); + for(i = 0; i < map_zone_all.capped_skills_count; i++) { + aFree(map_zone_all.capped_skills[i]); + } + aFree(map_zone_all.capped_skills); +} + +void do_final_maps(void) { + int i, v = 0; + + for( i = 0; i < map_num; i++ ) { + + if(map[i].cell) aFree(map[i].cell); + if(map[i].block) aFree(map[i].block); + if(map[i].block_mob) aFree(map[i].block_mob); + + if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random] + int j; + if(map[i].mob_delete_timer != INVALID_TIMER) + delete_timer(map[i].mob_delete_timer, map_removemobs_timer); + for (j=0; j<MAX_MOB_LIST_PER_MAP; j++) + if (map[i].moblist[j]) aFree(map[i].moblist[j]); + } + if( map[i].unit_count ) { + for(v = 0; v < map[i].unit_count; v++) { + aFree(map[i].units[v]); + } + if( map[i].units ) { + aFree(map[i].units); + map[i].units = NULL; + } + map[i].unit_count = 0; + } + + if( map[i].skill_count ) { + for(v = 0; v < map[i].skill_count; v++) { + aFree(map[i].skills[v]); + } + if( map[i].skills ) { + aFree(map[i].skills); + map[i].skills = NULL; + } + map[i].skill_count = 0; + } + + if( map[i].zone_mf_count ) { + for(v = 0; v < map[i].zone_mf_count; v++) { + aFree(map[i].zone_mf[v]); + } + if( map[i].zone_mf ) { + aFree(map[i].zone_mf); + map[i].zone_mf = NULL; + } + map[i].zone_mf_count = 0; + } + + if( map[i].channel ) + clif->chsys_delete(map[i].channel); + } + + map_zone_db_clear(); + +} /// Initializes map flags and adjusts them depending on configuration. -void map_flags_init(void) -{ - int i; +void map_flags_init(void) { + int i, v = 0; - for( i = 0; i < map_num; i++ ) - { + for( i = 0; i < map_num; i++ ) { // mapflags memset(&map[i].flag, 0, sizeof(map[i].flag)); // additional mapflag data - map[i].zone = 0; // restricted mapflag zone map[i].nocommand = 0; // nocommand mapflag level map[i].bexp = 100; // per map base exp multiplicator map[i].jexp = 100; // per map job exp multiplicator memset(map[i].drop_list, 0, sizeof(map[i].drop_list)); // pvp nightmare drop list + if( map[i].unit_count ) { + for(v = 0; v < map[i].unit_count; v++) { + aFree(map[i].units[v]); + } + aFree(map[i].units); + } + map[i].units = NULL; + map[i].unit_count = 0; + + if( map[i].skill_count ) { + for(v = 0; v < map[i].skill_count; v++) { + aFree(map[i].skills[v]); + } + aFree(map[i].skills); + } + map[i].skills = NULL; + map[i].skill_count = 0; + // adjustments - if( battle_config.pk_mode ) + if( battle_config.pk_mode ) { map[i].flag.pvp = 1; // make all maps pvp for pk_mode [Valaris] + map[i].zone = &map_zone_pk; + } else /* align with 'All' zone */ + map[i].zone = &map_zone_all; + + if( map[i].zone_mf_count ) { + for(v = 0; v < map[i].zone_mf_count; v++) { + aFree(map[i].zone_mf[v]); + } + aFree(map[i].zone_mf); + } + + map[i].zone_mf = NULL; + map[i].zone_mf_count = 0; + map[i].prev_zone = map[i].zone; + + map[i].invincible_time_inc = 0; + + map[i].weapon_damage_rate = 100; + map[i].magic_damage_rate = 100; + map[i].misc_damage_rate = 100; + map[i].short_damage_rate = 100; + map[i].long_damage_rate = 100; } } @@ -3006,14 +3167,13 @@ void map_removemapdb(struct map_data *m) /*====================================== * Initiate maps loading stage *--------------------------------------*/ -int map_readallmaps (void) -{ +int map_readallmaps (void) { int i; FILE* fp=NULL; int maps_removed = 0; char *map_cache_buffer = NULL; // Has the uncompressed gat data of all maps, so just one allocation has to be made char map_cache_decode_buffer[MAX_MAP_SIZE]; - + if( enable_grf ) ShowStatus("Loading maps (using GRF files)...\n"); else { @@ -3106,84 +3266,6 @@ static int map_ip_set = 0; static int char_ip_set = 0; /*========================================== - * Console Command Parser [Wizputer] - *------------------------------------------*/ -int parse_console(const char* buf) -{ - char type[64]; - char command[64]; - char map[64]; - int16 x = 0; - int16 y = 0; - int16 m; - int n; - struct map_session_data sd; - - memset(&sd, 0, sizeof(struct map_session_data)); - strcpy(sd.status.name, "console"); - - if( ( n = sscanf(buf, "%63[^:]:%63[^:]:%63s %hd %hd[^\n]", type, command, map, &x, &y) ) < 5 ) - { - if( ( n = sscanf(buf, "%63[^:]:%63[^\n]", type, command) ) < 2 ) - { - n = sscanf(buf, "%63[^\n]", type); - } - } - - if( n == 5 ) - { - m = map_mapname2mapid(map); - if( m < 0 ) - { - ShowWarning("Console: Unknown map.\n"); - return 0; - } - sd.bl.m = m; - map_search_freecell(&sd.bl, m, &sd.bl.x, &sd.bl.y, -1, -1, 0); - if( x > 0 ) - sd.bl.x = x; - if( y > 0 ) - sd.bl.y = y; - } - else - { - map[0] = '\0'; - if( n < 2 ) - command[0] = '\0'; - if( n < 1 ) - type[0] = '\0'; - } - - ShowNotice("Type of command: '%s' || Command: '%s' || Map: '%s' Coords: %d %d\n", type, command, map, x, y); - - if( n == 5 && strcmpi("admin",type) == 0 ) - { - if( !is_atcommand(sd.fd, &sd, command, 0) ) - ShowInfo("Console: not atcommand\n"); - } - else if( n == 2 && strcmpi("server", type) == 0 ) - { - if( strcmpi("shutdown", command) == 0 || strcmpi("exit", command) == 0 || strcmpi("quit", command) == 0 ) - { - runflag = 0; - } - } - else if( strcmpi("help", type) == 0 ) - { - ShowInfo("To use GM commands:\n"); - ShowInfo(" admin:<gm command>:<map of \"gm\"> <x> <y>\n"); - ShowInfo("You can use any GM command that doesn't require the GM.\n"); - ShowInfo("No using @item or @warp however you can use @charwarp\n"); - ShowInfo("The <map of \"gm\"> <x> <y> is for commands that need coords of the GM\n"); - ShowInfo("IE: @spawn\n"); - ShowInfo("To shutdown the server:\n"); - ShowInfo(" server:shutdown\n"); - } - - return 0; -} - -/*========================================== * Read map server configuration files (conf/map_server.conf...) *------------------------------------------*/ int map_config_read(char *cfgName) @@ -3216,7 +3298,7 @@ int map_config_read(char *cfgName) *ptr = '\0'; if(strcmpi(w1,"timestamp_format")==0) - strncpy(timestamp_format, w2, 20); + safestrncpy(timestamp_format, w2, 20); else if(strcmpi(w1,"stdout_with_ansisequence")==0) stdout_with_ansisequence = config_switch(w2); else if(strcmpi(w1,"console_silent")==0) { @@ -3232,11 +3314,11 @@ int map_config_read(char *cfgName) else if (strcmpi(w1, "char_port") == 0) chrif_setport(atoi(w2)); else if (strcmpi(w1, "map_ip") == 0) - map_ip_set = clif_setip(w2); + map_ip_set = clif->setip(w2); else if (strcmpi(w1, "bind_ip") == 0) - clif_setbindip(w2); + clif->setbindip(w2); else if (strcmpi(w1, "map_port") == 0) { - clif_setport(atoi(w2)); + clif->setport(atoi(w2)); map_port = (atoi(w2)); } else if (strcmpi(w1, "map") == 0) map_addmap(w2); @@ -3267,12 +3349,8 @@ int map_config_read(char *cfgName) else if (strcmpi(w1, "charhelp_txt") == 0) strcpy(charhelp_txt, w2); else if(strcmpi(w1,"db_path") == 0) - strncpy(db_path,w2,255); - else if (strcmpi(w1, "console") == 0) { - console = config_switch(w2); - if (console) - ShowNotice("Console Commands are enabled.\n"); - } else if (strcmpi(w1, "enable_spy") == 0) + safestrncpy(db_path,w2,255); + else if (strcmpi(w1, "enable_spy") == 0) enable_spy = config_switch(w2); else if (strcmpi(w1, "use_grf") == 0) enable_grf = config_switch(w2); @@ -3357,9 +3435,6 @@ int inter_config_read(char *cfgName) if( sscanf(line,"%[^:]: %[^\r\n]",w1,w2) < 2 ) continue; - if(strcmpi(w1, "main_chat_nick")==0) - safestrncpy(main_chat_nick, w2, sizeof(main_chat_nick)); - else if(strcmpi(w1,"item_db_db")==0) strcpy(item_db_db,w2); else @@ -3431,15 +3506,15 @@ int inter_config_read(char *cfgName) int map_sql_init(void) { // main db connection - mmysql_handle = Sql_Malloc(); + mmysql_handle = SQL->Malloc(); ShowInfo("Connecting to the Map DB Server....\n"); - if( SQL_ERROR == Sql_Connect(mmysql_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) ) + if( SQL_ERROR == SQL->Connect(mmysql_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) ) exit(EXIT_FAILURE); ShowStatus("connect success! (Map Server Connection)\n"); if( strlen(default_codepage) > 0 ) - if ( SQL_ERROR == Sql_SetEncoding(mmysql_handle, default_codepage) ) + if ( SQL_ERROR == SQL->SetEncoding(mmysql_handle, default_codepage) ) Sql_ShowDebug(mmysql_handle); return 0; @@ -3448,43 +3523,1338 @@ int map_sql_init(void) int map_sql_close(void) { ShowStatus("Close Map DB Connection....\n"); - Sql_Free(mmysql_handle); + SQL->Free(mmysql_handle); mmysql_handle = NULL; -#ifndef BETA_THREAD_TEST - if (log_config.sql_logs) - { + if (logs->config.sql_logs) { ShowStatus("Close Log DB Connection....\n"); - Sql_Free(logmysql_handle); + SQL->Free(logmysql_handle); logmysql_handle = NULL; } -#endif return 0; } int log_sql_init(void) { -#ifndef BETA_THREAD_TEST // log db connection - logmysql_handle = Sql_Malloc(); + logmysql_handle = SQL->Malloc(); ShowInfo(""CL_WHITE"[SQL]"CL_RESET": Connecting to the Log Database "CL_WHITE"%s"CL_RESET" At "CL_WHITE"%s"CL_RESET"...\n",log_db_db,log_db_ip); - if ( SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) ) + if ( SQL_ERROR == SQL->Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) ) exit(EXIT_FAILURE); ShowStatus(""CL_WHITE"[SQL]"CL_RESET": Successfully '"CL_GREEN"connected"CL_RESET"' to Database '"CL_WHITE"%s"CL_RESET"'.\n", log_db_db); if( strlen(default_codepage) > 0 ) - if ( SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage) ) + if ( SQL_ERROR == SQL->SetEncoding(logmysql_handle, default_codepage) ) Sql_ShowDebug(logmysql_handle); -#endif return 0; } +void map_zone_change2(int m, struct map_zone_data *zone) { + char empty[1] = "\0"; + + map[m].prev_zone = map[m].zone; + + if( map[m].zone_mf_count ) + map_zone_remove(m); + + map_zone_apply(m,zone,empty,empty,empty); +} +/* when changing from a mapflag to another during runtime */ +void map_zone_change(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) { + map[m].prev_zone = map[m].zone; + + if( map[m].zone_mf_count ) + map_zone_remove(m); + map_zone_apply(m,zone,start,buffer,filepath); +} +/* removes previous mapflags from this map */ +void map_zone_remove(int m) { + char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH]; + unsigned short k; + char empty[1] = "\0"; + for(k = 0; k < map[m].zone_mf_count; k++) { + int len = strlen(map[m].zone_mf[k]),j; + params[0] = '\0'; + memcpy(flag, map[m].zone_mf[k], MAP_ZONE_MAPFLAG_LENGTH); + for(j = 0; j < len; j++) { + if( flag[j] == '\t' ) { + memcpy(params, &flag[j+1], len - j); + flag[j] = '\0'; + break; + } + } + + npc_parse_mapflag(map[m].name,empty,flag,params,empty,empty,empty); + aFree(map[m].zone_mf[k]); + map[m].zone_mf[k] = NULL; + } + + aFree(map[m].zone_mf); + map[m].zone_mf = NULL; + map[m].zone_mf_count = 0; +} +static inline void map_zone_mf_cache_add(int m, char *rflag) { + RECREATE(map[m].zone_mf, char *, ++map[m].zone_mf_count); + CREATE(map[m].zone_mf[map[m].zone_mf_count - 1], char, MAP_ZONE_MAPFLAG_LENGTH); + safestrncpy(map[m].zone_mf[map[m].zone_mf_count - 1], rflag, MAP_ZONE_MAPFLAG_LENGTH); +} +/* TODO: introduce enumerations to each mapflag so instead of reading the string a number of times we read it only once and use its value wherever we need */ +/* cache previous values to revert */ +bool map_zone_mf_cache(int m, char *flag, char *params) { + char rflag[MAP_ZONE_MAPFLAG_LENGTH]; + int state = 1; + + if (params[0] != '\0' && !strcmpi(params, "off")) + state = 0; + + if (!strcmpi(flag, "nosave")) { + ;/* not yet supported to be reversed */ + /* + char savemap[32]; + int savex, savey; + if (state == 0) { + if( map[m].flag.nosave ) { + sprintf(rflag, "nosave SavePoint"); + map_zone_mf_cache_add(m,nosave); + } + } else if (!strcmpi(params, "SavePoint")) { + if( map[m].save.map ) { + sprintf(rflag, "nosave %s,%d,%d",mapindex_id2name(map[m].save.map),map[m].save.x,map[m].save.y); + } else + sprintf(rflag, "nosave %s,%d,%d",mapindex_id2name(map[m].save.map),map[m].save.x,map[m].save.y); + map_zone_mf_cache_add(m,nosave); + } else if (sscanf(params, "%31[^,],%d,%d", savemap, &savex, &savey) == 3) { + if( map[m].save.map ) { + sprintf(rflag, "nosave %s,%d,%d",mapindex_id2name(map[m].save.map),map[m].save.x,map[m].save.y); + map_zone_mf_cache_add(m,nosave); + } + }*/ + } else if (!strcmpi(flag,"autotrade")) { + if( state && map[m].flag.autotrade ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"autotrade off"); + else if( !map[m].flag.autotrade ) + map_zone_mf_cache_add(m,"autotrade"); + } + } else if (!strcmpi(flag,"allowks")) { + if( state && map[m].flag.allowks ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"allowks off"); + else if( !map[m].flag.allowks ) + map_zone_mf_cache_add(m,"allowks"); + } + } else if (!strcmpi(flag,"town")) { + if( state && map[m].flag.town ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"town off"); + else if( !map[m].flag.town ) + map_zone_mf_cache_add(m,"town"); + } + } else if (!strcmpi(flag,"nomemo")) { + if( state && map[m].flag.nomemo ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nomemo off"); + else if( !map[m].flag.nomemo ) + map_zone_mf_cache_add(m,"nomemo"); + } + } else if (!strcmpi(flag,"noteleport")) { + if( state && map[m].flag.noteleport ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noteleport off"); + else if( !map[m].flag.noteleport ) + map_zone_mf_cache_add(m,"noteleport"); + } + } else if (!strcmpi(flag,"nowarp")) { + if( state && map[m].flag.nowarp ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nowarp off"); + else if( !map[m].flag.nowarp ) + map_zone_mf_cache_add(m,"nowarp"); + } + } else if (!strcmpi(flag,"nowarpto")) { + if( state && map[m].flag.nowarpto ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nowarpto off"); + else if( !map[m].flag.nowarpto ) + map_zone_mf_cache_add(m,"nowarpto"); + } + } else if (!strcmpi(flag,"noreturn")) { + if( state && map[m].flag.noreturn ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noreturn off"); + else if( map[m].flag.noreturn ) + map_zone_mf_cache_add(m,"noreturn"); + } + } else if (!strcmpi(flag,"monster_noteleport")) { + if( state && map[m].flag.monster_noteleport ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"monster_noteleport off"); + else if( map[m].flag.monster_noteleport ) + map_zone_mf_cache_add(m,"monster_noteleport"); + } + } else if (!strcmpi(flag,"nobranch")) { + if( state && map[m].flag.nobranch ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nobranch off"); + else if( map[m].flag.nobranch ) + map_zone_mf_cache_add(m,"nobranch"); + } + } else if (!strcmpi(flag,"nopenalty")) { + if( state && map[m].flag.noexppenalty ) /* they are applied together, no need to check both */ + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nopenalty off"); + else if( map[m].flag.noexppenalty ) + map_zone_mf_cache_add(m,"nopenalty"); + } + } else if (!strcmpi(flag,"pvp")) { + if( state && map[m].flag.pvp ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"pvp off"); + else if( map[m].flag.pvp ) + map_zone_mf_cache_add(m,"pvp"); + } + } + else if (!strcmpi(flag,"pvp_noparty")) { + if( state && map[m].flag.pvp_noparty ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"pvp_noparty off"); + else if( map[m].flag.pvp_noparty ) + map_zone_mf_cache_add(m,"pvp_noparty"); + } + } else if (!strcmpi(flag,"pvp_noguild")) { + if( state && map[m].flag.pvp_noguild ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"pvp_noguild off"); + else if( map[m].flag.pvp_noguild ) + map_zone_mf_cache_add(m,"pvp_noguild"); + } + } else if (!strcmpi(flag, "pvp_nightmaredrop")) { + if( state && map[m].flag.pvp_nightmaredrop ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"pvp_nightmaredrop off"); + else if( map[m].flag.pvp_nightmaredrop ) + map_zone_mf_cache_add(m,"pvp_nightmaredrop"); + } + /* not yet fully supported */ + /*char drop_arg1[16], drop_arg2[16]; + int drop_per = 0; + if (sscanf(w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) { + int drop_id = 0, drop_type = 0; + if (!strcmpi(drop_arg1, "random")) + drop_id = -1; + else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL) + drop_id = 0; + if (!strcmpi(drop_arg2, "inventory")) + drop_type = 1; + else if (!strcmpi(drop_arg2,"equip")) + drop_type = 2; + else if (!strcmpi(drop_arg2,"all")) + drop_type = 3; + + if (drop_id != 0){ + int i; + for (i = 0; i < MAX_DROP_PER_MAP; i++) { + if (map[m].drop_list[i].drop_id == 0){ + map[m].drop_list[i].drop_id = drop_id; + map[m].drop_list[i].drop_type = drop_type; + map[m].drop_list[i].drop_per = drop_per; + break; + } + } + map[m].flag.pvp_nightmaredrop = 1; + } + } else if (!state) //Disable + map[m].flag.pvp_nightmaredrop = 0; + */ + } else if (!strcmpi(flag,"pvp_nocalcrank")) { + if( state && map[m].flag.pvp_nocalcrank ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"pvp_nocalcrank off"); + else if( map[m].flag.pvp_nocalcrank ) + map_zone_mf_cache_add(m,"pvp_nocalcrank"); + } + } else if (!strcmpi(flag,"gvg")) { + if( state && map[m].flag.gvg ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"gvg off"); + else if( map[m].flag.gvg ) + map_zone_mf_cache_add(m,"gvg"); + } + } else if (!strcmpi(flag,"gvg_noparty")) { + if( state && map[m].flag.gvg_noparty ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"gvg_noparty off"); + else if( map[m].flag.gvg_noparty ) + map_zone_mf_cache_add(m,"gvg_noparty"); + } + } else if (!strcmpi(flag,"gvg_dungeon")) { + if( state && map[m].flag.gvg_dungeon ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"gvg_dungeon off"); + else if( map[m].flag.gvg_dungeon ) + map_zone_mf_cache_add(m,"gvg_dungeon"); + } + } + else if (!strcmpi(flag,"gvg_castle")) { + if( state && map[m].flag.gvg_castle ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"gvg_castle off"); + else if( map[m].flag.gvg_castle ) + map_zone_mf_cache_add(m,"gvg_castle"); + } + } + else if (!strcmpi(flag,"battleground")) { + if( state && map[m].flag.battleground ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"battleground off"); + else if( map[m].flag.battleground ) + map_zone_mf_cache_add(m,"battleground"); + } + } else if (!strcmpi(flag,"noexppenalty")) { + if( state && map[m].flag.noexppenalty ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noexppenalty off"); + else if( map[m].flag.noexppenalty ) + map_zone_mf_cache_add(m,"noexppenalty"); + } + } else if (!strcmpi(flag,"nozenypenalty")) { + if( state && map[m].flag.nozenypenalty ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nozenypenalty off"); + else if( map[m].flag.nozenypenalty ) + map_zone_mf_cache_add(m,"nozenypenalty"); + } + } else if (!strcmpi(flag,"notrade")) { + if( state && map[m].flag.notrade ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"notrade off"); + else if( map[m].flag.notrade ) + map_zone_mf_cache_add(m,"notrade"); + } + } else if (!strcmpi(flag,"novending")) { + if( state && map[m].flag.novending ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"novending off"); + else if( map[m].flag.novending ) + map_zone_mf_cache_add(m,"novending"); + } + } else if (!strcmpi(flag,"nodrop")) { + if( state && map[m].flag.nodrop ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nodrop off"); + else if( map[m].flag.nodrop ) + map_zone_mf_cache_add(m,"nodrop"); + } + } else if (!strcmpi(flag,"noskill")) { + if( state && map[m].flag.noskill ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noskill off"); + else if( map[m].flag.noskill ) + map_zone_mf_cache_add(m,"noskill"); + } + } else if (!strcmpi(flag,"noicewall")) { + if( state && map[m].flag.noicewall ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noicewall off"); + else if( map[m].flag.noicewall ) + map_zone_mf_cache_add(m,"noicewall"); + } + } else if (!strcmpi(flag,"snow")) { + if( state && map[m].flag.snow ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"snow off"); + else if( map[m].flag.snow ) + map_zone_mf_cache_add(m,"snow"); + } + } else if (!strcmpi(flag,"clouds")) { + if( state && map[m].flag.clouds ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"clouds off"); + else if( map[m].flag.clouds ) + map_zone_mf_cache_add(m,"clouds"); + } + } else if (!strcmpi(flag,"clouds2")) { + if( state && map[m].flag.clouds2 ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"clouds2 off"); + else if( map[m].flag.clouds2 ) + map_zone_mf_cache_add(m,"clouds2"); + } + } else if (!strcmpi(flag,"fog")) { + if( state && map[m].flag.fog ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"fog off"); + else if( map[m].flag.fog ) + map_zone_mf_cache_add(m,"fog"); + } + } else if (!strcmpi(flag,"fireworks")) { + if( state && map[m].flag.fireworks ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"fireworks off"); + else if( map[m].flag.fireworks ) + map_zone_mf_cache_add(m,"fireworks"); + } + } else if (!strcmpi(flag,"sakura")) { + if( state && map[m].flag.sakura ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"sakura off"); + else if( map[m].flag.sakura ) + map_zone_mf_cache_add(m,"sakura"); + } + } else if (!strcmpi(flag,"leaves")) { + if( state && map[m].flag.leaves ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"leaves off"); + else if( map[m].flag.leaves ) + map_zone_mf_cache_add(m,"leaves"); + } + } else if (!strcmpi(flag,"nightenabled")) { + if( state && map[m].flag.nightenabled ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nightenabled off"); + else if( map[m].flag.nightenabled ) + map_zone_mf_cache_add(m,"nightenabled"); + } + } else if (!strcmpi(flag,"noexp")) { + if( state && map[m].flag.nobaseexp ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noexp off"); + else if( map[m].flag.nobaseexp ) + map_zone_mf_cache_add(m,"noexp"); + } + } + else if (!strcmpi(flag,"nobaseexp")) { + if( state && map[m].flag.nobaseexp ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nobaseexp off"); + else if( map[m].flag.nobaseexp ) + map_zone_mf_cache_add(m,"nobaseexp"); + } + } else if (!strcmpi(flag,"nojobexp")) { + if( state && map[m].flag.nojobexp ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nojobexp off"); + else if( map[m].flag.nojobexp ) + map_zone_mf_cache_add(m,"nojobexp"); + } + } else if (!strcmpi(flag,"noloot")) { + if( state && map[m].flag.nomobloot ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noloot off"); + else if( map[m].flag.nomobloot ) + map_zone_mf_cache_add(m,"noloot"); + } + } else if (!strcmpi(flag,"nomobloot")) { + if( state && map[m].flag.nomobloot ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nomobloot off"); + else if( map[m].flag.nomobloot ) + map_zone_mf_cache_add(m,"nomobloot"); + } + } else if (!strcmpi(flag,"nomvploot")) { + if( state && map[m].flag.nomvploot ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nomvploot off"); + else if( map[m].flag.nomvploot ) + map_zone_mf_cache_add(m,"nomvploot"); + } + } else if (!strcmpi(flag,"nocommand")) { + /* implementation may be incomplete */ + if( state && sscanf(params, "%d", &state) == 1 ) { + sprintf(rflag, "nocommand %s",params); + map_zone_mf_cache_add(m,rflag); + } else if( !state && map[m].nocommand ) { + sprintf(rflag, "nocommand %d",map[m].nocommand); + map_zone_mf_cache_add(m,rflag); + } else if( map[m].nocommand ) { + map_zone_mf_cache_add(m,"nocommand off"); + } + } else if (!strcmpi(flag,"jexp")) { + if( !state ) { + if( map[m].jexp != 100 ) { + sprintf(rflag,"jexp %d",map[m].jexp); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].jexp ) { + sprintf(rflag,"jexp %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } else if (!strcmpi(flag,"bexp")) { + if( !state ) { + if( map[m].bexp != 100 ) { + sprintf(rflag,"bexp %d",map[m].jexp); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].bexp ) { + sprintf(rflag,"bexp %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } else if (!strcmpi(flag,"loadevent")) { + if( state && map[m].flag.loadevent ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"loadevent off"); + else if( map[m].flag.loadevent ) + map_zone_mf_cache_add(m,"loadevent"); + } + } else if (!strcmpi(flag,"nochat")) { + if( state && map[m].flag.nochat ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nochat off"); + else if( map[m].flag.nochat ) + map_zone_mf_cache_add(m,"nochat"); + } + } else if (!strcmpi(flag,"partylock")) { + if( state && map[m].flag.partylock ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"partylock off"); + else if( map[m].flag.partylock ) + map_zone_mf_cache_add(m,"partylock"); + } + } else if (!strcmpi(flag,"guildlock")) { + if( state && map[m].flag.guildlock ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"guildlock off"); + else if( map[m].flag.guildlock ) + map_zone_mf_cache_add(m,"guildlock"); + } + } else if (!strcmpi(flag,"reset")) { + if( state && map[m].flag.reset ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"reset off"); + else if( map[m].flag.reset ) + map_zone_mf_cache_add(m,"reset"); + } + } else if (!strcmpi(flag,"adjust_unit_duration")) { + int skill_id, k; + char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH]; + int len = strlen(params); + + modifier[0] = '\0'; + memcpy(skill_name, params, MAP_ZONE_MAPFLAG_LENGTH); + + for(k = 0; k < len; k++) { + if( skill_name[k] == '\t' ) { + memcpy(modifier, &skill_name[k+1], len - k); + skill_name[k] = '\0'; + break; + } + } + + if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { + ;/* we dont mind it, the server will take care of it next. */ + } else { + int idx = map[m].unit_count; + + k = 0; + ARR_FIND(0, idx, k, map[m].units[k]->skill_id == skill_id); + + if( k < idx ) { + if( atoi(modifier) != map[m].units[k]->modifier ) { + sprintf(rflag,"adjust_unit_duration %s %d",skill_name,map[m].units[k]->modifier); + map_zone_mf_cache_add(m,rflag); + } + } else { + sprintf(rflag,"adjust_unit_duration %s 100",skill_name); + map_zone_mf_cache_add(m,rflag); + } + } + } else if (!strcmpi(flag,"adjust_skill_damage")) { + int skill_id, k; + char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH]; + int len = strlen(params); + + modifier[0] = '\0'; + memcpy(skill_name, params, MAP_ZONE_MAPFLAG_LENGTH); + + for(k = 0; k < len; k++) { + if( skill_name[k] == '\t' ) { + memcpy(modifier, &skill_name[k+1], len - k); + skill_name[k] = '\0'; + break; + } + } + + if( modifier[0] == '\0' || !( skill_id = skill->name2id(skill_name) ) || atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { + ;/* we dont mind it, the server will take care of it next. */ + } else { + int idx = map[m].skill_count; + + k = 0; + ARR_FIND(0, idx, k, map[m].skills[k]->skill_id == skill_id); + + if( k < idx ) { + if( atoi(modifier) != map[m].skills[k]->modifier ) { + sprintf(rflag,"adjust_skill_damage %s %d",skill_name,map[m].skills[k]->modifier); + map_zone_mf_cache_add(m,rflag); + } + } else { + sprintf(rflag,"adjust_skill_damage %s 100",skill_name); + map_zone_mf_cache_add(m,rflag); + } + + } + } else if (!strcmpi(flag,"zone")) { + ShowWarning("You can't add a zone through a zone! ERROR, skipping for '%s'...\n",map[m].name); + return true; + } else if ( !strcmpi(flag,"nomapchannelautojoin") ) { + if( state && map[m].flag.chsysnolocalaj ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"nomapchannelautojoin off"); + else if( map[m].flag.chsysnolocalaj ) + map_zone_mf_cache_add(m,"nomapchannelautojoin"); + } + } else if ( !strcmpi(flag,"invincible_time_inc") ) { + if( !state ) { + if( map[m].invincible_time_inc != 0 ) { + sprintf(rflag,"invincible_time_inc %d",map[m].invincible_time_inc); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].invincible_time_inc ) { + sprintf(rflag,"invincible_time_inc %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } else if ( !strcmpi(flag,"noknockback") ) { + if( state && map[m].flag.noknockback ) + ;/* nothing to do */ + else { + if( state ) + map_zone_mf_cache_add(m,"noknockback off"); + else if( map[m].flag.noknockback ) + map_zone_mf_cache_add(m,"noknockback"); + } + } else if ( !strcmpi(flag,"weapon_damage_rate") ) { + if( !state ) { + if( map[m].weapon_damage_rate != 100 ) { + sprintf(rflag,"weapon_damage_rate %d",map[m].weapon_damage_rate); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].weapon_damage_rate ) { + sprintf(rflag,"weapon_damage_rate %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } else if ( !strcmpi(flag,"magic_damage_rate") ) { + if( !state ) { + if( map[m].magic_damage_rate != 100 ) { + sprintf(rflag,"magic_damage_rate %d",map[m].magic_damage_rate); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].magic_damage_rate ) { + sprintf(rflag,"magic_damage_rate %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } else if ( !strcmpi(flag,"misc_damage_rate") ) { + if( !state ) { + if( map[m].misc_damage_rate != 100 ) { + sprintf(rflag,"misc_damage_rate %d",map[m].misc_damage_rate); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].misc_damage_rate ) { + sprintf(rflag,"misc_damage_rate %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } else if ( !strcmpi(flag,"short_damage_rate") ) { + if( !state ) { + if( map[m].short_damage_rate != 100 ) { + sprintf(rflag,"short_damage_rate %d",map[m].short_damage_rate); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].short_damage_rate ) { + sprintf(rflag,"short_damage_rate %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } else if ( !strcmpi(flag,"long_damage_rate") ) { + if( !state ) { + if( map[m].long_damage_rate != 100 ) { + sprintf(rflag,"long_damage_rate %d",map[m].long_damage_rate); + map_zone_mf_cache_add(m,rflag); + } + } if( sscanf(params, "%d", &state) == 1 ) { + if( state != map[m].long_damage_rate ) { + sprintf(rflag,"long_damage_rate %s",params); + map_zone_mf_cache_add(m,rflag); + } + } + } + return false; +} +void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath) { + int i; + char empty[1] = "\0"; + char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH]; + map[m].zone = zone; + for(i = 0; i < zone->mapflags_count; i++) { + int len = strlen(zone->mapflags[i]); + int k; + params[0] = '\0'; + memcpy(flag, zone->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); + for(k = 0; k < len; k++) { + if( flag[k] == '\t' ) { + memcpy(params, &flag[k+1], len - k); + flag[k] = '\0'; + break; + } + } + + if( map_zone_mf_cache(m,flag,params) ) + continue; + + npc_parse_mapflag(map[m].name,empty,flag,params,start,buffer,filepath); + } +} +/* used on npc load and reload to apply all "Normal" and "PK Mode" zones */ +void map_zone_init(void) { + char flag[MAP_ZONE_MAPFLAG_LENGTH], params[MAP_ZONE_MAPFLAG_LENGTH]; + struct map_zone_data *zone; + char empty[1] = "\0"; + int i,k,j; + + zone = &map_zone_all; + + for(i = 0; i < zone->mapflags_count; i++) { + int len = strlen(zone->mapflags[i]); + params[0] = '\0'; + memcpy(flag, zone->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); + for(k = 0; k < len; k++) { + if( flag[k] == '\t' ) { + memcpy(params, &flag[k+1], len - k); + flag[k] = '\0'; + break; + } + } + + for(j = 0; j < map_num; j++) { + if( map[j].zone == zone ) { + if( map_zone_mf_cache(j,flag,params) ) + break; + npc_parse_mapflag(map[j].name,empty,flag,params,empty,empty,empty); + } + } + } + + if( battle_config.pk_mode ) { + zone = &map_zone_pk; + for(i = 0; i < zone->mapflags_count; i++) { + int len = strlen(zone->mapflags[i]); + params[0] = '\0'; + memcpy(flag, zone->mapflags[i], MAP_ZONE_MAPFLAG_LENGTH); + for(k = 0; k < len; k++) { + if( flag[k] == '\t' ) { + memcpy(params, &flag[k+1], len - k); + flag[k] = '\0'; + break; + } + } + for(j = 0; j < map_num; j++) { + if( map[j].zone == zone ) { + if( map_zone_mf_cache(j,flag,params) ) + break; + npc_parse_mapflag(map[j].name,empty,flag,params,empty,empty,empty); + } + } + } + } + +} +unsigned short map_zone_str2itemid(const char *name) { + struct item_data *data; + + if( !name ) + return 0; + if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) { + if( !( data = itemdb_exists(atoi(name+2))) ) { + return 0; + } + } else { + if( !( data = itemdb_searchname(name) ) ) { + return 0; + } + } + return data->nameid; +} +unsigned short map_zone_str2skillid(const char *name) { + unsigned short nameid = 0; + + if( !name ) + return 0; + + if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) { + if( !skill->get_index((nameid = atoi(name+2))) ) + return 0; + } else { + if( !( nameid = strdb_iget(skilldb_name2id, name) ) ) { + return 0; + } + } + return nameid; +} +enum bl_type map_zone_bl_type(const char *entry, enum map_zone_skill_subtype *subtype) { + char temp[200], *parse; + enum bl_type bl = BL_NUL; + *subtype = MZS_NONE; + + if( !entry ) + return BL_NUL; + + safestrncpy(temp, entry, 200); + + parse = strtok(temp,"|"); + + while (parse != NULL) { + normalize_name(parse," "); + if( strcmpi(parse,"player") == 0 ) + bl |= BL_PC; + else if( strcmpi(parse,"homun") == 0 ) + bl |= BL_HOM; + else if( strcmpi(parse,"mercenary") == 0 ) + bl |= BL_MER; + else if( strcmpi(parse,"monster") == 0 ) + bl |= BL_MOB; + else if( strcmpi(parse,"clone") == 0 ) { + bl |= BL_MOB; + *subtype |= MZS_CLONE; + } else if( strcmpi(parse,"mob_boss") == 0 ) { + bl |= BL_MOB; + *subtype |= MZS_BOSS; + } else if( strcmpi(parse,"elemental") == 0 ) + bl |= BL_ELEM; + else if( strcmpi(parse,"pet") == 0 ) + bl |= BL_PET; + else if( strcmpi(parse,"all") == 0 ) { + bl |= BL_ALL; + *subtype |= MZS_ALL; + } else if( strcmpi(parse,"none") == 0 ) { + bl = BL_NUL; + } else { + ShowError("map_zone_db: '%s' unknown type, skipping...\n",parse); + } + parse = strtok(NULL,"|"); + } + return bl; +} +/* [Ind/Hercules] */ +void read_map_zone_db(void) { + config_t map_zone_db; + config_setting_t *zones = NULL; + /* TODO: #ifndef required for re/pre-re */ +#ifdef RENEWAL + const char *config_filename = "db/re/map_zone_db.conf"; // FIXME hardcoded name +#else + const char *config_filename = "db/pre-re/map_zone_db.conf"; // FIXME hardcoded name +#endif + if (conf_read_file(&map_zone_db, config_filename)) + return; + + zones = config_lookup(&map_zone_db, "zones"); + + if (zones != NULL) { + struct map_zone_data *zone; + config_setting_t *zone_e; + config_setting_t *skills; + config_setting_t *items; + config_setting_t *mapflags; + config_setting_t *commands; + config_setting_t *caps; + const char *name; + const char *zonename; + int i,h,v; + int zone_count = 0, disabled_skills_count = 0, disabled_items_count = 0, mapflags_count = 0, + disabled_commands_count = 0, capped_skills_count = 0; + enum map_zone_skill_subtype subtype; + + zone_count = config_setting_length(zones); + for (i = 0; i < zone_count; ++i) { + bool is_all = false; + + zone_e = config_setting_get_elem(zones, i); + + if (!config_setting_lookup_string(zone_e, "name", &zonename)) { + ShowError("map_zone_db: missing zone name, skipping... (%s:%d)\n", + config_setting_source_file(zone_e), config_setting_source_line(zone_e)); + config_setting_remove_elem(zones,i);/* remove from the tree */ + --zone_count; + --i; + continue; + } + + if( strdb_exists(zone_db, zonename) ) { + ShowError("map_zone_db: duplicate zone name '%s', skipping...\n",zonename); + config_setting_remove_elem(zones,i);/* remove from the tree */ + --zone_count; + --i; + continue; + } + + /* is this the global template? */ + if( strncmpi(zonename,MAP_ZONE_NORMAL_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) { + zone = &map_zone_all; + is_all = true; + } else if( strncmpi(zonename,MAP_ZONE_PK_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) { + zone = &map_zone_pk; + is_all = true; + } else { + CREATE( zone, struct map_zone_data, 1 ); + zone->disabled_skills_count = 0; + zone->disabled_items_count = 0; + } + safestrncpy(zone->name, zonename, MAP_ZONE_NAME_LENGTH); + + if( (skills = config_setting_get_member(zone_e, "disabled_skills")) != NULL ) { + disabled_skills_count = config_setting_length(skills); + /* validate */ + for(h = 0; h < config_setting_length(skills); h++) { + config_setting_t *skill = config_setting_get_elem(skills, h); + name = config_setting_name(skill); + if( !map_zone_str2skillid(name) ) { + ShowError("map_zone_db: unknown skill (%s) in disabled_skills for zone '%s', skipping skill...\n",name,zone->name); + config_setting_remove_elem(skills,h); + --disabled_skills_count; + --h; + continue; + } + if( !map_zone_bl_type(config_setting_get_string_elem(skills,h),&subtype) )/* we dont remove it from the three due to inheritance */ + --disabled_skills_count; + } + /* all ok, process */ + CREATE( zone->disabled_skills, struct map_zone_disabled_skill_entry *, disabled_skills_count ); + for(h = 0, v = 0; h < config_setting_length(skills); h++) { + config_setting_t *skill = config_setting_get_elem(skills, h); + struct map_zone_disabled_skill_entry * entry; + enum bl_type type; + name = config_setting_name(skill); + + if( (type = map_zone_bl_type(config_setting_get_string_elem(skills,h),&subtype)) ) { /* only add if enabled */ + CREATE( entry, struct map_zone_disabled_skill_entry, 1 ); + + entry->nameid = map_zone_str2skillid(name); + entry->type = type; + entry->subtype = subtype; + + zone->disabled_skills[v++] = entry; + } + + } + zone->disabled_skills_count = disabled_skills_count; + } + + if( (items = config_setting_get_member(zone_e, "disabled_items")) != NULL ) { + disabled_items_count = config_setting_length(items); + /* validate */ + for(h = 0; h < config_setting_length(items); h++) { + config_setting_t *item = config_setting_get_elem(items, h); + name = config_setting_name(item); + if( !map_zone_str2itemid(name) ) { + ShowError("map_zone_db: unknown item (%s) in disabled_items for zone '%s', skipping item...\n",name,zone->name); + config_setting_remove_elem(items,h); + --disabled_items_count; + --h; + continue; + } + if( !config_setting_get_bool(item) )/* we dont remove it from the three due to inheritance */ + --disabled_items_count; + } + /* all ok, process */ + CREATE( zone->disabled_items, int, disabled_items_count ); + for(h = 0, v = 0; h < config_setting_length(items); h++) { + config_setting_t *item = config_setting_get_elem(items, h); + + if( config_setting_get_bool(item) ) { /* only add if enabled */ + name = config_setting_name(item); + zone->disabled_items[v++] = map_zone_str2itemid(name); + } + + } + zone->disabled_items_count = disabled_items_count; + } + + if( (mapflags = config_setting_get_member(zone_e, "mapflags")) != NULL ) { + mapflags_count = config_setting_length(mapflags); + /* mapflags are not validated here, so we save all anyway */ + CREATE( zone->mapflags, char *, mapflags_count ); + for(h = 0; h < mapflags_count; h++) { + CREATE( zone->mapflags[h], char, MAP_ZONE_MAPFLAG_LENGTH ); + + name = config_setting_get_string_elem(mapflags, h); + + safestrncpy(zone->mapflags[h], name, MAP_ZONE_MAPFLAG_LENGTH); + + } + zone->mapflags_count = mapflags_count; + } + + if( (commands = config_setting_get_member(zone_e, "disabled_commands")) != NULL ) { + disabled_commands_count = config_setting_length(commands); + /* validate */ + for(h = 0; h < config_setting_length(commands); h++) { + config_setting_t *command = config_setting_get_elem(commands, h); + name = config_setting_name(command); + if( !atcommand->exists(name) ) { + ShowError("map_zone_db: unknown command '%s' in disabled_commands for zone '%s', skipping entry...\n",name,zone->name); + config_setting_remove_elem(commands,h); + --disabled_commands_count; + --h; + continue; + } + if( !config_setting_get_int(command) )/* we dont remove it from the three due to inheritance */ + --disabled_commands_count; + } + /* all ok, process */ + CREATE( zone->disabled_commands, struct map_zone_disabled_command_entry *, disabled_commands_count ); + for(h = 0, v = 0; h < config_setting_length(commands); h++) { + config_setting_t *command = config_setting_get_elem(commands, h); + struct map_zone_disabled_command_entry * entry; + int group_lv; + name = config_setting_name(command); + + if( (group_lv = config_setting_get_int(command)) ) { /* only add if enabled */ + CREATE( entry, struct map_zone_disabled_command_entry, 1 ); + + entry->cmd = atcommand->exists(name)->func; + entry->group_lv = group_lv; + + zone->disabled_commands[v++] = entry; + } + } + zone->disabled_commands_count = disabled_commands_count; + } + + if( (caps = config_setting_get_member(zone_e, "skill_damage_cap")) != NULL ) { + capped_skills_count = config_setting_length(caps); + /* validate */ + for(h = 0; h < config_setting_length(caps); h++) { + config_setting_t *cap = config_setting_get_elem(caps, h); + name = config_setting_name(cap); + if( !map_zone_str2skillid(name) ) { + ShowError("map_zone_db: unknown skill (%s) in skill_damage_cap for zone '%s', skipping skill...\n",name,zone->name); + config_setting_remove_elem(caps,h); + --capped_skills_count; + --h; + continue; + } + if( !map_zone_bl_type(config_setting_get_string_elem(cap,1),&subtype) )/* we dont remove it from the three due to inheritance */ + --capped_skills_count; + } + /* all ok, process */ + CREATE( zone->capped_skills, struct map_zone_skill_damage_cap_entry *, capped_skills_count ); + for(h = 0, v = 0; h < config_setting_length(caps); h++) { + config_setting_t *cap = config_setting_get_elem(caps, h); + struct map_zone_skill_damage_cap_entry * entry; + enum bl_type type; + name = config_setting_name(cap); + + if( (type = map_zone_bl_type(config_setting_get_string_elem(cap,1),&subtype)) ) { /* only add if enabled */ + CREATE( entry, struct map_zone_skill_damage_cap_entry, 1 ); + + entry->nameid = map_zone_str2skillid(name); + entry->cap = config_setting_get_int_elem(cap,0); + entry->type = type; + entry->subtype = subtype; + zone->capped_skills[v++] = entry; + } + } + zone->capped_skills_count = capped_skills_count; + } + + if( !is_all ) /* global template doesn't go into db -- since it isn't a alloc'd piece of data */ + strdb_put(zone_db, zonename, zone); + + } + + /* process inheritance, aka loop through the whole thing again :P */ + for (i = 0; i < zone_count; ++i) { + config_setting_t *inherit_tree = NULL; + config_setting_t *new_entry = NULL; + int inherit_count; + + zone_e = config_setting_get_elem(zones, i); + config_setting_lookup_string(zone_e, "name", &zonename); + + if( strncmpi(zonename,MAP_ZONE_ALL_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) { + continue;/* all zone doesn't inherit anything (if it did, everything would link to each other and boom endless loop) */ + } + + if( (inherit_tree = config_setting_get_member(zone_e, "inherit")) != NULL ) { + /* append global zone to this */ + new_entry = config_setting_add(inherit_tree,MAP_ZONE_ALL_NAME,CONFIG_TYPE_STRING); + config_setting_set_string(new_entry,MAP_ZONE_ALL_NAME); + } else { + /* create inherit member and add global zone to it */ + inherit_tree = config_setting_add(zone_e, "inherit",CONFIG_TYPE_ARRAY); + new_entry = config_setting_add(inherit_tree,MAP_ZONE_ALL_NAME,CONFIG_TYPE_STRING); + config_setting_set_string(new_entry,MAP_ZONE_ALL_NAME); + } + inherit_count = config_setting_length(inherit_tree); + for(h = 0; h < inherit_count; h++) { + struct map_zone_data *izone; /* inherit zone */ + int disabled_skills_count_i = 0; /* disabled skill count from inherit zone */ + int disabled_items_count_i = 0; /* disabled item count from inherit zone */ + int mapflags_count_i = 0; /* mapflag count from inherit zone */ + int disabled_commands_count_i = 0; /* commands count from inherit zone */ + int capped_skills_count_i = 0; /* skill capped count from inherit zone */ + int j; + + name = config_setting_get_string_elem(inherit_tree, h); + config_setting_lookup_string(zone_e, "name", &zonename);/* will succeed for we validated it earlier */ + + if( !(izone = strdb_get(zone_db, name)) ) { + ShowError("map_zone_db: Unknown zone '%s' being inherit by zone '%s', skipping...\n",name,zonename); + continue; + } + + if( strncmpi(zonename,MAP_ZONE_NORMAL_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) { + zone = &map_zone_all; + } else if( strncmpi(zonename,MAP_ZONE_PK_NAME,MAP_ZONE_NAME_LENGTH) == 0 ) { + zone = &map_zone_pk; + } else + zone = strdb_get(zone_db, zonename);/* will succeed for we just put it in here */ + + disabled_skills_count_i = izone->disabled_skills_count; + disabled_items_count_i = izone->disabled_items_count; + mapflags_count_i = izone->mapflags_count; + disabled_commands_count_i = izone->disabled_commands_count; + capped_skills_count_i = izone->capped_skills_count; + + /* process everything to override, paying attention to config_setting_get_bool */ + if( disabled_skills_count_i ) { + if( (skills = config_setting_get_member(zone_e, "disabled_skills")) == NULL ) + skills = config_setting_add(zone_e, "disabled_skills",CONFIG_TYPE_GROUP); + disabled_skills_count = config_setting_length(skills); + for(j = 0; j < disabled_skills_count_i; j++) { + int k; + for(k = 0; k < disabled_skills_count; k++) { + config_setting_t *skill = config_setting_get_elem(skills, k); + if( map_zone_str2skillid(config_setting_name(skill)) == izone->disabled_skills[j]->nameid ) { + break; + } + } + if( k == disabled_skills_count ) {/* we didn't find it */ + struct map_zone_disabled_skill_entry *entry; + RECREATE( zone->disabled_skills, struct map_zone_disabled_skill_entry *, ++zone->disabled_skills_count ); + CREATE( entry, struct map_zone_disabled_skill_entry, 1 ); + entry->nameid = izone->disabled_skills[j]->nameid; + entry->type = izone->disabled_skills[j]->type; + zone->disabled_skills[zone->disabled_skills_count-1] = entry; + } + } + } + + if( disabled_items_count_i ) { + if( (items = config_setting_get_member(zone_e, "disabled_items")) == NULL ) + items = config_setting_add(zone_e, "disabled_items",CONFIG_TYPE_GROUP); + disabled_items_count = config_setting_length(items); + for(j = 0; j < disabled_items_count_i; j++) { + int k; + for(k = 0; k < disabled_items_count; k++) { + config_setting_t *item = config_setting_get_elem(items, k); + + name = config_setting_name(item); + + if( map_zone_str2itemid(name) == izone->disabled_items[j] ) { + if( config_setting_get_bool(item) ) + continue; + break; + } + } + if( k == disabled_items_count ) {/* we didn't find it */ + RECREATE( zone->disabled_items, int, ++zone->disabled_items_count ); + zone->disabled_items[zone->disabled_items_count-1] = izone->disabled_items[j]; + } + } + } + + if( mapflags_count_i ) { + if( (mapflags = config_setting_get_member(zone_e, "mapflags")) == NULL ) + mapflags = config_setting_add(zone_e, "mapflags",CONFIG_TYPE_ARRAY); + mapflags_count = config_setting_length(mapflags); + for(j = 0; j < mapflags_count_i; j++) { + int k; + for(k = 0; k < mapflags_count; k++) { + name = config_setting_get_string_elem(mapflags, k); + + if( strcmpi(name,izone->mapflags[j]) == 0 ) { + break; + } + } + if( k == mapflags_count ) {/* we didn't find it */ + RECREATE( zone->mapflags, char*, ++zone->mapflags_count ); + CREATE( zone->mapflags[zone->mapflags_count-1], char, MAP_ZONE_MAPFLAG_LENGTH ); + safestrncpy(zone->mapflags[zone->mapflags_count-1], izone->mapflags[j], MAP_ZONE_MAPFLAG_LENGTH); + } + } + } + + if( disabled_commands_count_i ) { + if( (commands = config_setting_get_member(zone_e, "disabled_commands")) == NULL ) + commands = config_setting_add(zone_e, "disabled_commands",CONFIG_TYPE_GROUP); + + disabled_commands_count = config_setting_length(commands); + for(j = 0; j < disabled_commands_count_i; j++) { + int k; + for(k = 0; k < disabled_commands_count; k++) { + config_setting_t *command = config_setting_get_elem(commands, k); + if( atcommand->exists(config_setting_name(command))->func == izone->disabled_commands[j]->cmd ) { + break; + } + } + if( k == disabled_commands_count ) {/* we didn't find it */ + struct map_zone_disabled_command_entry *entry; + RECREATE( zone->disabled_commands, struct map_zone_disabled_command_entry *, ++zone->disabled_commands_count ); + CREATE( entry, struct map_zone_disabled_command_entry, 1 ); + entry->cmd = izone->disabled_commands[j]->cmd; + entry->group_lv = izone->disabled_commands[j]->group_lv; + zone->disabled_commands[zone->disabled_commands_count-1] = entry; + } + } + } + + if( capped_skills_count_i ) { + if( (caps = config_setting_get_member(zone_e, "skill_damage_cap")) == NULL ) + caps = config_setting_add(zone_e, "skill_damage_cap",CONFIG_TYPE_GROUP); + + capped_skills_count = config_setting_length(caps); + for(j = 0; j < capped_skills_count_i; j++) { + int k; + for(k = 0; k < capped_skills_count; k++) { + config_setting_t *cap = config_setting_get_elem(caps, k); + if( map_zone_str2skillid(config_setting_name(cap)) == izone->capped_skills[j]->nameid ) { + break; + } + } + if( k == capped_skills_count ) {/* we didn't find it */ + struct map_zone_skill_damage_cap_entry *entry; + RECREATE( zone->capped_skills, struct map_zone_skill_damage_cap_entry *, ++zone->capped_skills_count ); + CREATE( entry, struct map_zone_skill_damage_cap_entry, 1 ); + entry->nameid = izone->capped_skills[j]->nameid; + entry->cap = izone->capped_skills[j]->cap; + entry->type = izone->capped_skills[j]->type; + zone->capped_skills[zone->capped_skills_count-1] = entry; + } + } + } + + } + } + + 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 */ + config_destroy(&map_zone_db); + } +} /** * @see DBApply */ int map_db_final(DBKey key, DBData *data, va_list ap) { - struct map_data_other_server *mdos = db_data2ptr(data); + struct map_data_other_server *mdos = DB->data2ptr(data); if(mdos && mdos->cell == NULL) aFree(mdos); return 0; @@ -3495,7 +4865,7 @@ int map_db_final(DBKey key, DBData *data, va_list ap) */ int nick_db_final(DBKey key, DBData *data, va_list args) { - struct charid2nick* p = db_data2ptr(data); + struct charid2nick* p = DB->data2ptr(data); struct charid_request* req; if( p == NULL ) @@ -3531,7 +4901,7 @@ int cleanup_sub(struct block_list *bl, va_list ap) map_clearflooritem(bl); break; case BL_SKILL: - skill_delunit((struct skill_unit *) bl); + skill->delunit((struct skill_unit *) bl); break; } @@ -3543,7 +4913,7 @@ int cleanup_sub(struct block_list *bl, va_list ap) */ static int cleanup_db_sub(DBKey key, DBData *data, va_list va) { - return cleanup_sub(db_data2ptr(data), va); + return cleanup_sub(DB->data2ptr(data), va); } /*========================================== @@ -3551,17 +4921,19 @@ static int cleanup_db_sub(DBKey key, DBData *data, va_list va) *------------------------------------------*/ void do_final(void) { - int i, j; + int i; struct map_session_data* sd; struct s_mapiterator* iter; ShowStatus("Terminating...\n"); + hChSys.closing = true; + HPM->event(HPET_FINAL); //Ladies and babies first. iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) map_quit(sd); - mapit_free(iter); + mapit->free(iter); /* prepares npcs for a faster shutdown process */ do_clear_npc(); @@ -3577,43 +4949,35 @@ void do_final(void) id_db->foreach(id_db,cleanup_db_sub); chrif_char_reset_offline(); chrif_flush_fifo(); - - do_final_atcommand(); - do_final_battle(); + + atcommand->final(); + battle->final(); do_final_chrif(); - do_final_clif(); + ircbot->final();/* before clif. */ + clif->final(); do_final_npc(); - do_final_script(); + script->final(); do_final_instance(); do_final_itemdb(); do_final_storage(); - do_final_guild(); + guild->final(); do_final_party(); do_final_pc(); do_final_pet(); do_final_mob(); - do_final_msg(); - do_final_skill(); + homun->final(); + atcommand->final_msg(); + skill->final(); do_final_status(); do_final_unit(); do_final_battleground(); do_final_duel(); do_final_elemental(); - + do_final_maps(); + vending->final(); + map_db->destroy(map_db, map_db_final); - - for (i=0; i<map_num; i++) { - if(map[i].cell) aFree(map[i].cell); - if(map[i].block) aFree(map[i].block); - if(map[i].block_mob) aFree(map[i].block_mob); - if(battle_config.dynamic_mobs) { //Dynamic mobs flag by [random] - if(map[i].mob_delete_timer != INVALID_TIMER) - delete_timer(map[i].mob_delete_timer, map_removemobs_timer); - for (j=0; j<MAX_MOB_LIST_PER_MAP; j++) - if (map[i].moblist[j]) aFree(map[i].moblist[j]); - } - } - + mapindex_final(); if(enable_grf) grfio_final(); @@ -3628,6 +4992,9 @@ void do_final(void) regen_db->destroy(regen_db, NULL); map_sql_close(); + ers_destroy(map_iterator_ers); + + aFree(map); ShowStatus("Finished.\n"); } @@ -3689,22 +5056,19 @@ static void map_helpscreen(bool do_exit) /*====================================================== * Map-Server Version Screen [MC Cameri] *------------------------------------------------------*/ -static void map_versionscreen(bool do_exit) -{ - ShowInfo(CL_WHITE"rAthena SVN version: %s" CL_RESET"\n", get_svn_revision()); - ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://rathena.org/\n"); - ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rathena.net/#rathena\n"); +static void map_versionscreen(bool do_exit) { + const char *svn = get_svn_revision(); + const char *git = get_git_hash(); + ShowInfo(CL_WHITE"Hercules version: %s" CL_RESET"\n", git[0] != HERC_UNKNOWN_VER ? git : svn[0] != HERC_UNKNOWN_VER ? svn : "Unknown"); + ShowInfo(CL_GREEN"Website/Forum:"CL_RESET"\thttp://hercules.ws/\n"); + ShowInfo(CL_GREEN"IRC Channel:"CL_RESET"\tirc://irc.rizon.net/#Hercules\n"); ShowInfo("Open "CL_WHITE"readme.txt"CL_RESET" for more information.\n"); if( do_exit ) exit(EXIT_SUCCESS); } -/*====================================================== - * Map-Server Init and Command-line Arguments [Valaris] - *------------------------------------------------------*/ -void set_server_type(void) -{ - SERVER_TYPE = ATHENA_SERVER_MAP; +void set_server_type(void) { + SERVER_TYPE = SERVER_TYPE_MAP; } @@ -3718,9 +5082,9 @@ void do_shutdown(void) { struct map_session_data* sd; struct s_mapiterator* iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) - clif_GM_kick(NULL, sd); - mapit_free(iter); + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) + clif->GM_kick(NULL, sd); + mapit->free(iter); flush_fifos(); } chrif_check_shutdown(); @@ -3729,15 +5093,124 @@ void do_shutdown(void) static bool map_arg_next_value(const char* option, int i, int argc) { - if( i >= argc-1 ) - { + if( i >= argc-1 ) { ShowWarning("Missing value for option '%s'.\n", option); return false; } return true; } +struct map_session_data cpsd; +CPCMD(gm_position) { + int x = 0, y = 0, m = 0; + char map_name[25]; + + if( line == NULL || sscanf(line, "%d %d %24s",&x,&y,map_name) < 3 ) { + ShowError("gm:info invalid syntax. use '"CL_WHITE"gm:info xCord yCord map_name"CL_RESET"'\n"); + return; + } + if ( (m = map_mapname2mapid(map_name) <= 0 ) ) { + ShowError("gm:info '"CL_WHITE"%s"CL_RESET"' is not a known map\n",map_name); + return; + } + + if( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) { + ShowError("gm:info '"CL_WHITE"%d %d"CL_RESET"' is out of '"CL_WHITE"%s"CL_RESET"' map bounds!\n",x,y,map_name); + return; + } + + ShowInfo("HCP: updated console's game position to '"CL_WHITE"%d %d %s"CL_RESET"'\n",x,y,map_name); + cpsd.bl.x = x; + cpsd.bl.y = y; + cpsd.bl.m = m; +} +CPCMD(gm_use) { + + if( line == NULL ) { + ShowError("gm:use invalid syntax. use '"CL_WHITE"gm:use @command <optional params>"CL_RESET"'\n"); + return; + } + cpsd.fd = -2; + if( !atcommand->parse(cpsd.fd, &cpsd, line, 0) ) + ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' failed\n",line); + else + ShowInfo("HCP: '"CL_WHITE"%s"CL_RESET"' was used\n",line); + cpsd.fd = 0; + +} +/* Hercules Console Parser */ +void map_cp_defaults(void) { + /* default HCP data */ + memset(&cpsd, 0, sizeof(struct map_session_data)); + strcpy(cpsd.status.name, "Hercules Console"); + cpsd.bl.x = 150; + cpsd.bl.y = 150; + cpsd.bl.m = map_mapname2mapid("prontera"); + + console->addCommand("gm:info",CPCMD_A(gm_position)); + console->addCommand("gm:use",CPCMD_A(gm_use)); +} +/* Hercules Plugin Mananger */ +void map_hp_symbols(void) { + /* full interfaces */ + HPM->share(atcommand,"atcommand"); + HPM->share(buyingstore,"buyingstore"); + HPM->share(clif,"clif"); + HPM->share(ircbot,"ircbot"); + HPM->share(logs,"logs"); + HPM->share(script,"script"); + HPM->share(searchstore,"searchstore"); + HPM->share(skill,"skill"); + HPM->share(vending,"vending"); + /* partial */ + HPM->share(mapit,"mapit"); + HPM->share(map_foreachpc,"map_foreachpc"); + HPM->share(map_foreachmob,"map_foreachmob"); + HPM->share(map_foreachnpc,"map_foreachnpc"); + HPM->share(map_foreachregen,"map_foreachregen"); + HPM->share(map_foreachiddb,"map_foreachiddb"); + /* sql link */ + HPM->share(mmysql_handle,"sql_handle"); + /* specific */ + HPM->share(atcommand->create,"addCommand"); + HPM->share(script->addScript,"addScript"); + /* vars */ + HPM->share(map,"map"); +} +/* temporary until the map.c "Hercules Renewal Phase One" design is complete. */ +void map_defaults(void) { + mapit = &mapit_s; + + mapit->alloc = mapit_alloc; + mapit->free = mapit_free; + mapit->first = mapit_first; + mapit->last = mapit_last; + mapit->next = mapit_next; + mapit->prev = mapit_prev; + mapit->exists = mapit_exists; + + map_foreachpc = map_map_foreachpc; + map_foreachmob = map_map_foreachmob; + map_foreachnpc = map_map_foreachnpc; + map_foreachregen = map_map_foreachregen; + map_foreachiddb = map_map_foreachiddb; +} +void load_defaults(void) { + atcommand_defaults(); + battle_defaults(); + buyingstore_defaults(); + clif_defaults(); + guild_defaults(); + homunculus_defaults(); + ircbot_defaults(); + log_defaults(); + map_defaults(); + script_defaults(); + searchstore_defaults(); + skill_defaults(); + vending_defaults(); +} int do_init(int argc, char *argv[]) { int i; @@ -3842,15 +5315,17 @@ int do_init(int argc, char *argv[]) exit(EXIT_FAILURE); } } - + + CREATE(map,struct map_data,MAX_MAP_PER_SERVER); + + load_defaults(); + map_config_read(MAP_CONF_NAME); - /* only temporary until sirius's datapack patch is complete */ - // loads npcs map_reloadnpc(false); chrif_checkdefaultlogin(); - + if (!map_ip_set || !char_ip_set) { char ip_str[16]; ip2str(addr_[0], ip_str); @@ -3865,16 +5340,16 @@ int do_init(int argc, char *argv[]) ShowInfo("Defaulting to %s as our IP address\n", ip_str); if (!map_ip_set) - clif_setip(ip_str); + clif->setip(ip_str); if (!char_ip_set) chrif_setip(ip_str); } - - battle_config_read(BATTLE_CONF_FILENAME); - msg_config_read(MSG_CONF_NAME); + + battle->config_read(BATTLE_CONF_FILENAME); + atcommand->msg_read(MSG_CONF_NAME); script_config_read(SCRIPT_CONF_NAME); inter_config_read(INTER_CONF_NAME); - log_config_read(LOG_CONF_NAME); + logs->config_read(LOG_CONF_NAME); id_db = idb_alloc(DB_OPT_BASE); pc_db = idb_alloc(DB_OPT_BASE); //Added for reliable map_id2sd() use. [Skotlex] @@ -3886,38 +5361,47 @@ int do_init(int argc, char *argv[]) regen_db = idb_alloc(DB_OPT_BASE); // efficient status_natural_heal processing iwall_db = strdb_alloc(DB_OPT_RELEASE_DATA,2*NAME_LENGTH+2+1); // [Zephyrus] Invisible Walls + zone_db = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, MAP_ZONE_NAME_LENGTH); + map_iterator_ers = ers_new(sizeof(struct s_mapiterator),"map.c::map_iterator_ers",ERS_OPT_NONE); + map_sql_init(); - if (log_config.sql_logs) + if (logs->config.sql_logs) log_sql_init(); mapindex_init(); if(enable_grf) grfio_init(GRF_PATH_FILENAME); - + map_readallmaps(); add_timer_func_list(map_freeblock_timer, "map_freeblock_timer"); add_timer_func_list(map_clearflooritem_timer, "map_clearflooritem_timer"); add_timer_func_list(map_removemobs_timer, "map_removemobs_timer"); add_timer_interval(gettick()+1000, map_freeblock_timer, 0, 0, 60*1000); - - do_init_atcommand(); - do_init_battle(); + + HPM->symbol_defaults_sub = map_hp_symbols; + HPM->config_read(); + HPM->event(HPET_INIT); + + atcommand->init(); + battle->init(); do_init_instance(); do_init_chrif(); - do_init_clif(); - do_init_script(); + clif->init(); + ircbot->init(); + script->init(); do_init_itemdb(); - do_init_skill(); + skill->init(); + read_map_zone_db();/* read after item and skill initalization */ do_init_mob(); do_init_pc(); do_init_status(); do_init_party(); - do_init_guild(); + guild->init(); do_init_storage(); do_init_pet(); - do_init_merc(); + homun->init(); do_init_mercenary(); do_init_elemental(); do_init_quest(); @@ -3925,28 +5409,25 @@ int do_init(int argc, char *argv[]) do_init_unit(); do_init_battleground(); do_init_duel(); + vending->init(); npc_event_do_oninit(); // Init npcs (OnInit) - if( console ) - { - //##TODO invoke a CONSOLE_START plugin event - } - if (battle_config.pk_mode) ShowNotice("Server is running on '"CL_WHITE"PK Mode"CL_RESET"'.\n"); + Sql_HerculesUpdateCheck(mmysql_handle); + ShowStatus("Server is '"CL_GREEN"ready"CL_RESET"' and listening on port '"CL_WHITE"%d"CL_RESET"'.\n\n", map_port); - - if( runflag != CORE_ST_STOP ) - { + + if( runflag != CORE_ST_STOP ) { shutdown_callback = do_shutdown; runflag = MAPSERVER_ST_RUNNING; } -#if defined(BUILDBOT) - if( buildbotflag ) - exit(EXIT_FAILURE); -#endif - + + map_cp_defaults(); + + HPM->event(HPET_READY); + return 0; } diff --git a/src/map/map.h b/src/map/map.h index 86d936972..a7bcb08db 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -1,5 +1,6 @@ -// 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 _MAP_H_ #define _MAP_H_ @@ -10,18 +11,17 @@ #include "../common/mapindex.h" #include "../common/db.h" -/** - * [rAthena.org] - **/ #include "../config/core.h" +#include "atcommand.h" + #include <stdarg.h> struct npc_data; struct item_data; +struct hChSysCh; -enum E_MAPSERVER_ST -{ +enum E_MAPSERVER_ST { MAPSERVER_ST_RUNNING = CORE_ST_LAST, MAPSERVER_ST_SHUTDOWN, MAPSERVER_ST_LAST @@ -108,7 +108,7 @@ enum { MAPID_ASSASSIN, MAPID_STAR_GLADIATOR, MAPID_KAGEROUOBORO = JOBL_2_1|0x0A, - MAPID_DEATH_KNIGHT = JOBL_2_1|0x0D, + MAPID_DEATH_KNIGHT = JOBL_2_1|0x0E, //2-2 Jobs MAPID_CRUSADER = JOBL_2_2|0x1, MAPID_SAGE, @@ -360,6 +360,8 @@ enum _sp { SP_BASECLASS=120, //Hmm.. why 100+19? I just use the next one... [Skotlex] SP_KILLERRID=121, SP_KILLEDRID=122, + SP_SLOTCHANGE=123, + SP_CHARRENAME=124, // Mercenaries SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190, @@ -406,7 +408,7 @@ enum _sp { SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE, SP_MAGIC_SP_GAIN_VALUE, SP_MAGIC_HP_GAIN_VALUE, SP_ADD_CLASS_DROP_ITEM, //2041-2045 SP_EMATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2049 SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2050-2054 - SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE //2055-2056 + SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST //2055-2058 }; enum _look { @@ -495,6 +497,68 @@ struct iwall_data { bool shootable; }; +struct mapflag_skill_adjust { + unsigned short skill_id; + unsigned short modifier; +}; + +enum map_zone_skill_subtype { + MZS_NONE = 0x0, + MZS_CLONE = 0x01, + MZS_BOSS = 0x02, + + MZS_ALL = 0xFFF, +}; + +struct map_zone_disabled_skill_entry { + unsigned short nameid; + enum bl_type type; + enum map_zone_skill_subtype subtype; +}; +struct map_zone_disabled_command_entry { + AtCommandFunc cmd; + int group_lv; +}; + +struct map_zone_skill_damage_cap_entry { + unsigned short nameid; + unsigned int cap; + enum bl_type type; + enum map_zone_skill_subtype subtype; +}; + +#define MAP_ZONE_NAME_LENGTH 30 +#define MAP_ZONE_ALL_NAME "All" +#define MAP_ZONE_NORMAL_NAME "Normal" +#define MAP_ZONE_PVP_NAME "PvP" +#define MAP_ZONE_GVG_NAME "GvG" +#define MAP_ZONE_BG_NAME "Battlegrounds" +#define MAP_ZONE_PK_NAME "PK Mode" +#define MAP_ZONE_MAPFLAG_LENGTH 50 +DBMap *zone_db;/* string => struct map_zone_data */ +struct map_zone_data { + char name[MAP_ZONE_NAME_LENGTH];/* 20'd */ + struct map_zone_disabled_skill_entry **disabled_skills; + int disabled_skills_count; + int *disabled_items; + int disabled_items_count; + char **mapflags; + int mapflags_count; + struct map_zone_disabled_command_entry **disabled_commands; + int disabled_commands_count; + struct map_zone_skill_damage_cap_entry **capped_skills; + int capped_skills_count; +}; +void map_zone_init(void); +void map_zone_remove(int m); +void map_zone_apply(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath); +void map_zone_change(int m, struct map_zone_data *zone, const char* start, const char* buffer, const char* filepath); +void map_zone_change2(int m, struct map_zone_data *zone); + +struct map_zone_data map_zone_all;/* used as a base on all maps */ +struct map_zone_data map_zone_pk;/* used for (pk_mode) */ + + struct map_data { char name[MAP_NAME_LENGTH]; uint16 index; // The map index used by the mapindex* functions. @@ -543,17 +607,11 @@ struct map_data { unsigned fireworks : 1; unsigned sakura : 1; // [Valaris] unsigned leaves : 1; // [Valaris] - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //unsigned rain : 1; // [Valaris] - unsigned nogo : 1; // [Valaris] unsigned nobaseexp : 1; // [Lorky] added by Lupus unsigned nojobexp : 1; // [Lorky] unsigned nomobloot : 1; // [Lorky] unsigned nomvploot : 1; // [Lorky] unsigned nightenabled :1; //For night display. [Skotlex] - unsigned restricted : 1; // [Komurka] unsigned nodrop : 1; unsigned novending : 1; unsigned loadevent : 1; @@ -562,6 +620,8 @@ struct map_data { unsigned guildlock :1; unsigned src4instance : 1; // To flag this map when it's used as a src map for instances unsigned reset :1; // [Daegaladh] + unsigned chsysnolocalaj : 1; + unsigned noknockback : 1; } flag; struct point save; struct npc_data *npc[MAX_NPC_PER_MAP]; @@ -573,7 +633,6 @@ struct map_data { struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer] int mob_delete_timer; // [Skotlex] - int zone; // zone number (for item/skill restrictions) int jexp; // map experience multiplicator int bexp; // map experience multiplicator int nocommand; //Blocks @/# commands for non-gms. [Skotlex] @@ -587,6 +646,36 @@ struct map_data { // Instance Variables int instance_id; int instance_src_map; + + /* adjust_unit_duration mapflag */ + struct mapflag_skill_adjust **units; + unsigned short unit_count; + /* adjust_skill_damage mapflag */ + struct mapflag_skill_adjust **skills; + unsigned short skill_count; + + /* Hercules nocast db overhaul */ + struct map_zone_data *zone; + char **zone_mf;/* used to store this map's zone mapflags that should be re-applied once zone is removed */ + unsigned short zone_mf_count; + struct map_zone_data *prev_zone; + + /* Hercules Local Chat */ + struct hChSysCh *channel; + + /* invincible_time_inc mapflag */ + unsigned int invincible_time_inc; + + /* weapon_damage_rate mapflag */ + unsigned short weapon_damage_rate; + /* magic_damage_rate mapflag */ + unsigned short magic_damage_rate; + /* misc_damage_rate mapflag */ + unsigned short misc_damage_rate; + /* short_damage_rate mapflag */ + unsigned short short_damage_rate; + /* long_damage_rate mapflag */ + unsigned short long_damage_rate; }; /// Stores information about a remote map (for multi-mapserver setups). @@ -604,7 +693,7 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk); void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag); void map_setgatcell(int16 m, int16 x, int16 y, int gat); -extern struct map_data map[]; +struct map_data *map; extern int map_num; extern int autosave_interval; @@ -687,11 +776,13 @@ int map_eraseipport(unsigned short map, uint32 ip, uint16 port); int map_eraseallipport(void); void map_addiddb(struct block_list *); void map_deliddb(struct block_list *bl); -void map_foreachpc(int (*func)(struct map_session_data* sd, va_list args), ...); -void map_foreachmob(int (*func)(struct mob_data* md, va_list args), ...); -void map_foreachnpc(int (*func)(struct npc_data* nd, va_list args), ...); -void map_foreachregen(int (*func)(struct block_list* bl, va_list args), ...); -void map_foreachiddb(int (*func)(struct block_list* bl, va_list args), ...); +/* temporary until the map.c "Hercules Renewal Phase One" design is complete. */ +void (*map_foreachpc) (int (*func)(struct map_session_data* sd, va_list args), ...); +void (*map_foreachmob) (int (*func)(struct mob_data* md, va_list args), ...); +void (*map_foreachnpc) (int (*func)(struct npc_data* nd, va_list args), ...); +void (*map_foreachregen) (int (*func)(struct block_list* bl, va_list args), ...); +void (*map_foreachiddb) (int (*func)(struct block_list* bl, va_list args), ...); +/* */ struct map_session_data * map_nick2sd(const char*); struct mob_data * map_getmob_boss(int16 m); struct mob_data * map_id2boss(int id); @@ -700,24 +791,27 @@ struct mob_data * map_id2boss(int id); void map_reloadnpc(bool clear); /// Bitfield of flags for the iterator. -enum e_mapitflags -{ +enum e_mapitflags { MAPIT_NORMAL = 0, // MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold auth'ed, active players. }; struct s_mapiterator; -struct s_mapiterator* mapit_alloc(enum e_mapitflags flags, enum bl_type types); -void mapit_free(struct s_mapiterator* mapit); -struct block_list* mapit_first(struct s_mapiterator* mapit); -struct block_list* mapit_last(struct s_mapiterator* mapit); -struct block_list* mapit_next(struct s_mapiterator* mapit); -struct block_list* mapit_prev(struct s_mapiterator* mapit); -bool mapit_exists(struct s_mapiterator* mapit); -#define mapit_getallusers() mapit_alloc(MAPIT_NORMAL,BL_PC) -#define mapit_geteachpc() mapit_alloc(MAPIT_NORMAL,BL_PC) -#define mapit_geteachmob() mapit_alloc(MAPIT_NORMAL,BL_MOB) -#define mapit_geteachnpc() mapit_alloc(MAPIT_NORMAL,BL_NPC) -#define mapit_geteachiddb() mapit_alloc(MAPIT_NORMAL,BL_ALL) +/* temporary until the map.c "Hercules Renewal Phase One" design is complete. */ +struct mapit_interface { + struct s_mapiterator* (*alloc) (enum e_mapitflags flags, enum bl_type types); + void (*free) (struct s_mapiterator* mapit); + struct block_list* (*first) (struct s_mapiterator* mapit); + struct block_list* (*last) (struct s_mapiterator* mapit); + struct block_list* (*next) (struct s_mapiterator* mapit); + struct block_list* (*prev) (struct s_mapiterator* mapit); + bool (*exists) (struct s_mapiterator* mapit); +} mapit_s; +struct mapit_interface *mapit; +#define mapit_getallusers() mapit->alloc(MAPIT_NORMAL,BL_PC) +#define mapit_geteachpc() mapit->alloc(MAPIT_NORMAL,BL_PC) +#define mapit_geteachmob() mapit->alloc(MAPIT_NORMAL,BL_MOB) +#define mapit_geteachnpc() mapit->alloc(MAPIT_NORMAL,BL_NPC) +#define mapit_geteachiddb() mapit->alloc(MAPIT_NORMAL,BL_ALL) int map_check_dir(int s_dir,int t_dir); uint8 map_calc_dir( struct block_list *src,int16 x,int16 y); @@ -763,26 +857,6 @@ typedef struct elemental_data TBL_ELEM; #define BL_CAST(type_, bl) \ ( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) ) - -extern char main_chat_nick[16]; - -#ifdef BETA_THREAD_TEST - -extern char default_codepage[32]; -extern int map_server_port; -extern char map_server_ip[32]; -extern char map_server_id[32]; -extern char map_server_pw[32]; -extern char map_server_db[32]; - -extern char log_db_ip[32]; -extern int log_db_port; -extern char log_db_id[32]; -extern char log_db_pw[32]; -extern char log_db_db[32]; - -#endif - #include "../common/sql.h" extern int db_use_sqldbs; diff --git a/src/map/mapreg.h b/src/map/mapreg.h index d5fadafc5..e83f9e053 100644 --- a/src/map/mapreg.h +++ b/src/map/mapreg.h @@ -1,9 +1,19 @@ -// 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 _MAPREG_H_ #define _MAPREG_H_ +struct mapreg_save { + int uid; + union { + int i; + char *str; + } u; + bool save; +}; + void mapreg_reload(void); void mapreg_final(void); void mapreg_init(void); diff --git a/src/map/mapreg_sql.c b/src/map/mapreg_sql.c index 7782f7f02..484da5641 100644 --- a/src/map/mapreg_sql.c +++ b/src/map/mapreg_sql.c @@ -1,8 +1,10 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/db.h" +#include "../common/ers.h" #include "../common/malloc.h" #include "../common/showmsg.h" #include "../common/sql.h" @@ -10,55 +12,70 @@ #include "../common/timer.h" #include "map.h" // mmysql_handle #include "script.h" +#include "mapreg.h" #include <stdlib.h> #include <string.h> static DBMap* mapreg_db = NULL; // int var_id -> int value static DBMap* mapregstr_db = NULL; // int var_id -> char* value +static struct eri *mapreg_ers; //[Ind/Hercules] static char mapreg_table[32] = "mapreg"; -static bool mapreg_dirty = false; +static bool mapreg_i_dirty = false; +static bool mapreg_str_dirty = false; + #define MAPREG_AUTOSAVE_INTERVAL (300*1000) /// Looks up the value of an integer variable using its uid. -int mapreg_readreg(int uid) -{ - return idb_iget(mapreg_db, uid); +int mapreg_readreg(int uid) { + struct mapreg_save *m = idb_get(mapreg_db, uid); + return m?m->u.i:0; } /// Looks up the value of a string variable using its uid. -char* mapreg_readregstr(int uid) -{ - return idb_get(mapregstr_db, uid); +char* mapreg_readregstr(int uid) { + struct mapreg_save *m = idb_get(mapregstr_db, uid); + return m?m->u.str:NULL; } /// Modifies the value of an integer variable. -bool mapreg_setreg(int uid, int val) -{ +bool mapreg_setreg(int uid, int val) { + struct mapreg_save *m; int num = (uid & 0x00ffffff); int i = (uid & 0xff000000) >> 24; const char* name = get_str(num); - if( val != 0 ) - { - if( idb_iput(mapreg_db,uid,val) ) - mapreg_dirty = true; // already exists, delay write - else if(name[1] != '@') - {// write new variable to database - char tmp_str[32*2+1]; - Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); - if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg_table, tmp_str, i, val) ) - Sql_ShowDebug(mmysql_handle); + if( val != 0 ) { + if( (m = idb_get(mapreg_db,uid)) ) { + m->u.i = val; + if(name[1] != '@') { + m->save = true; + mapreg_i_dirty = true; + } + } else { + m = ers_alloc(mapreg_ers, struct mapreg_save); + + m->u.i = val; + m->uid = uid; + m->save = false; + + if(name[1] != '@') {// write new variable to database + char tmp_str[32*2+1]; + SQL->EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + if( SQL_ERROR == SQL->Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%d')", mapreg_table, tmp_str, i, val) ) + Sql_ShowDebug(mmysql_handle); + } + idb_put(mapreg_db, uid, m); + } + } else { // val == 0 + if( (m = idb_get(mapreg_db,uid)) ) { + ers_free(mapreg_ers, m); } - } - else // val == 0 - { idb_remove(mapreg_db,uid); - if( name[1] != '@' ) - {// Remove from database because it is unused. - if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) + if( name[1] != '@' ) {// Remove from database because it is unused. + if( SQL_ERROR == SQL->Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) Sql_ShowDebug(mmysql_handle); } } @@ -67,32 +84,48 @@ bool mapreg_setreg(int uid, int val) } /// Modifies the value of a string variable. -bool mapreg_setregstr(int uid, const char* str) -{ +bool mapreg_setregstr(int uid, const char* str) { + struct mapreg_save *m; int num = (uid & 0x00ffffff); int i = (uid & 0xff000000) >> 24; const char* name = get_str(num); - if( str == NULL || *str == 0 ) - { + if( str == NULL || *str == 0 ) { if(name[1] != '@') { - if( SQL_ERROR == Sql_Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) + if( SQL_ERROR == SQL->Query(mmysql_handle, "DELETE FROM `%s` WHERE `varname`='%s' AND `index`='%d'", mapreg_table, name, i) ) Sql_ShowDebug(mmysql_handle); } + if( (m = idb_get(mapregstr_db,uid)) ) { + if( m->u.str != NULL ) + aFree(m->u.str); + ers_free(mapreg_ers, m); + } idb_remove(mapregstr_db,uid); - } - else - { - if (idb_put(mapregstr_db,uid, aStrdup(str))) - mapreg_dirty = true; - else if(name[1] != '@') { //put returned null, so we must insert. - // Someone is causing a database size infinite increase here without name[1] != '@' [Lance] - char tmp_str[32*2+1]; - char tmp_str2[255*2+1]; - Sql_EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); - Sql_EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255)); - if( SQL_ERROR == Sql_Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg_table, tmp_str, i, tmp_str2) ) - Sql_ShowDebug(mmysql_handle); + } else { + if( (m = idb_get(mapregstr_db,uid)) ) { + if( m->u.str != NULL ) + aFree(m->u.str); + m->u.str = aStrdup(str); + if(name[1] != '@') { + mapreg_str_dirty = true; + m->save = true; + } + } else { + m = ers_alloc(mapreg_ers, struct mapreg_save); + + m->uid = uid; + m->u.str = aStrdup(str); + m->save = false; + + if(name[1] != '@') { //put returned null, so we must insert. + char tmp_str[32*2+1]; + char tmp_str2[255*2+1]; + SQL->EscapeStringLen(mmysql_handle, tmp_str, name, strnlen(name, 32)); + SQL->EscapeStringLen(mmysql_handle, tmp_str2, str, strnlen(str, 255)); + if( SQL_ERROR == SQL->Query(mmysql_handle, "INSERT INTO `%s`(`varname`,`index`,`value`) VALUES ('%s','%d','%s')", mapreg_table, tmp_str, i, tmp_str2) ) + Sql_ShowDebug(mmysql_handle); + } + idb_put(mapregstr_db, uid, m); } } @@ -100,8 +133,7 @@ bool mapreg_setregstr(int uid, const char* str) } /// Loads permanent variables from database -static void script_load_mapreg(void) -{ +static void script_load_mapreg(void) { /* 0 1 2 +-------------------------+ @@ -126,97 +158,147 @@ static void script_load_mapreg(void) SqlStmt_BindColumn(stmt, 1, SQLDT_INT, &index, 0, NULL, NULL); SqlStmt_BindColumn(stmt, 2, SQLDT_STRING, &value[0], sizeof(value), NULL, NULL); - while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) - { + while ( SQL_SUCCESS == SqlStmt_NextRow(stmt) ) { + struct mapreg_save *m = NULL; int s = add_str(varname); int i = index; - if( varname[length-1] == '$' ) - idb_put(mapregstr_db, (i<<24)|s, aStrdup(value)); - else - idb_iput(mapreg_db, (i<<24)|s, atoi(value)); + if( varname[length-1] == '$' ) { + if( idb_exists(mapregstr_db, (i<<24)|s) ) { + ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value); + continue; + } + } else { + if( idb_exists(mapreg_db, (i<<24)|s) ) { + ShowWarning("load_mapreg: duplicate! '%s' => '%s' skipping...\n",varname,value); + continue; + } + } + + m = ers_alloc(mapreg_ers, struct mapreg_save); + m->uid = (i<<24)|s; + m->save = false; + if( varname[length-1] == '$' ) { + m->u.str = aStrdup(value); + idb_put(mapregstr_db, m->uid, m); + } else { + m->u.i = atoi(value); + idb_put(mapreg_db, m->uid, m); + } } SqlStmt_Free(stmt); - mapreg_dirty = false; + mapreg_i_dirty = false; + mapreg_str_dirty = false; } /// Saves permanent variables to database -static void script_save_mapreg(void) -{ +static void script_save_mapreg(void) { DBIterator* iter; - DBData *data; - DBKey key; - - iter = db_iterator(mapreg_db); - for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) - { - int num = (key.i & 0x00ffffff); - int i = (key.i & 0xff000000) >> 24; - const char* name = get_str(num); - - if( name[1] == '@' ) - continue; - - if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, db_data2i(data), name, i) ) - Sql_ShowDebug(mmysql_handle); + struct mapreg_save *m = NULL; + + if( mapreg_i_dirty ) { + iter = db_iterator(mapreg_db); + for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) { + if( m->save ) { + int num = (m->uid & 0x00ffffff); + int i = (m->uid & 0xff000000) >> 24; + const char* name = get_str(num); + + if( SQL_ERROR == SQL->Query(mmysql_handle, "UPDATE `%s` SET `value`='%d' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg_table, m->u.i, name, i) ) + Sql_ShowDebug(mmysql_handle); + m->save = false; + } + } + dbi_destroy(iter); + mapreg_i_dirty = false; } - dbi_destroy(iter); - iter = db_iterator(mapregstr_db); - for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) - { - int num = (key.i & 0x00ffffff); - int i = (key.i & 0xff000000) >> 24; - const char* name = get_str(num); - char tmp_str2[2*255+1]; - - if( name[1] == '@' ) - continue; - - Sql_EscapeStringLen(mmysql_handle, tmp_str2, db_data2ptr(data), safestrnlen(db_data2ptr(data), 255)); - if( SQL_ERROR == Sql_Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d'", mapreg_table, tmp_str2, name, i) ) - Sql_ShowDebug(mmysql_handle); + if( mapreg_str_dirty ) { + iter = db_iterator(mapregstr_db); + for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) { + if( m->save ) { + int num = (m->uid & 0x00ffffff); + int i = (m->uid & 0xff000000) >> 24; + const char* name = get_str(num); + char tmp_str2[2*255+1]; + + SQL->EscapeStringLen(mmysql_handle, tmp_str2, m->u.str, safestrnlen(m->u.str, 255)); + if( SQL_ERROR == SQL->Query(mmysql_handle, "UPDATE `%s` SET `value`='%s' WHERE `varname`='%s' AND `index`='%d' LIMIT 1", mapreg_table, tmp_str2, name, i) ) + Sql_ShowDebug(mmysql_handle); + m->save = false; + } + } + dbi_destroy(iter); + mapreg_str_dirty = false; } - dbi_destroy(iter); - - mapreg_dirty = false; } -static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) -{ - if( mapreg_dirty ) - script_save_mapreg(); - +static int script_autosave_mapreg(int tid, unsigned int tick, int id, intptr_t data) { + script_save_mapreg(); return 0; } -void mapreg_reload(void) -{ - if( mapreg_dirty ) - script_save_mapreg(); +void mapreg_reload(void) { + DBIterator* iter; + struct mapreg_save *m = NULL; + script_save_mapreg(); + + iter = db_iterator(mapreg_db); + for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) { + ers_free(mapreg_ers, m); + } + dbi_destroy(iter); + + iter = db_iterator(mapregstr_db); + for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) { + if( m->u.str != NULL ) { + aFree(m->u.str); + } + ers_free(mapreg_ers, m); + } + dbi_destroy(iter); + db_clear(mapreg_db); db_clear(mapregstr_db); script_load_mapreg(); } -void mapreg_final(void) -{ - if( mapreg_dirty ) - script_save_mapreg(); +void mapreg_final(void) { + DBIterator* iter; + struct mapreg_save *m = NULL; + + script_save_mapreg(); + iter = db_iterator(mapreg_db); + for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) { + ers_free(mapreg_ers, m); + } + dbi_destroy(iter); + + iter = db_iterator(mapregstr_db); + for( m = dbi_first(iter); dbi_exists(iter); m = dbi_next(iter) ) { + if( m->u.str != NULL ) { + aFree(m->u.str); + } + ers_free(mapreg_ers, m); + } + dbi_destroy(iter); + db_destroy(mapreg_db); db_destroy(mapregstr_db); + + ers_destroy(mapreg_ers); } -void mapreg_init(void) -{ +void mapreg_init(void) { mapreg_db = idb_alloc(DB_OPT_BASE); - mapregstr_db = idb_alloc(DB_OPT_RELEASE_DATA); + mapregstr_db = idb_alloc(DB_OPT_BASE); + mapreg_ers = ers_new(sizeof(struct mapreg_save), "mapreg_sql.c::mapreg_ers", ERS_OPT_NONE); script_load_mapreg(); @@ -224,8 +306,7 @@ void mapreg_init(void) add_timer_interval(gettick() + MAPREG_AUTOSAVE_INTERVAL, script_autosave_mapreg, 0, 0, MAPREG_AUTOSAVE_INTERVAL); } -bool mapreg_config_read(const char* w1, const char* w2) -{ +bool mapreg_config_read(const char* w1, const char* w2) { if(!strcmpi(w1, "mapreg_db")) safestrncpy(mapreg_table, w2, sizeof(mapreg_table)); else diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 973dac33e..02fcea891 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/malloc.h" @@ -156,7 +157,7 @@ int mercenary_set_faith(struct mercenary_data *md, int value) *faith += value; *faith = cap_value(*faith, 0, SHRT_MAX); - clif_mercenary_updatestatus(sd, SP_MERCFAITH); + clif->mercenary_updatestatus(sd, SP_MERCFAITH); return 0; } @@ -260,7 +261,7 @@ int merc_delete(struct mercenary_data *md, int reply) case 1: mercenary_set_faith(md, -1); break; // -1 Loyalty on Mercenary killed } - clif_mercenary_message(sd, reply); + clif->mercenary_message(sd, reply); return unit_remove_map(&md->bl, CLR_OUTSIGHT); } @@ -336,9 +337,9 @@ int merc_data_received(struct s_mercenary *merc, bool flag) if( md && md->bl.prev == NULL && sd->bl.prev != NULL ) { map_addblock(&md->bl); - clif_spawn(&md->bl); - clif_mercenary_info(sd); - clif_mercenary_skillblock(sd); + clif->spawn(&md->bl); + clif->mercenary_info(sd); + clif->mercenary_skillblock(sd); } return 1; @@ -347,9 +348,9 @@ int merc_data_received(struct s_mercenary *merc, bool flag) void mercenary_heal(struct mercenary_data *md, int hp, int sp) { if( hp ) - clif_mercenary_updatestatus(md->master, SP_HP); + clif->mercenary_updatestatus(md->master, SP_HP); if( sp ) - clif_mercenary_updatestatus(md->master, SP_SP); + clif->mercenary_updatestatus(md->master, SP_SP); } int mercenary_dead(struct mercenary_data *md) @@ -379,7 +380,7 @@ int mercenary_kills(struct mercenary_data *md) } if( md->master ) - clif_mercenary_updatestatus(md->master, SP_MERCKILLS); + clif->mercenary_updatestatus(md->master, SP_MERCKILLS); return 0; } @@ -404,8 +405,8 @@ static bool read_mercenarydb_sub(char* str[], int columns, int current) db = &mercenary_db[current]; db->class_ = atoi(str[0]); - strncpy(db->sprite, str[1], NAME_LENGTH); - strncpy(db->name, str[2], NAME_LENGTH); + safestrncpy(db->sprite, str[1], NAME_LENGTH); + safestrncpy(db->name, str[2], NAME_LENGTH); db->lv = atoi(str[3]); status = &db->status; @@ -455,7 +456,7 @@ static bool read_mercenarydb_sub(char* str[], int columns, int current) int read_mercenarydb(void) { memset(mercenary_db,0,sizeof(mercenary_db)); - sv_readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub); + sv->readdb(db_path, "mercenary_db.txt", ',', 26, 26, MAX_MERCENARY_CLASS, &read_mercenarydb_sub); return 0; } @@ -493,7 +494,7 @@ static bool read_mercenary_skilldb_sub(char* str[], int columns, int current) int read_mercenary_skilldb(void) { - sv_readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub); + sv->readdb(db_path, "mercenary_skill_db.txt", ',', 3, 3, -1, &read_mercenary_skilldb_sub); return 0; } diff --git a/src/map/mob.c b/src/map/mob.c index ac3c1dfe3..57325ba1c 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -112,9 +113,9 @@ int mobdb_searchname(const char *str) static int mobdb_searchname_array_sub(struct mob_db* mob, const char *str) { if (mob == mob_dummy) - return 1; //Invalid mob. - if(!mob->base_exp && !mob->job_exp) - return 1; //Discount slave-mobs (no exp) as requested by Playtester. [Skotlex] + return 1; + if(!mob->base_exp && !mob->job_exp && mob->spawn[0].qty < 1) + return 1; // Monsters with no base/job exp and no spawn point are, by this criteria, considered "slave mobs" and excluded from search results if(stristr(mob->jname,str)) return 0; if(stristr(mob->name,str)) @@ -161,7 +162,7 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time) status_set_viewdata(&nd->bl, nd->class_); status_change_init(&nd->bl); unit_dataset(&nd->bl); - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); } @@ -173,7 +174,7 @@ void mvptomb_destroy(struct mob_data *md) { m = nd->bl.m; - clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); + clif->clearunit_area(&nd->bl,CLR_OUTSIGHT); map_delblock(&nd->bl); @@ -355,14 +356,14 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target) if( !(md = BL_CAST(BL_MOB,target)) ) return false; // Tarjet is not MOB - if( (s_bl = battle_get_master(src)) == NULL ) + if( (s_bl = battle->get_master(src)) == NULL ) s_bl = src; if( !(sd = BL_CAST(BL_PC,s_bl)) ) return false; // Master is not PC t_bl = map_id2bl(md->target_id); - if( !t_bl || (s_bl = battle_get_master(t_bl)) == NULL ) + if( !t_bl || (s_bl = battle->get_master(t_bl)) == NULL ) s_bl = t_bl; t_sd = BL_CAST(BL_PC,s_bl); @@ -398,7 +399,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target) if( DIFF_TICK(sd->ks_floodprotect_tick, tick) <= 0 ) { sprintf(output, "[KS Warning!! - Owner : %s]", pl_sd->status.name); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); sd->ks_floodprotect_tick = tick + 2000; } @@ -407,7 +408,7 @@ bool mob_ksprotected (struct block_list *src, struct block_list *target) if( DIFF_TICK(pl_sd->ks_floodprotect_tick, tick) <= 0 ) { sprintf(output, "[Watch out! %s is trying to KS you!]", sd->status.name); - clif_disp_onlyself(pl_sd, output, strlen(output)); + clif->disp_onlyself(pl_sd, output, strlen(output)); pl_sd->ks_floodprotect_tick = tick + 2000; } @@ -482,8 +483,8 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const if (class_ == MOBID_EMPERIUM) { - struct guild_castle* gc = guild_mapindex2gc(map[m].index); - struct guild* g = (gc) ? guild_search(gc->guild_id) : NULL; + struct guild_castle* gc = guild->mapindex2gc(map[m].index); + struct guild* g = (gc) ? guild->search(gc->guild_id) : NULL; if (gc) { md->guardian_data = (struct guardian_data*)aCalloc(1, sizeof(struct guardian_data)); @@ -586,7 +587,7 @@ static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t d md = (struct mob_data*)bl; nullpo_ret(md->guardian_data); - g = guild_search((int)data); + g = guild->search((int)data); if (g == NULL) { //Liberate castle, if the guild is not found this is an error! [Skotlex] @@ -597,16 +598,16 @@ static int mob_spawn_guardian_sub(int tid, unsigned int tick, int id, intptr_t d if (md->guardian_data->castle->guild_id) //Free castle up. { ShowNotice("Clearing ownership of castle %d (%s)\n", md->guardian_data->castle->castle_id, md->guardian_data->castle->castle_name); - guild_castledatasave(md->guardian_data->castle->castle_id, 1, 0); + guild->castledatasave(md->guardian_data->castle->castle_id, 1, 0); } } else { if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); + guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian. } return 0; } - guardup_lv = guild_checkskill(g,GD_GUARDUP); + guardup_lv = guild->checkskill(g,GD_GUARDUP); md->guardian_data->emblem_id = g->emblem_id; memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); md->guardian_data->guardup_lv = guardup_lv; @@ -666,7 +667,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam if (!mob_parse_dataset(&data)) return 0; - gc=guild_mapname2gc(map[m].name); + gc=guild->mapname2gc(map[m].name); if (gc == NULL) { ShowError("mob_spawn_guardian: No castle set at map %s\n", map[m].name); @@ -675,7 +676,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam if (!gc->guild_id) ShowWarning("mob_spawn_guardian: Spawning guardian %d on a castle with no guild (castle map %s)\n", class_, map[m].name); else - g = guild_search(gc->guild_id); + g = guild->search(gc->guild_id); if( has_index && gc->guardian[guardian].id ) { //Check if guardian already exists, refuse to spawn if so. @@ -712,7 +713,7 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam { md->guardian_data->emblem_id = g->emblem_id; memcpy (md->guardian_data->guild_name, g->name, NAME_LENGTH); - md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP); + md->guardian_data->guardup_lv = guild->checkskill(g,GD_GUARDUP); } else if (md->guardian_data->guild_id) add_timer(gettick()+5000,mob_spawn_guardian_sub,md->bl.id,md->guardian_data->guild_id); mob_spawn(md); @@ -874,8 +875,8 @@ int mob_setdelayspawn(struct mob_data *md) spawntime = spawntime/100*battle_config.mob_spawn_delay; } - if (spawntime < 500) //Min respawn time (is it needed?) - spawntime = 500; + if (spawntime < 5000) //Monsters should never respawn faster than within 5 seconds + spawntime = 5000; if( md->spawn_timer != INVALID_TIMER ) delete_timer(md->spawn_timer, mob_delayspawn); @@ -983,8 +984,8 @@ int mob_spawn (struct mob_data *md) map_addblock(&md->bl); if( map[md->bl.m].users ) - clif_spawn(&md->bl); - skill_unit_move(&md->bl,tick,1); + clif->spawn(&md->bl); + skill->unit_move(&md->bl,tick,1); mobskill_use(md, tick, MSC_SPAWN); return 0; } @@ -1067,7 +1068,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) if ((mode&MD_TARGETWEAK) && status_get_lv(bl) >= md->level-5) return 0; - if(battle_check_target(&md->bl,bl,BCT_ENEMY)<=0) + if(battle->check_target(&md->bl,bl,BCT_ENEMY)<=0) return 0; switch (bl->type) @@ -1084,7 +1085,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) dist = distance_bl(&md->bl, bl); if( ((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) && - battle_check_range(&md->bl,bl,md->db->range2) + battle->check_range(&md->bl,bl,md->db->range2) ) { //Pick closest target? if( map[bl->m].icewall_num && @@ -1121,12 +1122,11 @@ static int mob_ai_sub_hard_changechase(struct block_list *bl,va_list ap) //If can't seek yet, not an enemy, or you can't attack it, skip. if ((*target) == bl || - battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 || + battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 || !status_check_skilluse(&md->bl, bl, 0, 0)) return 0; - if(battle_check_range (&md->bl, bl, md->status.rhw.range)) - { + if(battle->check_range (&md->bl, bl, md->status.rhw.range)) { (*target) = bl; md->target_id=bl->id; md->min_chase= md->db->range3; @@ -1145,7 +1145,7 @@ static int mob_ai_sub_hard_bg_ally(struct block_list *bl,va_list ap) { md=va_arg(ap,struct mob_data *); target= va_arg(ap,struct block_list**); - if( status_check_skilluse(&md->bl, bl, 0, 0) && battle_check_target(&md->bl,bl,BCT_ENEMY)<=0 ) { + if( status_check_skilluse(&md->bl, bl, 0, 0) && battle->check_target(&md->bl,bl,BCT_ENEMY)<=0 ) { (*target) = bl; } return 1; @@ -1268,7 +1268,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) else if (ud->skilltarget) { tbl = map_id2bl(ud->skilltarget); //Required check as skilltarget is not always an enemy. [Skotlex] - if (tbl && battle_check_target(&md->bl, tbl, BCT_ENEMY) <= 0) + if (tbl && battle->check_target(&md->bl, tbl, BCT_ENEMY) <= 0) tbl = NULL; } if (tbl && status_check_skilluse(&md->bl, tbl, 0, 0)) { @@ -1406,9 +1406,7 @@ int mob_warpchase(struct mob_data *md, struct block_list *target) static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) { struct block_list *tbl = NULL, *abl = NULL; - int dist; int mode; - int search_size; int view_range, can_move; if(md->bl.prev == NULL || md->status.hp <= 0) @@ -1463,7 +1461,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) { if( md->attacked_id == md->target_id ) { //Rude attacked check. - if( !battle_check_range(&md->bl, tbl, md->status.rhw.range) + if( !battle->check_range(&md->bl, tbl, md->status.rhw.range) && ( //Can't attack back and can't reach back. (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] @@ -1481,11 +1479,12 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) else if( (abl = map_id2bl(md->attacked_id)) && (!tbl || mob_can_changetarget(md, abl, mode)) ) { + int dist; if( md->bl.m != abl->m || abl->prev == NULL || (dist = distance_bl(&md->bl, abl)) >= MAX_MINCHASE // Attacker longer than visual area - || battle_check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob + || battle->check_target(&md->bl, abl, BCT_ENEMY) <= 0 // Attacker is not enemy of mob || (battle_config.mob_ai&0x2 && !status_check_skilluse(&md->bl, abl, 0, 0)) // Cannot normal attack back to Attacker - || (!battle_check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ... + || (!battle->check_range(&md->bl, abl, md->status.rhw.range) // Not on Melee Range and ... && ( // Reach check (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0 && (battle_config.mob_ai&0x2 || (md->sc.data[SC_SPIDERWEB] && md->sc.data[SC_SPIDERWEB]->val1) || md->sc.data[SC_BITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNSTRAP] @@ -1511,7 +1510,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) else { //Attackable if (!tbl || dist < md->status.rhw.range || !check_distance_bl(&md->bl, tbl, dist) - || battle_gettarget(tbl) != md->bl.id) + || battle->get_target(tbl) != md->bl.id) { //Change if the new target is closer than the actual one //or if the previous target is not attacking the mob. [Skotlex] md->target_id = md->attacked_id; // set target @@ -1536,7 +1535,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) // Scan area for targets if (!tbl && mode&MD_LOOTER && md->lootitem && DIFF_TICK(tick, md->ud.canact_tick) > 0 && (md->lootitem_count < LOOTITEM_SIZE || battle_config.monster_loot_type != 1)) - { // Scan area for items to loot, avoid trying to loot of the mob is full and can't consume the items. + { // Scan area for items to loot, avoid trying to loot if the mob is full and can't consume the items. map_foreachinrange (mob_ai_sub_hard_lootsearch, &md->bl, view_range, BL_ITEM, md, &tbl); } @@ -1547,6 +1546,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) else if (mode&MD_CHANGECHASE && (md->state.skillstate == MSS_RUSH || md->state.skillstate == MSS_FOLLOW)) { + int search_size; search_size = view_range<md->status.rhw.range ? view_range:md->status.rhw.range; map_foreachinrange (mob_ai_sub_hard_changechase, &md->bl, search_size, DEFAULT_ENEMY_TYPE(md), md, &tbl); } @@ -1602,7 +1602,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) fitem = (struct flooritem_data *)tbl; //Logs items, taken by (L)ooter Mobs [Lupus] - log_pick_mob(md, LOG_TYPE_LOOT, fitem->item_data.amount, &fitem->item_data); + logs->pick_mob(md, LOG_TYPE_LOOT, fitem->item_data.amount, &fitem->item_data, NULL); if (md->lootitem_count < LOOTITEM_SIZE) { memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0])); @@ -1614,7 +1614,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) } if (pcdb_checkid(md->vd->class_)) { //Give them walk act/delay to properly mimic players. [Skotlex] - clif_takeitem(&md->bl,tbl); + clif->takeitem(&md->bl,tbl); md->ud.canact_tick = tick + md->status.amotion; unit_set_walkdelay(&md->bl, tick, md->status.amotion, 1); } @@ -1628,7 +1628,7 @@ static bool mob_ai_sub_hard(struct mob_data *md, unsigned int tick) if (md->ud.target == tbl->id && md->ud.attacktimer != INVALID_TIMER) //Already locked. return true; - if (battle_check_range (&md->bl, tbl, md->status.rhw.range)) + if (battle->check_range (&md->bl, tbl, md->status.rhw.range)) { //Target within range, engage if(tbl->type == BL_PC) @@ -1789,13 +1789,12 @@ static int mob_ai_hard(int tid, unsigned int tick, int id, intptr_t data) /*========================================== * Initializes the delay drop structure for mob-dropped items. *------------------------------------------*/ -static struct item_drop* mob_setdropitem(int nameid, int qty) -{ +static struct item_drop* mob_setdropitem(int nameid, int qty, struct item_data *data) { struct item_drop *drop = ers_alloc(item_drop_ers, struct item_drop); memset(&drop->item_data, 0, sizeof(struct item)); drop->item_data.nameid = nameid; drop->item_data.amount = qty; - drop->item_data.identify = itemdb_isidentified(nameid); + drop->item_data.identify = data ? itemdb_isidentified2(data) : itemdb_isidentified(nameid); drop->next = NULL; return drop; } @@ -1843,7 +1842,7 @@ static void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, str TBL_PC* sd; //Logs items, dropped by mobs [Lupus] - log_pick_mob(md, loot?LOG_TYPE_LOOT:LOG_TYPE_PICKDROP_MONSTER, -ditem->item_data.amount, &ditem->item_data); + logs->pick_mob(md, loot?LOG_TYPE_LOOT:LOG_TYPE_PICKDROP_MONSTER, -ditem->item_data.amount, &ditem->item_data, NULL); sd = map_charid2sd(dlist->first_charid); if( sd == NULL ) sd = map_charid2sd(dlist->second_charid); @@ -2038,8 +2037,7 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage) return; } //Call when a mob has received damage. -void mob_damage(struct mob_data *md, struct block_list *src, int damage) -{ +void mob_damage(struct mob_data *md, struct block_list *src, int damage) { if (damage > 0) { //Store total damage... if (UINT_MAX - (unsigned int)damage > md->tdmg) md->tdmg+=damage; @@ -2063,7 +2061,7 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) } if (battle_config.show_mob_info&3) - clif_charnameack (0, &md->bl); + clif->charnameack (0, &md->bl); if (!src) return; @@ -2072,9 +2070,11 @@ void mob_damage(struct mob_data *md, struct block_list *src, int damage) if( !(md->status.mode&MD_BOSS) ){ int i; for(i = 0; i < DAMAGELOG_SIZE; i++){ // must show hp bar to all char who already hit the mob. - struct map_session_data *sd = map_charid2sd(md->dmglog[i].id); - if( sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE) ) // check if in range - clif_monster_hp_bar(md, sd->fd); + if( md->dmglog[i].id ) { + struct map_session_data *sd = map_charid2sd(md->dmglog[i].id); + if( sd && check_distance_bl(&md->bl, &sd->bl, AREA_SIZE) ) // check if in range + clif->monster_hp_bar(md,sd); + } } } #endif @@ -2100,7 +2100,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) int id,zeny; unsigned int base_exp,job_exp; } pt[DAMAGELOG_SIZE]; - int i,temp,count,pnum=0,m=md->bl.m; + int i, temp, count, m = md->bl.m, pnum = 0; int dmgbltypes = 0; // bitfield of all bl types, that caused damage to the mob and are elligible for exp distribution unsigned int mvp_damage, tick = gettick(); bool rebirth, homkillonly; @@ -2114,7 +2114,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } if( md->guardian_data && md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS ) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); + guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number,0); if( src ) { // Use Dead skill only if not killed by Script or Command @@ -2142,13 +2142,12 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) count++; //Only logged into same map chars are counted for the total. if (pc_isdead(tsd)) continue; // skip dead players - if(md->dmglog[i].flag == MDLF_HOMUN && !merc_is_hom_active(tsd->hd)) + if(md->dmglog[i].flag == MDLF_HOMUN && !homun_alive(tsd->hd)) continue; // skip homunc's share if inactive if( md->dmglog[i].flag == MDLF_PET && (!tsd->status.pet_id || !tsd->pd) ) continue; // skip pet's share if inactive - if(md->dmglog[i].dmg > mvp_damage) - { + if(md->dmglog[i].dmg > mvp_damage) { third_sd = second_sd; second_sd = mvp_sd; mvp_sd = tsd; @@ -2157,8 +2156,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) tmpsd[i] = tsd; // record as valid damage-log entry - switch( md->dmglog[i].flag ) - { + switch( md->dmglog[i].flag ) { case MDLF_NORMAL: dmgbltypes|= BL_PC; break; case MDLF_HOMUN: dmgbltypes|= BL_HOM; break; case MDLF_PET: dmgbltypes|= BL_PET; break; @@ -2200,8 +2198,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if(battle_config.mobs_level_up && md->level > md->db->lv) // [Valaris] bonus += (md->level-md->db->lv)*battle_config.mobs_level_up_exp_rate; - for(i = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) - { + for(i = 0; i < DAMAGELOG_SIZE && md->dmglog[i].id; i++) { int flag=1,zeny=0; unsigned int base_exp, job_exp; double per; //Your share of the mob's exp @@ -2225,12 +2222,15 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } // change experience for different sized monsters [Valaris] - if (battle_config.mob_size_influence) - { - if (md->special_state.size == SZ_MEDIUM) - per /= 2.; - else if (md->special_state.size == SZ_BIG) - per *= 2.; + if (battle_config.mob_size_influence) { + switch( md->special_state.size ) { + case SZ_MEDIUM: + per /= 2.; + break; + case SZ_BIG: + per *= 2.; + break; + } } if( md->dmglog[i].flag == MDLF_PET ) @@ -2253,42 +2253,39 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) else job_exp = (unsigned int)cap_value(md->db->job_exp * per * bonus/100. * map[m].jexp/100., 1, UINT_MAX); - if ((temp = tmpsd[i]->status.party_id)>0 /*&& !md->dmglog[i].flag == MDLF_HOMUN*/) //Homun-done damage (flag 1) is given to party - { + if ( (temp = tmpsd[i]->status.party_id) > 0 ) { int j; - for(j=0;j<pnum && pt[j].id!=temp;j++); //Locate party. + for( j = 0; j < pnum && pt[j].id != temp; j++ ); //Locate party. - if(j==pnum){ //Possibly add party. + if( j == pnum ){ //Possibly add party. pt[pnum].p = party_search(temp); - if(pt[pnum].p && pt[pnum].p->party.exp) - { - pt[pnum].id=temp; - pt[pnum].base_exp=base_exp; - pt[pnum].job_exp=job_exp; - pt[pnum].zeny=zeny; // zeny share [Valaris] + if(pt[pnum].p && pt[pnum].p->party.exp) { + pt[pnum].id = temp; + pt[pnum].base_exp = base_exp; + pt[pnum].job_exp = job_exp; + pt[pnum].zeny = zeny; // zeny share [Valaris] pnum++; flag=0; } - }else{ //Add to total + } else { //Add to total if (pt[j].base_exp > UINT_MAX - base_exp) - pt[j].base_exp=UINT_MAX; + pt[j].base_exp = UINT_MAX; else - pt[j].base_exp+=base_exp; + pt[j].base_exp += base_exp; if (pt[j].job_exp > UINT_MAX - job_exp) - pt[j].job_exp=UINT_MAX; + pt[j].job_exp = UINT_MAX; else - pt[j].job_exp+=job_exp; + pt[j].job_exp += job_exp; pt[j].zeny+=zeny; // zeny share [Valaris] flag=0; } } + if(base_exp && md->dmglog[i].flag == MDLF_HOMUN) //tmpsd[i] is null if it has no homunc. + homun->gainexp(tmpsd[i]->hd, base_exp); if(flag) { - if(base_exp && md->dmglog[i].flag == MDLF_HOMUN) //tmpsd[i] is null if it has no homunc. - merc_hom_gainexp(tmpsd[i]->hd, base_exp); - if(base_exp || job_exp) - { + if(base_exp || job_exp) { if( md->dmglog[i].flag != MDLF_PET || battle_config.pet_attack_exp_to_master ) { #ifdef RENEWAL_EXP int rate = pc_level_penalty_mod(tmpsd[i], md, 1); @@ -2303,7 +2300,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } } - for(i=0;i<pnum;i++) //Party share. + for( i = 0; i < pnum; i++ ) //Party share. party_exp_share(pt[i].p, &md->bl, pt[i].base_exp,pt[i].job_exp,pt[i].zeny); } //End EXP giving. @@ -2385,7 +2382,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) continue; } - ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1); + ditem = mob_setdropitem(md->db->dropitem[i].nameid, 1, it); //A Rare Drop Global Announce by Lupus if( mvp_sd && drop_rate <= battle_config.rare_drop_announce ) { @@ -2401,7 +2398,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) // Ore Discovery [Celest] if (sd == mvp_sd && pc_checkskill(sd,BS_FINDINGORE)>0 && battle_config.finding_ore_rate/10 >= rnd()%10000) { - ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1); + ditem = mob_setdropitem(itemdb_searchrandomid(IG_FINDINGORE), 1, NULL); mob_item_drop(md, dlist, ditem, 0, battle_config.finding_ore_rate/10, homkillonly); } @@ -2431,7 +2428,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if (rnd()%10000 >= drop_rate) continue; itemid = (sd->add_drop[i].id > 0) ? sd->add_drop[i].id : itemdb_searchrandomid(sd->add_drop[i].group); - mob_item_drop(md, dlist, mob_setdropitem(itemid,1), 0, drop_rate, homkillonly); + mob_item_drop(md, dlist, mob_setdropitem(itemid,1,NULL), 0, drop_rate, homkillonly); } } @@ -2483,8 +2480,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) mexp = (unsigned int)cap_value(exp, 1, UINT_MAX); - clif_mvp_effect(mvp_sd); - clif_mvp_exp(mvp_sd,mexp); + clif->mvp_effect(mvp_sd); + clif->mvp_exp(mvp_sd,mexp); pc_gainexp(mvp_sd, &md->bl, mexp,0, false); log_mvp[1] = mexp; @@ -2507,9 +2504,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } for(i = 0; i < MAX_MVP_DROP; i++) { + struct item_data *data; if(mdrop_id[i] <= 0) continue; - if(!itemdb_exists(mdrop_id[i])) + if(! (data = itemdb_exists(mdrop_id[i])) ) continue; temp = mdrop_p[i]; @@ -2520,32 +2518,30 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) memset(&item,0,sizeof(item)); item.nameid=mdrop_id[i]; - item.identify= itemdb_isidentified(item.nameid); - clif_mvp_item(mvp_sd,item.nameid); + item.identify= itemdb_isidentified2(data); + clif->mvp_item(mvp_sd,item.nameid); log_mvp[0] = item.nameid; //A Rare MVP Drop Global Announce by Lupus if(temp<=battle_config.rare_drop_announce) { - struct item_data *i_data; char message[128]; - i_data = itemdb_exists(item.nameid); - sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, i_data->jname, temp/100.); + sprintf (message, msg_txt(541), mvp_sd->status.name, md->name, data->jname, temp/100.); //MSG: "'%s' won %s's %s (chance: %0.02f%%)" intif_broadcast(message,strlen(message)+1,0); } if((temp = pc_additem(mvp_sd,&item,1,LOG_TYPE_PICKDROP_PLAYER)) != 0) { - clif_additem(mvp_sd,0,0,temp); + clif->additem(mvp_sd,0,0,temp); map_addflooritem(&item,1,mvp_sd->bl.m,mvp_sd->bl.x,mvp_sd->bl.y,mvp_sd->status.char_id,(second_sd?second_sd->status.char_id:0),(third_sd?third_sd->status.char_id:0),1); } //Logs items, MVP prizes [Lupus] - log_pick_mob(md, LOG_TYPE_MVP, -1, &item); + logs->pick_mob(md, LOG_TYPE_MVP, -1, &item, data); break; } } - log_mvpdrop(mvp_sd, md->class_, log_mvp); + logs->mvpdrop(mvp_sd, md->class_, log_mvp); } if (type&2 && !sd && md->class_ == MOBID_EMPERIUM) @@ -2571,7 +2567,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) sd->mission_mobid = temp; pc_setglobalreg(sd,"TK_MISSION_ID", temp); sd->mission_count = 0; - clif_mission_info(sd, temp, 0); + clif->mission_info(sd, temp, 0); } pc_setglobalreg(sd,"TK_MISSION_COUNT", sd->mission_count); } @@ -2618,14 +2614,14 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if( pcdb_checkid(md->vd->class_) ) {//Player mobs are not removed automatically by the client. /* first we set them dead, then we delay the outsight effect */ - clif_clearunit_area(&md->bl,CLR_DEAD); - clif_clearunit_delayed(&md->bl, CLR_OUTSIGHT,tick+3000); + clif->clearunit_area(&md->bl,CLR_DEAD); + clif->clearunit_delayed(&md->bl, CLR_OUTSIGHT,tick+3000); } else /** * We give the client some time to breath and this allows it to display anything it'd like with the dead corpose * For example, this delay allows it to display soul drain effect **/ - clif_clearunit_delayed(&md->bl, CLR_DEAD, tick+250); + clif->clearunit_delayed(&md->bl, CLR_DEAD, tick+250); } @@ -2636,8 +2632,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) if (battle_config.mvp_tomb_enabled && md->spawn->state.boss) mvptomb_create(md, mvp_sd ? mvp_sd->status.name : NULL, time(NULL)); - if( !rebirth ) + if( !rebirth ) { + status_change_clear(&md->bl,1); mob_setdelayspawn(md); //Set respawning. + } return 3; //Remove from map. } @@ -2653,11 +2651,11 @@ void mob_revive(struct mob_data *md, unsigned int hp) md->tdmg = 0; if (!md->bl.prev) map_addblock(&md->bl); - clif_spawn(&md->bl); - skill_unit_move(&md->bl,tick,1); + clif->spawn(&md->bl); + skill->unit_move(&md->bl,tick,1); mobskill_use(md, tick, MSC_SPAWN); if (battle_config.show_mob_info&3) - clif_charnameack (0, &md->bl); + clif->charnameack (0, &md->bl); } int mob_guardian_guildchange(struct mob_data *md) @@ -2677,25 +2675,25 @@ int mob_guardian_guildchange(struct mob_data *md) md->guardian_data->guild_name[0] = '\0'; } else { if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS && md->guardian_data->castle->guardian[md->guardian_data->number].visible) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); + guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); unit_free(&md->bl,CLR_OUTSIGHT); //Remove guardian. } return 0; } - g = guild_search(md->guardian_data->castle->guild_id); + g = guild->search(md->guardian_data->castle->guild_id); if (g == NULL) { //Properly remove guardian info from Castle data. ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->guild_id); if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS) - guild_castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); + guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0); unit_free(&md->bl,CLR_OUTSIGHT); return 0; } md->guardian_data->guild_id = g->guild_id; md->guardian_data->emblem_id = g->emblem_id; - md->guardian_data->guardup_lv = guild_checkskill(g,GD_GUARDUP); + md->guardian_data->guardup_lv = guild->checkskill(g,GD_GUARDUP); memcpy(md->guardian_data->guild_name, g->name, NAME_LENGTH); return 1; @@ -2764,7 +2762,7 @@ int mob_class_change (struct mob_data *md, int class_) mob_stop_walking(md, 0); unit_skillcastcancel(&md->bl, 0); status_set_viewdata(&md->bl, class_); - clif_mob_class_change(md,md->vd->class_); + clif->class_change(&md->bl, md->vd->class_, 1); status_calc_mob(md, 1); md->ud.state.speed_changed = 1; //Speed change update. @@ -2786,7 +2784,7 @@ int mob_class_change (struct mob_data *md, int class_) md->target_id = md->attacked_id = 0; //Need to update name display. - clif_charnameack(0, &md->bl); + clif->charnameack(0, &md->bl); status_change_end(&md->bl,SC_KEEPING,INVALID_TIMER); return 0; } @@ -2797,7 +2795,7 @@ int mob_class_change (struct mob_data *md, int class_) void mob_heal(struct mob_data *md,unsigned int heal) { if (battle_config.show_mob_info&3) - clif_charnameack (0, &md->bl); + clif->charnameack (0, &md->bl); } /*========================================== @@ -2947,7 +2945,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id) } } - clif_skill_nodamage(&md->bl,&md->bl,skill_id,amount,1); + clif->skill_nodamage(&md->bl,&md->bl,skill_id,amount,1); } return 0; @@ -2989,7 +2987,7 @@ int mob_getfriendhprate_sub(struct block_list *bl,va_list ap) if ((*fr) != NULL) //A friend was already found. return 0; - if (battle_check_target(&md->bl,bl,BCT_ENEMY)>0) + if (battle->check_target(&md->bl,bl,BCT_ENEMY)>0) return 0; rate = get_percentage(status_get_hp(bl), status_get_max_hp(bl)); @@ -3041,7 +3039,7 @@ int mob_getfriendstatus_sub(struct block_list *bl,va_list ap) if( mmd->bl.id == bl->id && !(battle_config.mob_ai&0x10) ) return 0; - if (battle_check_target(&mmd->bl,bl,BCT_ENEMY)>0) + if (battle->check_target(&mmd->bl,bl,BCT_ENEMY)>0) return 0; cond1=va_arg(ap,int); cond2=va_arg(ap,int); @@ -3178,13 +3176,12 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) continue; //Skill requisite failed to be fulfilled. //Execute skill - if (skill_get_casttype(ms[i].skill_id) == CAST_GROUND) - { //Ground skill. + if (skill->get_casttype(ms[i].skill_id) == CAST_GROUND) {//Ground skill. short x, y; switch (ms[i].target) { case MST_RANDOM: //Pick a random enemy within skill range. - bl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), - skill_get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); + bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), + skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); break; case MST_TARGET: case MST_AROUND5: @@ -3219,7 +3216,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) } md->skill_idx = i; map_freeblock_lock(); - if( !battle_check_range(&md->bl,bl,skill_get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || + if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || !unit_skilluse_pos2(&md->bl, x, y,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) ) { map_freeblock_unlock(); @@ -3229,8 +3226,8 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) //Targetted skill switch (ms[i].target) { case MST_RANDOM: //Pick a random enemy within skill range. - bl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md), - skill_get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); + bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), + skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv)); break; case MST_TARGET: bl = map_id2bl(md->target_id); @@ -3257,7 +3254,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) md->skill_idx = i; map_freeblock_lock(); - if( !battle_check_range(&md->bl,bl,skill_get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || + if( !battle->check_range(&md->bl,bl,skill->get_range2(&md->bl, ms[i].skill_id,ms[i].skill_lv)) || !unit_skilluse_id2(&md->bl, bl->id,ms[i].skill_id, ms[i].skill_lv,ms[i].casttime, ms[i].cancel) ) { map_freeblock_unlock(); @@ -3272,7 +3269,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) snprintf(name, sizeof name,"%s", md->name); strtok(name, "#"); // discard extra name identifier if present [Daegaladh] snprintf(temp, sizeof temp,"%s : %s", name, mc->msg); - clif_messagecolor(&md->bl, mc->color, temp); + clif->messagecolor(&md->bl, mc->color, temp); } if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill. for (j = 0; j < md->db->maxskill; j++) @@ -3314,7 +3311,7 @@ int mobskill_event(struct mob_data *md, struct block_list *src, unsigned int tic //Restore previous target only if skill condition failed to trigger. [Skotlex] md->target_id = target_id; //Otherwise check if the target is an enemy, and unlock if needed. - else if (battle_check_target(&md->bl, src, BCT_ENEMY) <= 0) + else if (battle->check_target(&md->bl, src, BCT_ENEMY) <= 0) md->target_id = target_id; return res; @@ -3338,7 +3335,7 @@ int mob_is_clone(int class_) int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, const char *event, int master_id, int mode, int flag, unsigned int duration) { int class_; - int i,j,inf,skill_id, fd; + int i,j,h,inf,skill_id, fd; struct mob_data *md; struct mob_skill *ms; struct mob_db* db; @@ -3390,49 +3387,56 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons //Go Backwards to give better priority to advanced skills. for (i=0,j = MAX_SKILL_TREE-1;j>=0 && i< MAX_MOBSKILL ;j--) { + int idx = skill_tree[pc_class2idx(sd->status.class_)][j].idx; skill_id = skill_tree[pc_class2idx(sd->status.class_)][j].id; - if (!skill_id || sd->status.skill[skill_id].lv < 1 || - (skill_get_inf2(skill_id)&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) || - skill_get_nocast(skill_id)&16 + if (!skill_id || sd->status.skill[idx].lv < 1 || + (skill_db[idx].inf2&(INF2_WEDDING_SKILL|INF2_GUILD_SKILL)) ) continue; + for(h = 0; h < map[sd->bl.m].zone->disabled_skills_count; h++) { + if( skill_id == map[sd->bl.m].zone->disabled_skills[h]->nameid && map[sd->bl.m].zone->disabled_skills[h]->subtype == MZS_CLONE ) { + break; + } + } + if( h < map[sd->bl.m].zone->disabled_skills_count ) + continue; //Normal aggressive mob, disable skills that cannot help them fight //against players (those with flags UF_NOMOB and UF_NOPC are specific //to always aid players!) [Skotlex] if (!(flag&1) && - skill_get_unit_id(skill_id, 0) && - skill_get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC)) + skill->get_unit_id(skill_id, 0) && + skill->get_unit_flag(skill_id)&(UF_NOMOB|UF_NOPC)) continue; /** * The clone should be able to cast the skill (e.g. have the required weapon) bugreport:5299) **/ - if( !skill_check_condition_castbegin(sd,skill_id,sd->status.skill[skill_id].lv) ) + if( !skill->check_condition_castbegin(sd,skill_id,sd->status.skill[idx].lv) ) continue; memset (&ms[i], 0, sizeof(struct mob_skill)); ms[i].skill_id = skill_id; - ms[i].skill_lv = sd->status.skill[skill_id].lv; + ms[i].skill_lv = sd->status.skill[idx].lv; ms[i].state = MSS_ANY; ms[i].permillage = 500*battle_config.mob_skill_rate/100; //Default chance of all skills: 5% ms[i].emotion = -1; ms[i].cancel = 0; - ms[i].casttime = skill_castfix(&sd->bl,skill_id, ms[i].skill_lv); - ms[i].delay = 5000+skill_delayfix(&sd->bl,skill_id, ms[i].skill_lv); + ms[i].casttime = skill->cast_fix(&sd->bl,skill_id, ms[i].skill_lv); + ms[i].delay = 5000+skill->delay_fix(&sd->bl,skill_id, ms[i].skill_lv); - inf = skill_get_inf(skill_id); + inf = skill_db[idx].inf; if (inf&INF_ATTACK_SKILL) { ms[i].target = MST_TARGET; ms[i].cond1 = MSC_ALWAYS; - if (skill_get_range(skill_id, ms[i].skill_lv) > 3) + if (skill->get_range(skill_id, ms[i].skill_lv) > 3) ms[i].state = MSS_ANYTARGET; else ms[i].state = MSS_BERSERK; } else if(inf&INF_GROUND_SKILL) { - if (skill_get_inf2(skill_id)&INF2_TRAP) { //Traps! + if (skill->get_inf2(skill_id)&INF2_TRAP) { //Traps! ms[i].state = MSS_IDLE; ms[i].target = MST_AROUND2; ms[i].delay = 60000; - } else if (skill_get_unit_target(skill_id) == BCT_ENEMY) { //Target Enemy + } else if (skill->get_unit_target(skill_id) == BCT_ENEMY) { //Target Enemy ms[i].state = MSS_ANYTARGET; ms[i].target = MST_TARGET; ms[i].cond1 = MSC_ALWAYS; @@ -3442,10 +3446,10 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons ms[i].cond2 = 95; } } else if (inf&INF_SELF_SKILL) { - if (skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF) { //auto-select target skill. + if (skill->get_inf2(skill_id)&INF2_NO_TARGET_SELF) { //auto-select target skill. ms[i].target = MST_TARGET; ms[i].cond1 = MSC_ALWAYS; - if (skill_get_range(skill_id, ms[i].skill_lv) > 3) { + if (skill->get_range(skill_id, ms[i].skill_lv) > 3) { ms[i].state = MSS_ANYTARGET; } else { ms[i].state = MSS_BERSERK; @@ -3456,7 +3460,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons ms[i].cond2 = 90; ms[i].permillage = 2000; //Delay: Remove the stock 5 secs and add half of the support time. - ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2; + ms[i].delay += -5000 +(skill->get_time(skill_id, ms[i].skill_lv) + skill->get_time2(skill_id, ms[i].skill_lv))/2; if (ms[i].delay < 5000) ms[i].delay = 5000; //With a minimum of 5 secs. } @@ -3469,7 +3473,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons else if (skill_id == ALL_RESURRECTION) ms[i].cond2 = 1; //Delay: Remove the stock 5 secs and add half of the support time. - ms[i].delay += -5000 +(skill_get_time(skill_id, ms[i].skill_lv) + skill_get_time2(skill_id, ms[i].skill_lv))/2; + ms[i].delay += -5000 +(skill->get_time(skill_id, ms[i].skill_lv) + skill->get_time2(skill_id, ms[i].skill_lv))/2; if (ms[i].delay < 2000) ms[i].delay = 2000; //With a minimum of 2 secs. @@ -3619,9 +3623,9 @@ static unsigned int mob_drop_adjust(int baserate, int rate_adjust, unsigned shor */ static void item_dropratio_adjust(int nameid, int mob_id, int *rate_adjust) { - int i; if( item_drop_ratio_db[nameid] ) { if( item_drop_ratio_db[nameid]->mob_id[0] ) { // only for listed mobs + int i; ARR_FIND(0, MAX_ITEMRATIO_MOBS, i, item_drop_ratio_db[nameid]->mob_id[i] == mob_id); if(i < MAX_ITEMRATIO_MOBS) // found *rate_adjust = item_drop_ratio_db[nameid]->drop_ratio; @@ -3772,7 +3776,6 @@ static bool mob_parse_dbrow(char** str) // MVP Drops: MVP1id,MVP1per,MVP2id,MVP2per,MVP3id,MVP3per for(i = 0; i < MAX_MVP_DROP; i++) { - struct item_data *id; int rate_adjust = battle_config.item_rate_mvp;; db->mvpitem[i].nameid = atoi(str[31+i*2]); if (!db->mvpitem[i].nameid) { @@ -3784,6 +3787,7 @@ static bool mob_parse_dbrow(char** str) //calculate and store Max available drop chance of the MVP item if (db->mvpitem[i].p) { + struct item_data *id; id = itemdb_search(db->mvpitem[i].nameid); if (id->maxchance == -1 || (id->maxchance < db->mvpitem[i].p/10 + 1) ) { //item has bigger drop chance or sold in shops @@ -3893,10 +3897,9 @@ static void mob_readdb(void) for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { - char path[256]; - if(fi > 0) { + char path[256]; sprintf(path, "%s/%s", db_path, filename[fi]); if(!exists(path)) { @@ -3904,7 +3907,7 @@ static void mob_readdb(void) } } - sv_readdb(db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub); + sv->readdb(db_path, filename[fi], ',', 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, 31+2*MAX_MVP_DROP+2*MAX_MOB_DROP, -1, &mob_readdb_sub); } } @@ -3920,13 +3923,13 @@ static int mob_read_sqldb(void) uint32 lines = 0, count = 0; // retrieve all rows from the mob database - if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) { + if( SQL_ERROR == SQL->Query(mmysql_handle, "SELECT * FROM `%s`", mob_db_name[fi]) ) { Sql_ShowDebug(mmysql_handle); continue; } // process rows one by one - while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) { + while( SQL_SUCCESS == SQL->NextRow(mmysql_handle) ) { // wrap the result into a TXT-compatible format char line[1024]; char* str[31+2*MAX_MVP_DROP+2*MAX_MOB_DROP]; @@ -3938,7 +3941,7 @@ static int mob_read_sqldb(void) { char* data; size_t len; - Sql_GetData(mmysql_handle, i, &data, &len); + SQL->GetData(mmysql_handle, i, &data, &len); strcpy(p, data); str[i] = p; @@ -3952,7 +3955,7 @@ static int mob_read_sqldb(void) } // free the query result - Sql_FreeResult(mmysql_handle); + SQL->FreeResult(mmysql_handle); ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_db_name[fi]); } @@ -4018,8 +4021,8 @@ static int mob_read_randommonster(void) memset(&summon, 0, sizeof(summon)); - for( i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER; i++ ) - { + for( i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER; i++ ) { + unsigned int count = 0; mob_db_data[0]->summonper[i] = 1002; // Default fallback value, in case the database does not provide one sprintf(line, "%s/%s", db_path, mobfile[i]); fp=fopen(line,"r"); @@ -4045,6 +4048,7 @@ static int mob_read_randommonster(void) class_ = atoi(str[0]); if(mob_db(class_) == mob_dummy) continue; + count++; mob_db_data[class_]->summonper[i]=atoi(str[2]); if (i) { if( summon[i].qty < ARRAYLENGTH(summon[i].class_) ) //MvPs @@ -4055,13 +4059,12 @@ static int mob_read_randommonster(void) } } } - if (i && !summon[i].qty) - { //At least have the default here. + if (i && !summon[i].qty) { //At least have the default here. summon[i].class_[0] = mob_db_data[0]->summonper[i]; summon[i].qty = 1; } fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n",mobfile[i]); + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n",count,mobfile[i]); } return 0; } @@ -4120,7 +4123,7 @@ static bool mob_parse_row_chatdb(char** str, const char* source, int line, int* } msg[len] = 0; // strip previously found EOL - strncpy(ms->msg, str[2], CHAT_SIZE_MAX); + safestrncpy(ms->msg, str[2], CHAT_SIZE_MAX); return true; } @@ -4178,7 +4181,7 @@ static void mob_readchatdb(void) count++; } fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n", arc); + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, arc); } /*========================================== @@ -4262,6 +4265,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current) struct mob_skill *ms, gms; int mob_id; int i =0, j, tmp; + uint16 sidx = 0; mob_id = atoi(str[0]); @@ -4308,8 +4312,7 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current) //Skill ID j=atoi(str[3]); - if (j<=0 || j>MAX_SKILL_DB) //fixed Lupus - { + if ( !(sidx = skill->get_index(j) ) ) { if (mob_id < 0) ShowError("mob_parse_row_mobskilldb: Invalid Skill ID (%d) for all mobs\n", j); else @@ -4351,18 +4354,16 @@ static bool mob_parse_row_mobskilldb(char** str, int columns, int current) } //Check that the target condition is right for the skill type. [Skotlex] - if (skill_get_casttype(ms->skill_id) == CAST_GROUND) - { //Ground skill. - if (ms->target > MST_AROUND) - { + if ( skill->get_casttype2(sidx) == CAST_GROUND) {//Ground skill. + if (ms->target > MST_AROUND) { ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target for ground skill %d (%s) for %s.\n", - ms->skill_id, skill_get_name(ms->skill_id), + ms->skill_id, skill_db[sidx].name, mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite); ms->target = MST_TARGET; } } else if (ms->target > MST_MASTER) { ShowWarning("mob_parse_row_mobskilldb: Wrong mob skill target 'around' for non-ground skill %d (%s) for %s.\n", - ms->skill_id, skill_get_name(ms->skill_id), + ms->skill_id, skill_db[sidx].name, mob_id < 0?"all mobs":mob_db_data[mob_id]->sprite); ms->target = MST_TARGET; } @@ -4460,10 +4461,9 @@ static void mob_readskilldb(void) { for( fi = 0; fi < ARRAYLENGTH(filename); ++fi ) { - char path[256]; - if(fi > 0) { + char path[256]; sprintf(path, "%s/%s", db_path, filename[fi]); if(!exists(path)) { @@ -4471,7 +4471,7 @@ static void mob_readskilldb(void) { } } - sv_readdb(db_path, filename[fi], ',', 19, 19, -1, &mob_parse_row_mobskilldb); + sv->readdb(db_path, filename[fi], ',', 19, 19, -1, &mob_parse_row_mobskilldb); } } @@ -4495,13 +4495,13 @@ static int mob_read_sqlskilldb(void) uint32 lines = 0, count = 0; // retrieve all rows from the mob skill database - if( SQL_ERROR == Sql_Query(mmysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi]) ) { + if( SQL_ERROR == SQL->Query(mmysql_handle, "SELECT * FROM `%s`", mob_skill_db_name[fi]) ) { Sql_ShowDebug(mmysql_handle); continue; } // process rows one by one - while( SQL_SUCCESS == Sql_NextRow(mmysql_handle) ) { + while( SQL_SUCCESS == SQL->NextRow(mmysql_handle) ) { // wrap the result into a TXT-compatible format char* str[19]; char* dummy = ""; @@ -4509,7 +4509,7 @@ static int mob_read_sqlskilldb(void) ++lines; for( i = 0; i < 19; ++i ) { - Sql_GetData(mmysql_handle, i, &str[i], NULL); + SQL->GetData(mmysql_handle, i, &str[i], NULL); if( str[i] == NULL ) str[i] = dummy; // get rid of NULL columns } @@ -4520,7 +4520,7 @@ static int mob_read_sqlskilldb(void) } // free the query result - Sql_FreeResult(mmysql_handle); + SQL->FreeResult(mmysql_handle); ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", count, mob_skill_db_name[fi]); } @@ -4561,11 +4561,9 @@ static bool mob_readdb_race2(char* fields[], int columns, int current) static bool mob_readdb_itemratio(char* str[], int columns, int current) { int nameid, ratio, i; - struct item_data *id; - nameid = atoi(str[0]); - if( ( id = itemdb_exists(nameid) ) == NULL ) + if( itemdb_exists(nameid) == NULL ) { ShowWarning("itemdb_read_itemratio: Invalid item id %d.\n", nameid); return false; @@ -4588,7 +4586,7 @@ static bool mob_readdb_itemratio(char* str[], int columns, int current) */ static void mob_load(void) { - sv_readdb(db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio); // must be read before mobdb + sv->readdb(db_path, "mob_item_ratio.txt", ',', 2, 2+MAX_ITEMRATIO_MOBS, -1, &mob_readdb_itemratio); // must be read before mobdb mob_readchatdb(); if (db_use_sqldbs) { @@ -4600,9 +4598,9 @@ static void mob_load(void) mob_readdb(); mob_readskilldb(); } - sv_readdb(db_path, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail); + sv->readdb(db_path, "mob_avail.txt", ',', 2, 12, -1, &mob_readdb_mobavail); mob_read_randommonster(); - sv_readdb(db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, &mob_readdb_race2); + sv->readdb(db_path, DBPATH"mob_race2_db.txt", ',', 2, 20, -1, &mob_readdb_race2); } void mob_reload(void) { diff --git a/src/map/npc.c b/src/map/npc.c index 5d8a0274e..090c03e58 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -95,6 +96,7 @@ static DBMap *npc_path_db; //For holding the view data of npc classes. [Skotlex] static struct view_data npc_viewdb[MAX_NPC_CLASS]; +static struct view_data npc_viewdb2[MAX_NPC_CLASS2_END-MAX_NPC_CLASS2_START]; static struct script_event_s { //Holds pointers to the commonly executed scripts for speedup. [Skotlex] @@ -107,11 +109,34 @@ struct view_data* npc_get_viewdata(int class_) { //Returns the viewdata for normal npc classes. if( class_ == INVISIBLE_CLASS ) return &npc_viewdb[0]; - if (npcdb_checkid(class_) || class_ == WARP_CLASS) - return &npc_viewdb[class_]; + if (npcdb_checkid(class_) || class_ == WARP_CLASS){ + if( class_ > MAX_NPC_CLASS2_START ){ + return &npc_viewdb2[class_-MAX_NPC_CLASS2_START]; + }else{ + return &npc_viewdb[class_]; + } + } return NULL; } +static int npc_isnear_sub(struct block_list* bl, va_list args) { + struct npc_data *nd = (struct npc_data*)bl; + + if( nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE) ) + return 0; + + return 1; +} + +bool npc_isnear(struct block_list * bl) { + + if( battle_config.min_npc_vendchat_distance > 0 && + map_foreachinrange(npc_isnear_sub,bl, battle_config.min_npc_vendchat_distance, BL_NPC) ) + return true; + + return false; +} + int npc_ontouch_event(struct map_session_data *sd, struct npc_data *nd) { char name[EVENT_NAME_LENGTH]; @@ -180,24 +205,24 @@ int npc_enable(const char* name, int flag) if (flag&1) { nd->sc.option&=~OPTION_INVISIBLE; - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); } else if (flag&2) nd->sc.option&=~OPTION_HIDE; else if (flag&4) nd->sc.option|= OPTION_HIDE; else { //Can't change the view_data to invisible class because the view_data for all npcs is shared! [Skotlex] nd->sc.option|= OPTION_INVISIBLE; - clif_clearunit_area(&nd->bl,CLR_OUTSIGHT); // Hack to trick maya purple card [Xazax] + clif->clearunit_area(&nd->bl,CLR_OUTSIGHT); // Hack to trick maya purple card [Xazax] } if (nd->class_ == WARP_CLASS || nd->class_ == FLAG_CLASS) { //Client won't display option changes for these classes [Toms] if (nd->sc.option&(OPTION_HIDE|OPTION_INVISIBLE)) - clif_clearunit_area(&nd->bl, CLR_OUTSIGHT); + clif->clearunit_area(&nd->bl, CLR_OUTSIGHT); else - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); } else - clif_changeoption(&nd->bl); + clif->changeoption(&nd->bl); if( flag&3 && (nd->u.scr.xs >= 0 || nd->u.scr.ys >= 0) ) //check if player standing on a OnTouchArea map_foreachinarea( npc_enable_sub, nd->bl.m, nd->bl.x-nd->u.scr.xs, nd->bl.y-nd->u.scr.ys, nd->bl.x+nd->u.scr.xs, nd->bl.y+nd->u.scr.ys, BL_PC, nd ); @@ -215,26 +240,41 @@ struct npc_data* npc_name2id(const char* name) /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT /** * Timer to check for idle time and timeout the dialog if necessary **/ int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data* sd = NULL; + unsigned int timeout = NPC_SECURE_TIMEOUT_NEXT; if( (sd = map_id2sd(id)) == NULL || !sd->npc_id ) { if( sd ) sd->npc_idle_timer = INVALID_TIMER; return 0;//Not logged in anymore OR no longer attached to a npc } - if( DIFF_TICK(tick,sd->npc_idle_tick) > (SECURE_NPCTIMEOUT*1000) ) { + + switch( sd->npc_idle_type ) { + case NPCT_INPUT: + timeout = NPC_SECURE_TIMEOUT_INPUT; + break; + case NPCT_MENU: + timeout = NPC_SECURE_TIMEOUT_MENU; + break; + //case NPCT_WAIT: var starts with this value + } + + if( DIFF_TICK(tick,sd->npc_idle_tick) > (timeout*1000) ) { /** * If we still have the NPC script attached, tell it to stop. **/ if( sd->st ) sd->st->state = END; + sd->state.menu_or_input = 0; + sd->npc_menu = 0; + /** * This guy's been idle for longer than allowed, close him. **/ - clif_scriptclose(sd,sd->npc_id); + clif->scriptclose(sd,sd->npc_id); sd->npc_idle_timer = INVALID_TIMER; } else //Create a new instance of ourselves to continue sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0); @@ -252,7 +292,7 @@ int npc_event_dequeue(struct map_session_data* sd) if(sd->npc_id) { //Current script is aborted. if(sd->state.using_fake_npc){ - clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); + clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); sd->state.using_fake_npc = 0; } if (sd->st) { @@ -313,7 +353,7 @@ int npc_event_doall_sub(DBKey key, DBData *data, va_list ap) const char* name; int rid; - nullpo_ret(ev = db_data2ptr(data)); + nullpo_ret(ev = DB->data2ptr(data)); nullpo_ret(c = va_arg(ap, int *)); nullpo_ret(name = va_arg(ap, const char *)); rid = va_arg(ap, int); @@ -341,7 +381,7 @@ static int npc_event_do_sub(DBKey key, DBData *data, va_list ap) int* c; const char* name; - nullpo_ret(ev = db_data2ptr(data)); + nullpo_ret(ev = DB->data2ptr(data)); nullpo_ret(c = va_arg(ap, int *)); nullpo_ret(name = va_arg(ap, const char *)); @@ -488,7 +528,6 @@ struct timer_event_data { *------------------------------------------*/ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) { - int next; int old_rid, old_timer; unsigned int old_tick; struct npc_data* nd=(struct npc_data *)map_id2bl(id); @@ -526,6 +565,7 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) ted->next++; if( nd->u.scr.timeramount > ted->next ) { + int next; next = nd->u.scr.timer_event[ ted->next ].timer - nd->u.scr.timer_event[ ted->next - 1 ].timer; ted->time += next; if( sd ) @@ -560,10 +600,9 @@ int npc_timerevent(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ int npc_timerevent_start(struct npc_data* nd, int rid) { - int j, next; + int j; unsigned int tick = gettick(); struct map_session_data *sd = NULL; //Player to whom script is attached. - struct timer_event_data *ted; nullpo_ret(nd); @@ -587,6 +626,8 @@ int npc_timerevent_start(struct npc_data* nd, int rid) if (j < nd->u.scr.timeramount) { + int next; + struct timer_event_data *ted; // Arrange for the next event ted = ers_alloc(timer_event_ers, struct timer_event_data); ted->next = j; // Set event index @@ -947,7 +988,7 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y) struct unit_data *ud = unit_bl2ud(&sd->bl); if( ud && ud->walkpath.path_pos < ud->walkpath.path_len ) { // Since walktimer always == INVALID_TIMER at this time, we stop walking manually. [Inkfish] - clif_fixpos(&sd->bl); + clif->fixpos(&sd->bl); ud->walkpath.path_pos = ud->walkpath.path_len; } sd->areanpc_id = map[m].npc[i]->bl.id; @@ -1118,7 +1159,7 @@ int npc_globalmessage(const char* name, const char* mes) return 0; snprintf(temp, sizeof(temp), "%s : %s", name, mes); - clif_GlobalMessage(&nd->bl,temp); + clif->GlobalMessage(&nd->bl,temp); return 0; } @@ -1133,19 +1174,19 @@ void run_tomb(struct map_session_data* sd, struct npc_data* nd) // TODO: Find exact color? snprintf(buffer, sizeof(buffer), msg_txt(657), nd->u.tomb.md->db->name); - clif_scriptmes(sd, nd->bl.id, buffer); + clif->scriptmes(sd, nd->bl.id, buffer); - clif_scriptmes(sd, nd->bl.id, msg_txt(658)); + clif->scriptmes(sd, nd->bl.id, msg_txt(658)); snprintf(buffer, sizeof(buffer), msg_txt(659), time); - clif_scriptmes(sd, nd->bl.id, buffer); + clif->scriptmes(sd, nd->bl.id, buffer); - clif_scriptmes(sd, nd->bl.id, msg_txt(660)); + clif->scriptmes(sd, nd->bl.id, msg_txt(660)); snprintf(buffer, sizeof(buffer), msg_txt(661), nd->u.tomb.killer_name[0] ? nd->u.tomb.killer_name : "Unknown"); - clif_scriptmes(sd, nd->bl.id, buffer); + clif->scriptmes(sd, nd->bl.id, buffer); - clif_scriptclose(sd, nd->bl.id); + clif->scriptclose(sd, nd->bl.id); } /*========================================== @@ -1170,10 +1211,10 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) switch(nd->subtype) { case SHOP: - clif_npcbuysell(sd,nd->bl.id); + clif->npcbuysell(sd,nd->bl.id); break; case CASHSHOP: - clif_cashshop_show(sd,nd); + clif->cashshop_show(sd,nd); break; case SCRIPT: run_script(nd->u.scr.script,0,sd->bl.id,nd->bl.id); @@ -1189,7 +1230,7 @@ int npc_click(struct map_session_data* sd, struct npc_data* nd) /*========================================== * *------------------------------------------*/ -int npc_scriptcont(struct map_session_data* sd, int id) +int npc_scriptcont(struct map_session_data* sd, int id, bool closing) { nullpo_retr(1, sd); @@ -1211,7 +1252,7 @@ int npc_scriptcont(struct map_session_data* sd, int id) /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT /** * Update the last NPC iteration **/ @@ -1224,6 +1265,9 @@ int npc_scriptcont(struct map_session_data* sd, int id) if( sd->progressbar.npc_id && DIFF_TICK(sd->progressbar.timeout,gettick()) > 0 ) return 1; + if( closing && sd->st->state == CLOSE ) + sd->st->state = END; + run_script_main(sd->st); return 0; @@ -1259,9 +1303,9 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) sd->npc_shopid = id; if (type==0) { - clif_buylist(sd,nd); + clif->buylist(sd,nd); } else { - clif_selllist(sd); + clif->selllist(sd); } return 0; } @@ -1457,12 +1501,12 @@ int npc_cashshop_buy(struct map_session_data *sd, int nameid, int amount, int po /// Player item purchase from npc shop. /// /// @param item_list 'n' pairs <amount,itemid> -/// @return result code for clif_parse_NpcBuyListSend +/// @return result code for clif->parse_NpcBuyListSend int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) { struct npc_data* nd; double z; - int i,j,w,skill,new_; + int i,j,w,skill_t,new_, idx = skill->get_index(MC_DISCOUNT); nullpo_retr(3, sd); nullpo_retr(3, item_list); @@ -1477,8 +1521,7 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) w = 0; new_ = 0; // process entries in buy list, one by one - for( i = 0; i < n; ++i ) - { + for( i = 0; i < n; ++i ) { int nameid, amount, value; // find this entry in the shop's sell list @@ -1497,20 +1540,19 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) if( !itemdb_exists(nameid) ) return 3; // item no longer in itemdb - if( !itemdb_isstackable(nameid) && amount > 1 ) - { //Exploit? You can't buy more than 1 of equipment types o.O + if( !itemdb_isstackable(nameid) && amount > 1 ) { + //Exploit? You can't buy more than 1 of equipment types o.O ShowWarning("Player %s (%d:%d) sent a hexed packet trying to buy %d of nonstackable item %d!\n", sd->status.name, sd->status.account_id, sd->status.char_id, amount, nameid); amount = item_list[i*2+0] = 1; } - if( nd->master_nd ) - {// Script-controlled shops decide by themselves, what can be bought and for what price. + if( nd->master_nd ) { + // Script-controlled shops decide by themselves, what can be bought and for what price. continue; } - switch( pc_checkadditem(sd,nameid,amount) ) - { + switch( pc_checkadditem(sd,nameid,amount) ) { case ADDITEM_EXIST: break; @@ -1540,16 +1582,14 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) pc_payzeny(sd,(int)z,LOG_TYPE_NPC, NULL); - for( i = 0; i < n; ++i ) - { + for( i = 0; i < n; ++i ) { int nameid = item_list[i*2+1]; int amount = item_list[i*2+0]; struct item item_tmp; if (itemdb_type(nameid) == IT_PETEGG) pet_create_egg(sd, nameid); - else - { + else { memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid = nameid; item_tmp.identify = 1; @@ -1559,14 +1599,12 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) } // custom merchant shop exp bonus - if( battle_config.shop_exp > 0 && z > 0 && (skill = pc_checkskill(sd,MC_DISCOUNT)) > 0 ) - { - if( sd->status.skill[MC_DISCOUNT].flag >= SKILL_FLAG_REPLACED_LV_0 ) - skill = sd->status.skill[MC_DISCOUNT].flag - SKILL_FLAG_REPLACED_LV_0; + if( battle_config.shop_exp > 0 && z > 0 && (skill_t = pc_checkskill2(sd,idx)) > 0 ) { + if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0; - if( skill > 0 ) - { - z = z * (double)skill * (double)battle_config.shop_exp/10000.; + if( skill_t > 0 ) { + z = z * (double)skill_t * (double)battle_config.shop_exp/10000.; if( z < 1 ) z = 1; pc_gainexp(sd,NULL,0,(int)z, false); @@ -1636,45 +1674,40 @@ static int npc_selllist_sub(struct map_session_data* sd, int n, unsigned short* /// Player item selling to npc shop. /// /// @param item_list 'n' pairs <index,amount> -/// @return result code for clif_parse_NpcSellListSend +/// @return result code for clif->parse_NpcSellListSend int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) { double z; - int i,skill; + int i,skill_t, idx = skill->get_index(MC_OVERCHARGE); struct npc_data *nd; nullpo_retr(1, sd); nullpo_retr(1, item_list); - if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP ) - { + if( ( nd = npc_checknear(sd, map_id2bl(sd->npc_shopid)) ) == NULL || nd->subtype != SHOP ) { return 1; } z = 0; // verify the sell list - for( i = 0; i < n; i++ ) - { + for( i = 0; i < n; i++ ) { int nameid, amount, idx, value; idx = item_list[i*2]-2; amount = item_list[i*2+1]; - if( idx >= MAX_INVENTORY || idx < 0 || amount < 0 ) - { + if( idx >= MAX_INVENTORY || idx < 0 || amount < 0 ) { return 1; } nameid = sd->status.inventory[idx].nameid; - if( !nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount ) - { + if( !nameid || !sd->inventory_data[idx] || sd->status.inventory[idx].amount < amount ) { return 1; } - if( nd->master_nd ) - {// Script-controlled shops decide by themselves, what can be sold and at what price. + if( nd->master_nd ) {// Script-controlled shops decide by themselves, what can be sold and at what price. continue; } @@ -1683,23 +1716,19 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) z+= (double)value*amount; } - if( nd->master_nd ) - {// Script-controlled shops + if( nd->master_nd ) { // Script-controlled shops return npc_selllist_sub(sd, n, item_list, nd->master_nd); } // delete items - for( i = 0; i < n; i++ ) - { + for( i = 0; i < n; i++ ) { int amount, idx; idx = item_list[i*2]-2; amount = item_list[i*2+1]; - if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) - { - if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) - { + if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET ) { + if( search_petDB_index(sd->status.inventory[idx].nameid, PET_EGG) >= 0 ) { intif_delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2])); } } @@ -1713,14 +1742,12 @@ int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list) pc_getzeny(sd, (int)z, LOG_TYPE_NPC, NULL); // custom merchant shop exp bonus - if( battle_config.shop_exp > 0 && z > 0 && ( skill = pc_checkskill(sd,MC_OVERCHARGE) ) > 0) - { - if( sd->status.skill[MC_OVERCHARGE].flag >= SKILL_FLAG_REPLACED_LV_0 ) - skill = sd->status.skill[MC_OVERCHARGE].flag - SKILL_FLAG_REPLACED_LV_0; + if( battle_config.shop_exp > 0 && z > 0 && ( skill_t = pc_checkskill2(sd,idx) ) > 0) { + if( sd->status.skill[idx].flag >= SKILL_FLAG_REPLACED_LV_0 ) + skill_t = sd->status.skill[idx].flag - SKILL_FLAG_REPLACED_LV_0; - if( skill > 0 ) - { - z = z * (double)skill * (double)battle_config.shop_exp/10000.; + if( skill_t > 0 ) { + z = z * (double)skill_t * (double)battle_config.shop_exp/10000.; if( z < 1 ) z = 1; pc_gainexp(sd, NULL, 0, (int)z, false); @@ -1740,7 +1767,7 @@ int npc_remove_map(struct npc_data* nd) if(nd->bl.prev == NULL || nd->bl.m < 0) return 1; //Not assigned to a map. m = nd->bl.m; - clif_clearunit_area(&nd->bl,CLR_RESPAWN); + clif->clearunit_area(&nd->bl,CLR_RESPAWN); npc_unsetcells(nd); map_delblock(&nd->bl); //Remove npc from map[].npc list. [Skotlex] @@ -1758,7 +1785,7 @@ int npc_remove_map(struct npc_data* nd) */ static int npc_unload_ev(DBKey key, DBData *data, va_list ap) { - struct event_data* ev = db_data2ptr(data); + struct event_data* ev = DB->data2ptr(data); char* npcname = va_arg(ap, char *); if(strcmp(ev->nd->exname,npcname)==0){ @@ -1825,7 +1852,7 @@ int npc_unload(struct npc_data* nd, bool single) { ev_db->foreach(ev_db,npc_unload_ev,nd->exname); //Clean up all events related iter = mapit_geteachpc(); - for( bl = (struct block_list*)mapit_first(iter); mapit_exists(iter); bl = (struct block_list*)mapit_next(iter) ) { + for( bl = (struct block_list*)mapit->first(iter); mapit->exists(iter); bl = (struct block_list*)mapit->next(iter) ) { struct map_session_data *sd = ((TBL_PC*)bl); if( sd && sd->npc_timer_id != INVALID_TIMER ) { const struct TimerData *td = get_timer(sd->npc_timer_id); @@ -1839,10 +1866,10 @@ int npc_unload(struct npc_data* nd, bool single) { sd->npc_timer_id = INVALID_TIMER; } } - mapit_free(iter); + mapit->free(iter); if (nd->u.scr.timerid != INVALID_TIMER) { - const struct TimerData *td = NULL; + const struct TimerData *td; td = get_timer(nd->u.scr.timerid); if (td && td->data) ers_free(timer_event_ers, (void*)td->data); @@ -1862,7 +1889,7 @@ int npc_unload(struct npc_data* nd, bool single) { } } if( nd->u.scr.guild_id ) - guild_flag_remove(nd); + guild->flag_remove(nd); } script_stop_sleeptimers(nd->bl.id); @@ -1915,7 +1942,7 @@ void npc_addsrcfile(const char* name) file = (struct npc_src_list*)aMalloc(sizeof(struct npc_src_list) + strlen(name)); file->next = NULL; - strncpy(file->name, name, strlen(name) + 1); + safestrncpy(file->name, name, strlen(name) + 1); if( file_prev == NULL ) npc_src_files = file; else @@ -2076,7 +2103,7 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short status_change_init(&nd->bl); unit_dataset(&nd->bl); if( map[nd->bl.m].users ) - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); strdb_put(npcname_db, nd->exname, nd); return nd; @@ -2107,6 +2134,11 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const return strchr(start,'\n');// skip and continue } + if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) { + ShowError("npc_parse_warp: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map[m].name, x, y, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer)); + return strchr(start,'\n');;//try next + } + CREATE(nd, struct npc_data, 1); nd->bl.id = npc_get_new_npc_id(); @@ -2137,7 +2169,7 @@ static const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const status_change_init(&nd->bl); unit_dataset(&nd->bl); if( map[nd->bl.m].users ) - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); strdb_put(npcname_db, nd->exname, nd); return strchr(start,'\n');// continue @@ -2154,13 +2186,10 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const struct npc_data *nd; enum npc_subtype type; - if( strcmp(w1,"-") == 0 ) - {// 'floating' shop? + if( strcmp(w1,"-") == 0 ) {// 'floating' shop? x = y = dir = 0; m = -1; - } - else - {// w1=<map name>,<x>,<y>,<facing> + } else {// w1=<map name>,<x>,<y>,<facing> char mapname[32]; if( sscanf(w1, "%31[^,],%d,%d,%d", mapname, &x, &y, &dir) != 4 || strchr(w4, ',') == NULL ) @@ -2172,6 +2201,11 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const m = map_mapname2mapid(mapname); } + if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) { + ShowError("npc_parse_shop: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map[m].name, x, y, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer)); + return strchr(start,'\n');;//try next + } + if( !strcasecmp(w2,"cashshop") ) type = CASHSHOP; else @@ -2250,7 +2284,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const unit_dataset(&nd->bl); nd->ud.dir = dir; if( map[nd->bl.m].users ) - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); } else {// 'floating' shop? map_addiddb(&nd->bl); @@ -2268,7 +2302,7 @@ static const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const int npc_convertlabel_db(DBKey key, DBData *data, va_list ap) { const char* lname = (const char*)key.str; - int lpos = db_data2i(data); + int lpos = DB->data2i(data); struct npc_label_list** label_list; int* label_list_num; const char* filepath; @@ -2463,7 +2497,7 @@ static const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, cons { status_set_viewdata(&nd->bl, nd->class_); if( map[nd->bl.m].users ) - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); } } else @@ -2557,6 +2591,11 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch m = map_mapname2mapid(mapname); } + if( m != -1 && ( x < 0 || x >= map[m].xs || y < 0 || y >= map[m].ys ) ) { + ShowError("npc_parse_duplicate: out-of-bounds coordinates (\"%s\",%d,%d), map is %dx%d, in file '%s', line '%d'\n", map[m].name, x, y, map[m].xs, map[m].ys,filepath,strline(buffer,start-buffer)); + return end;//try next + } + if( type == WARP && sscanf(w4, "%d,%d", &xs, &ys) == 2 );// <spanx>,<spany> else if( type == SCRIPT && sscanf(w4, "%d,%d,%d", &class_, &xs, &ys) == 3);// <sprite id>,<triggerX>,<triggerY> else if( type != WARP ) class_ = atoi(w4);// <sprite id> @@ -2624,7 +2663,7 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch { status_set_viewdata(&nd->bl, nd->class_); if( map[nd->bl.m].users ) - clif_spawn(&nd->bl); + clif->spawn(&nd->bl); } } else @@ -2702,7 +2741,7 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) { status_change_init(&wnd->bl); unit_dataset(&wnd->bl); if( map[wnd->bl.m].users ) - clif_spawn(&wnd->bl); + clif->spawn(&wnd->bl); strdb_put(npcname_db, wnd->exname, wnd); } else @@ -2806,9 +2845,9 @@ void npc_movenpc(struct npc_data* nd, int16 x, int16 y) x = cap_value(x, 0, map[m].xs-1); y = cap_value(y, 0, map[m].ys-1); - map_foreachinrange(clif_outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + map_foreachinrange(clif->outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); map_moveblock(&nd->bl, x, y, gettick()); - map_foreachinrange(clif_insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); + map_foreachinrange(clif->insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl); } /// Changes the display name of the npc. @@ -2821,7 +2860,7 @@ void npc_setdisplayname(struct npc_data* nd, const char* newname) safestrncpy(nd->name, newname, sizeof(nd->name)); if( map[nd->bl.m].users ) - clif_charnameack(0, &nd->bl); + clif->charnameack(0, &nd->bl); } /// Changes the display class of the npc. @@ -2836,11 +2875,11 @@ void npc_setclass(struct npc_data* nd, short class_) return; if( map[nd->bl.m].users ) - clif_clearunit_area(&nd->bl, CLR_OUTSIGHT);// fade out + clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);// fade out nd->class_ = class_; status_set_viewdata(&nd->bl, class_); if( map[nd->bl.m].users ) - clif_spawn(&nd->bl);// fade in + clif->spawn(&nd->bl);// fade in } // @commands (script based) @@ -2880,24 +2919,25 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL); // split atcmd parameters based on spaces - i = 0; - j = 0; - temp = (char*)aMalloc(strlen(message) + 1); - while( message[i] != '\0' ) { - if( message[i] == ' ' && k < 127 ) { - temp[j] = '\0'; - setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL); - j = 0; - ++i; - } else - temp[j++] = message[i++]; + for( i = 0; i < ( strlen( message ) + 1 ) && k < 127; i ++ ) { + if( message[i] == ' ' || message[i] == '\0' ) { + if( message[ ( i - 1 ) ] == ' ' ) { + continue; // To prevent "@atcmd [space][space]" and .@atcmd_numparameters return 1 without any parameter. + } + temp[k] = '\0'; + k = 0; + if( temp[0] != '\0' ) { + setd_sub( st, NULL, ".@atcmd_parameters$", j++, (void *)temp, NULL ); + } + } else { + temp[k] = message[i]; + k++; + } } - temp[j] = '\0'; - setd_sub(st, NULL, ".@atcmd_parameters$", k++, (void *)temp, NULL); - setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)&k, NULL); + setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)__64BPTRSIZE(j), NULL); aFree(temp); run_script_main(st); @@ -2932,9 +2972,9 @@ static const char* npc_parse_function(char* w1, char* w2, char* w3, char* w4, co return end; func_db = script_get_userfunc_db(); - if (func_db->put(func_db, db_str2key(w3), db_ptr2data(script), &old_data)) + if (func_db->put(func_db, DB->str2key(w3), DB->ptr2data(script), &old_data)) { - struct script_code *oldscript = (struct script_code*)db_data2ptr(&old_data); + struct script_code *oldscript = (struct script_code*)DB->data2ptr(&old_data); ShowInfo("npc_parse_function: Overwriting user function [%s] (%s:%d)\n", w3, filepath, strline(buffer,start-buffer)); script_free_vars(oldscript->script_vars); aFree(oldscript->script_buf); @@ -3132,14 +3172,12 @@ static const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const c return strchr(start,'\n');// continue } - /*========================================== * Set or disable mapflag on map * eg : bat_c01 mapflag battleground 2 * also chking if mapflag conflict with another *------------------------------------------*/ -static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) -{ +const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath) { int16 m; char mapname[32]; int state = 1; @@ -3206,19 +3244,23 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con map[m].flag.nozenypenalty=state; } else if (!strcmpi(w3,"pvp")) { + struct map_zone_data *zone; map[m].flag.pvp = state; - if( state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) - { + if( state && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) { map[m].flag.gvg = 0; map[m].flag.gvg_dungeon = 0; map[m].flag.gvg_castle = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing GvG flags from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); } - if( state && map[m].flag.battleground ) - { + if( state && map[m].flag.battleground ) { map[m].flag.battleground = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); } + if( state && (zone = strdb_get(zone_db, MAP_ZONE_PVP_NAME)) && map[m].zone != zone ) { + map_zone_change(m,zone,start,buffer,filepath); + } else if ( !state ) { + map[m].zone = &map_zone_pk; + } } else if (!strcmpi(w3,"pvp_noparty")) map[m].flag.pvp_noparty=state; @@ -3226,9 +3268,9 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con map[m].flag.pvp_noguild=state; else if (!strcmpi(w3, "pvp_nightmaredrop")) { char drop_arg1[16], drop_arg2[16]; - int drop_id = 0, drop_type = 0, drop_per = 0; + int drop_per = 0; if (sscanf(w4, "%[^,],%[^,],%d", drop_arg1, drop_arg2, &drop_per) == 3) { - int i; + int drop_id = 0, drop_type = 0; if (!strcmpi(drop_arg1, "random")) drop_id = -1; else if (itemdb_exists((drop_id = atoi(drop_arg1))) == NULL) @@ -3241,6 +3283,7 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con drop_type = 3; if (drop_id != 0){ + int i; for (i = 0; i < MAX_DROP_PER_MAP; i++) { if (map[m].drop_list[i].drop_id == 0){ map[m].drop_list[i].drop_id = drop_id; @@ -3257,17 +3300,20 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con else if (!strcmpi(w3,"pvp_nocalcrank")) map[m].flag.pvp_nocalcrank=state; else if (!strcmpi(w3,"gvg")) { + struct map_zone_data *zone; + map[m].flag.gvg = state; - if( state && map[m].flag.pvp ) - { + if( state && map[m].flag.pvp ) { map[m].flag.pvp = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and GvG flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); } - if( state && map[m].flag.battleground ) - { + if( state && map[m].flag.battleground ) { map[m].flag.battleground = 0; ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing BattleGround flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); } + if( state && (zone = strdb_get(zone_db, MAP_ZONE_GVG_NAME)) && map[m].zone != zone ) { + map_zone_change(m,zone,start,buffer,filepath); + } } else if (!strcmpi(w3,"gvg_noparty")) map[m].flag.gvg_noparty=state; @@ -3280,28 +3326,29 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con if (state) map[m].flag.pvp=0; } else if (!strcmpi(w3,"battleground")) { - if( state ) - { + struct map_zone_data *zone; + if( state ) { if( sscanf(w4, "%d", &state) == 1 ) map[m].flag.battleground = state; else map[m].flag.battleground = 1; // Default value - } - else + } else map[m].flag.battleground = 0; - if( map[m].flag.battleground && map[m].flag.pvp ) - { + if( map[m].flag.battleground && map[m].flag.pvp ) { map[m].flag.pvp = 0; ShowWarning("npc_parse_mapflag: You can't set PvP and BattleGround flags for the same map! Removing PvP flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); } - if( map[m].flag.battleground && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) - { + if( map[m].flag.battleground && (map[m].flag.gvg || map[m].flag.gvg_dungeon || map[m].flag.gvg_castle) ) { map[m].flag.gvg = 0; map[m].flag.gvg_dungeon = 0; map[m].flag.gvg_castle = 0; ShowWarning("npc_parse_mapflag: You can't set GvG and BattleGround flags for the same map! Removing GvG flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); } + + if( state && (zone = strdb_get(zone_db, MAP_ZONE_BG_NAME)) && map[m].zone != zone ) { + map_zone_change(m,zone,start,buffer,filepath); + } } else if (!strcmpi(w3,"noexppenalty")) map[m].flag.noexppenalty=state; @@ -3331,15 +3378,8 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con map[m].flag.sakura=state; else if (!strcmpi(w3,"leaves")) map[m].flag.leaves=state; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //else if (!strcmpi(w3,"rain")) - // map[m].flag.rain=state; else if (!strcmpi(w3,"nightenabled")) map[m].flag.nightenabled=state; - else if (!strcmpi(w3,"nogo")) - map[m].flag.nogo=state; else if (!strcmpi(w3,"noexp")) { map[m].flag.nobaseexp=state; map[m].flag.nojobexp=state; @@ -3365,16 +3405,6 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con } else map[m].nocommand=0; } - else if (!strcmpi(w3,"restricted")) { - if (state) { - map[m].flag.restricted=1; - sscanf(w4, "%d", &state); - map[m].zone |= 1<<(state+1); - } else { - map[m].flag.restricted=0; - map[m].zone = 0; - } - } else if (!strcmpi(w3,"jexp")) { map[m].jexp = (state) ? atoi(w4) : 100; if( map[m].jexp < 0 ) map[m].jexp = 100; @@ -3395,7 +3425,140 @@ static const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, con map[m].flag.guildlock=state; else if (!strcmpi(w3,"reset")) map[m].flag.reset=state; - else + else if (!strcmpi(w3,"adjust_unit_duration")) { + int skill_id, k; + char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH]; + int len = strlen(w4); + + modifier[0] = '\0'; + memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH); + + for(k = 0; k < len; k++) { + if( skill_name[k] == '\t' ) { + memcpy(modifier, &skill_name[k+1], len - k); + skill_name[k] = '\0'; + break; + } + } + + if( modifier[0] == '\0' ) { + ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } else if( !( skill_id = skill->name2id(skill_name) ) || !skill->get_unit_id( skill->name2id(skill_name), 0) ) { + ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n",skill_name, map[m].name, filepath, strline(buffer,start-buffer)); + } else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { + ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_unit_duration' flag! removing flag from %s (file '%s', line '%d').\n", atoi(modifier), skill_name, map[m].name, filepath, strline(buffer,start-buffer)); + } else { + int idx = map[m].unit_count; + + ARR_FIND(0, idx, k, map[m].units[k]->skill_id == skill_id); + + if( k < idx ) { + if( atoi(modifier) != 100 ) + map[m].units[k]->modifier = (unsigned short)atoi(modifier); + else { /* remove */ + int cursor = 0; + aFree(map[m].units[k]); + map[m].units[k] = NULL; + for( k = 0; k < idx; k++ ) { + if( map[m].units[k] == NULL ) + continue; + + memmove(&map[m].units[cursor], &map[m].units[k], sizeof(struct mapflag_skill_adjust)); + + cursor++; + } + if( !( map[m].unit_count = cursor ) ) { + aFree(map[m].units); + map[m].units = NULL; + } + } + } else if( atoi(modifier) != 100 ) { + RECREATE(map[m].units, struct mapflag_skill_adjust*, ++map[m].unit_count); + CREATE(map[m].units[idx],struct mapflag_skill_adjust,1); + map[m].units[idx]->skill_id = (unsigned short)skill_id; + map[m].units[idx]->modifier = (unsigned short)atoi(modifier); + } + } + } else if (!strcmpi(w3,"adjust_skill_damage")) { + int skill_id, k; + char skill_name[MAP_ZONE_MAPFLAG_LENGTH], modifier[MAP_ZONE_MAPFLAG_LENGTH]; + int len = strlen(w4); + + modifier[0] = '\0'; + memcpy(skill_name, w4, MAP_ZONE_MAPFLAG_LENGTH); + + for(k = 0; k < len; k++) { + if( skill_name[k] == '\t' ) { + memcpy(modifier, &skill_name[k+1], len - k); + skill_name[k] = '\0'; + break; + } + } + + if( modifier[0] == '\0' ) { + ShowWarning("npc_parse_mapflag: Missing 5th param for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", map[m].name, filepath, strline(buffer,start-buffer)); + } else if( !( skill_id = skill->name2id(skill_name) ) ) { + ShowWarning("npc_parse_mapflag: Unknown skill (%s) for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", skill_name, map[m].name, filepath, strline(buffer,start-buffer)); + } else if ( atoi(modifier) < 1 || atoi(modifier) > USHRT_MAX ) { + ShowWarning("npc_parse_mapflag: Invalid modifier '%d' for skill '%s' for 'adjust_skill_damage' flag! removing flag from %s (file '%s', line '%d').\n", atoi(modifier), skill_name, map[m].name, filepath, strline(buffer,start-buffer)); + } else { + int idx = map[m].skill_count; + + ARR_FIND(0, idx, k, map[m].skills[k]->skill_id == skill_id); + + if( k < idx ) { + if( atoi(modifier) != 100 ) + map[m].skills[k]->modifier = (unsigned short)atoi(modifier); + else { /* remove */ + int cursor = 0; + aFree(map[m].skills[k]); + map[m].skills[k] = NULL; + for( k = 0; k < idx; k++ ) { + if( map[m].skills[k] == NULL ) + continue; + + memmove(&map[m].skills[cursor], &map[m].skills[k], sizeof(struct mapflag_skill_adjust)); + + cursor++; + } + if( !( map[m].skill_count = cursor ) ) { + aFree(map[m].skills); + map[m].skills = NULL; + } + } + } else if( atoi(modifier) != 100 ) { + RECREATE(map[m].skills, struct mapflag_skill_adjust*, ++map[m].skill_count); + CREATE(map[m].skills[idx],struct mapflag_skill_adjust,1); + map[m].skills[idx]->skill_id = (unsigned short)skill_id; + map[m].skills[idx]->modifier = (unsigned short)atoi(modifier); + } + + } + } else if (!strcmpi(w3,"zone")) { + struct map_zone_data *zone; + + if( !(zone = strdb_get(zone_db, w4)) ) { + ShowWarning("npc_parse_mapflag: Invalid zone '%s'! removing flag from %s (file '%s', line '%d').\n", w4, map[m].name, filepath, strline(buffer,start-buffer)); + } else if( map[m].zone != zone ) { + map_zone_change(m,zone,start,buffer,filepath); + } + } else if ( !strcmpi(w3,"nomapchannelautojoin") ) { + map[m].flag.chsysnolocalaj = state; + } else if ( !strcmpi(w3,"invincible_time_inc") ) { + map[m].invincible_time_inc = (state) ? atoi(w4) : 0; + } else if ( !strcmpi(w3,"noknockback") ) { + map[m].flag.noknockback = state; + } else if ( !strcmpi(w3,"weapon_damage_rate") ) { + map[m].weapon_damage_rate = (state) ? atoi(w4) : 100; + } else if ( !strcmpi(w3,"magic_damage_rate") ) { + map[m].magic_damage_rate = (state) ? atoi(w4) : 100; + } else if ( !strcmpi(w3,"misc_damage_rate") ) { + map[m].misc_damage_rate = (state) ? atoi(w4) : 100; + } else if ( !strcmpi(w3,"short_damage_rate") ) { + map[m].short_damage_rate = (state) ? atoi(w4) : 100; + } else if ( !strcmpi(w3,"long_damage_rate") ) { + map[m].long_damage_rate = (state) ? atoi(w4) : 100; + } else ShowError("npc_parse_mapflag: unrecognized mapflag '%s' (file '%s', line '%d').\n", w3, filepath, strline(buffer,start-buffer)); return strchr(start,'\n');// continue @@ -3443,7 +3606,7 @@ void npc_parsesrcfile(const char* filepath, bool runOnInit) lines++; // w1<TAB>w2<TAB>w3<TAB>w4 - count = sv_parse(p, len+buffer-p, 0, '\t', pos, ARRAYLENGTH(pos), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF)); + count = sv->parse(p, len+buffer-p, 0, '\t', pos, ARRAYLENGTH(pos), (e_svopt)(SV_TERMINATE_LF|SV_TERMINATE_CRLF)); if( count < 0 ) { ShowError("npc_parsesrcfile: Parse error in file '%s', line '%d'. Stopping...\n", filepath, strline(buffer,p-buffer)); @@ -3606,14 +3769,14 @@ void npc_read_event_script(void) DBData *data; char name[64]="::"; - strncpy(name+2,config[i].event_name,62); + safestrncpy(name+2,config[i].event_name,62); script_event[i].event_count = 0; iter = db_iterator(ev_db); for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) { const char* p = key.str; - struct event_data* ed = db_data2ptr(data); + struct event_data* ed = DB->data2ptr(data); unsigned char count = script_event[i].event_count; if( count >= ARRAYLENGTH(script_event[i].event) ) @@ -3661,7 +3824,7 @@ int npc_reload(void) { struct block_list* bl; /* clear guild flag cache */ - guild_flags_clear(); + guild->flags_clear(); npc_clear_pathlist(); @@ -3673,7 +3836,7 @@ int npc_reload(void) { //Remove all npcs/mobs. [Skotlex] iter = mapit_geteachiddb(); - for( bl = (struct block_list*)mapit_first(iter); mapit_exists(iter); bl = (struct block_list*)mapit_next(iter) ) { + for( bl = (struct block_list*)mapit->first(iter); mapit->exists(iter); bl = (struct block_list*)mapit->next(iter) ) { switch(bl->type) { case BL_NPC: if( bl->id != fake_nd->bl.id )// don't remove fake_nd @@ -3684,7 +3847,7 @@ int npc_reload(void) { break; } } - mapit_free(iter); + mapit->free(iter); if(battle_config.dynamic_mobs) {// dynamic check by [random] @@ -3728,12 +3891,14 @@ int npc_reload(void) { "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Cached\n" "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", npc_id - npc_new_min, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); - + do_final_instance(); for( i = 0; i < ARRAYLENGTH(instance); ++i ) instance_init(instance[i].instance_id); + map_zone_init(); + //Re-read the NPC Script Events cache. npc_read_event_script(); @@ -3840,6 +4005,8 @@ int do_init_npc(void) npc_viewdb[0].class_ = INVISIBLE_CLASS; //Invisible class is stored here. for( i = 1; i < MAX_NPC_CLASS; i++ ) npc_viewdb[i].class_ = i; + for( i = MAX_NPC_CLASS2_START; i < MAX_NPC_CLASS2_END; i++ ) + npc_viewdb2[i - MAX_NPC_CLASS2_START].class_ = i; ev_db = strdb_alloc((DBOptions)(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA),2*NAME_LENGTH+2+1); npcname_db = strdb_alloc(DB_OPT_BASE,NAME_LENGTH); @@ -3862,6 +4029,8 @@ int do_init_npc(void) "\t-'"CL_WHITE"%d"CL_RESET"' Mobs Not Cached\n", npc_id - START_NPC_NUM, npc_warp, npc_shop, npc_script, npc_mob, npc_cache_mob, npc_delay_mob); + map_zone_init(); + // set up the events cache memset(script_event, 0, sizeof(script_event)); npc_read_event_script(); diff --git a/src/map/npc.h b/src/map/npc.h index ee88da08c..8800b4e5b 100644 --- a/src/map/npc.h +++ b/src/map/npc.h @@ -88,10 +88,15 @@ enum actor_classes INVISIBLE_CLASS = 32767, }; +// Old NPC range #define MAX_NPC_CLASS 1000 +// New NPC range +#define MAX_NPC_CLASS2_START 10000 +#define MAX_NPC_CLASS2_END 10049 + //Checks if a given id is a valid npc id. [Skotlex] //Since new npcs are added all the time, the max valid value is the one before the first mob (Scorpion = 1001) -#define npcdb_checkid(id) ( ( (id) >= 46 && (id) <= 125) || (id) == HIDDEN_WARP_CLASS || ( (id) > 400 && (id) < MAX_NPC_CLASS ) || (id) == INVISIBLE_CLASS ) +#define npcdb_checkid(id) ( ( (id) >= 46 && (id) <= 125) || (id) == HIDDEN_WARP_CLASS || ( (id) > 400 && (id) < MAX_NPC_CLASS ) || (id) == INVISIBLE_CLASS || ( (id) > 10000 && (id) < 10049 ) ) #ifdef PCRE_SUPPORT void npc_chat_finalize(struct npc_data* nd); @@ -118,12 +123,13 @@ int npc_touch_areanpc2(struct mob_data *md); // [Skotlex] int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range); int npc_touchnext_areanpc(struct map_session_data* sd,bool leavemap); int npc_click(struct map_session_data* sd, struct npc_data* nd); -int npc_scriptcont(struct map_session_data* sd, int id); +int npc_scriptcont(struct map_session_data* sd, int id, bool closing); struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl); int npc_buysellsel(struct map_session_data* sd, int id, int type); int npc_buylist(struct map_session_data* sd,int n, unsigned short* item_list); int npc_selllist(struct map_session_data* sd, int n, unsigned short* item_list); void npc_parse_mob2(struct spawn_data* mob); +const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath); struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y); int npc_globalmessage(const char* name,const char* mes); @@ -134,6 +140,7 @@ int npc_enable(const char* name, int flag); void npc_setdisplayname(struct npc_data* nd, const char* newname); void npc_setclass(struct npc_data* nd, short class_); struct npc_data* npc_name2id(const char* name); +bool npc_isnear(struct block_list * bl); int npc_get_new_npc_id(void); @@ -172,7 +179,7 @@ int npc_cashshop_buylist(struct map_session_data *sd, int points, int count, uns /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT int npc_rr_secure_timeout_timer(int tid, unsigned int tick, int id, intptr_t data); #endif diff --git a/src/map/npc_chat.c b/src/map/npc_chat.c index 39a3a8584..81373bbb6 100644 --- a/src/map/npc_chat.c +++ b/src/map/npc_chat.c @@ -1,5 +1,6 @@ -// 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 #ifdef PCRE_SUPPORT @@ -407,44 +408,44 @@ int npc_chat_sub(struct block_list* bl, va_list ap) int buildin_defpattern(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); - const char* pattern = conv_str(st,& (st->stack->stack_data[st->start+3])); - const char* label = conv_str(st,& (st->stack->stack_data[st->start+4])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); + const char* pattern = script->conv_str(st,& (st->stack->stack_data[st->start+3])); + const char* label = script->conv_str(st,& (st->stack->stack_data[st->start+4])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); npc_chat_def_pattern(nd, setid, pattern, label); - return 0; + return 1; } int buildin_activatepset(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); activate_pcreset(nd, setid); - return 0; + return 1; } int buildin_deactivatepset(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); deactivate_pcreset(nd, setid); - return 0; + return 1; } int buildin_deletepset(struct script_state* st) { - int setid = conv_num(st,& (st->stack->stack_data[st->start+2])); + int setid = script->conv_num(st,& (st->stack->stack_data[st->start+2])); struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); delete_pcreset(nd, setid); - return 0; + return 1; } #endif //PCRE_SUPPORT diff --git a/src/map/packets.h b/src/map/packets.h new file mode 100644 index 000000000..7e14305b7 --- /dev/null +++ b/src/map/packets.h @@ -0,0 +1,2089 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +//Included directly by clif.h in packet_loaddb() + +#ifndef _PACKETS_H_ +#define _PACKETS_H_ + +#ifndef packet + #define packet(a,b,...) +#endif + +/* + * packet syntax + * - packet(packet_id,length) + * OR + * - packet(packet_id,length,function,offset ( specifies the offset of a packet field in bytes from the begin of the packet ),...) + * - Example: packet(0x0072,19,clif->pWantToConnection,2,6,10,14,18); + */ + +packet(0x0064,55); +packet(0x0065,17); +packet(0x0066,6); +packet(0x0067,37); +packet(0x0068,46); +packet(0x0069,-1); +packet(0x006a,23); +packet(0x006b,-1); +packet(0x006c,3); +packet(0x006d,108); +packet(0x006e,3); +packet(0x006f,2); +packet(0x0070,6); +packet(0x0071,28); +packet(0x0072,19,clif->pWantToConnection,2,6,10,14,18); +packet(0x0073,11); +packet(0x0074,3); +packet(0x0075,-1); +packet(0x0076,9); +packet(0x0077,5); +packet(0x0078,54); +packet(0x0079,53); +packet(0x007a,58); +packet(0x007b,60); +packet(0x007c,41); +packet(0x007d,2,clif->pLoadEndAck,0); +packet(0x007e,6,clif->pTickSend,2); +packet(0x007f,6); +packet(0x0080,7); +packet(0x0081,3); +packet(0x0082,2); +packet(0x0083,2); +packet(0x0084,2); +packet(0x0085,5,clif->pWalkToXY,2); +packet(0x0086,16); +packet(0x0087,12); +packet(0x0088,10); +packet(0x0089,7,clif->pActionRequest,2,6); +packet(0x008a,29); +packet(0x008b,2); +packet(0x008c,-1,clif->pGlobalMessage,2,4); +packet(0x008d,-1); +packet(0x008e,-1); +//packet(0x008f,-1); +packet(0x0090,7,clif->pNpcClicked,2); +packet(0x0091,22); +packet(0x0092,28); +packet(0x0093,2); +packet(0x0094,6,clif->pGetCharNameRequest,2); +packet(0x0095,30); +packet(0x0096,-1,clif->pWisMessage,2,4,28); +packet(0x0097,-1); +packet(0x0098,3); +packet(0x0099,-1,clif->pBroadcast,2,4); +packet(0x009a,-1); +packet(0x009b,5,clif->pChangeDir,2,4); +packet(0x009c,9); +packet(0x009d,17); +packet(0x009e,17); +packet(0x009f,6,clif->pTakeItem,2); +packet(0x00a0,23); +packet(0x00a1,6); +packet(0x00a2,6,clif->pDropItem,2,4); +packet(0x00a3,-1); +packet(0x00a4,-1); +packet(0x00a5,-1); +packet(0x00a6,-1); +packet(0x00a7,8,clif->pUseItem,2,4); +packet(0x00a8,7); +packet(0x00a9,6,clif->pEquipItem,2,4); +packet(0x00aa,7); +packet(0x00ab,4,clif->pUnequipItem,2); +packet(0x00ac,7); +//packet(0x00ad,-1); +packet(0x00ae,-1); +packet(0x00af,6); +packet(0x00b0,8); +packet(0x00b1,8); +packet(0x00b2,3,clif->pRestart,2); +packet(0x00b3,3); +packet(0x00b4,-1); +packet(0x00b5,6); +packet(0x00b6,6); +packet(0x00b7,-1); +packet(0x00b8,7,clif->pNpcSelectMenu,2,6); +packet(0x00b9,6,clif->pNpcNextClicked,2); +packet(0x00ba,2); +packet(0x00bb,5,clif->pStatusUp,2,4); +packet(0x00bc,6); +packet(0x00bd,44); +packet(0x00be,5); +packet(0x00bf,3,clif->pEmotion,2); +packet(0x00c0,7); +packet(0x00c1,2,clif->pHowManyConnections,0); +packet(0x00c2,6); +packet(0x00c3,8); +packet(0x00c4,6); +packet(0x00c5,7,clif->pNpcBuySellSelected,2,6); +packet(0x00c6,-1); +packet(0x00c7,-1); +packet(0x00c8,-1,clif->pNpcBuyListSend,2,4); +packet(0x00c9,-1,clif->pNpcSellListSend,2,4); +packet(0x00ca,3); +packet(0x00cb,3); +packet(0x00cc,6,clif->pGMKick,2); +packet(0x00cd,3); +packet(0x00ce,2,clif->pGMKickAll,0); +packet(0x00cf,27,clif->pPMIgnore,2,26); +packet(0x00d0,3,clif->pPMIgnoreAll,2); +packet(0x00d1,4); +packet(0x00d2,4); +packet(0x00d3,2,clif->pPMIgnoreList,0); +packet(0x00d4,-1); +packet(0x00d5,-1,clif->pCreateChatRoom,2,4,6,7,15); +packet(0x00d6,3); +packet(0x00d7,-1); +packet(0x00d8,6); +packet(0x00d9,14,clif->pChatAddMember,2,6); +packet(0x00da,3); +packet(0x00db,-1); +packet(0x00dc,28); +packet(0x00dd,29); +packet(0x00de,-1,clif->pChatRoomStatusChange,2,4,6,7,15); +packet(0x00df,-1); +packet(0x00e0,30,clif->pChangeChatOwner,2,6); +packet(0x00e1,30); +packet(0x00e2,26,clif->pKickFromChat,2); +packet(0x00e3,2,clif->pChatLeave,0); +packet(0x00e4,6,clif->pTradeRequest,2); +packet(0x00e5,26); +packet(0x00e6,3,clif->pTradeAck,2); +packet(0x00e7,3); +packet(0x00e8,8,clif->pTradeAddItem,2,4); +packet(0x00e9,19); +packet(0x00ea,5); +packet(0x00eb,2,clif->pTradeOk,0); +packet(0x00ec,3); +packet(0x00ed,2,clif->pTradeCancel,0); +packet(0x00ee,2); +packet(0x00ef,2,clif->pTradeCommit,0); +packet(0x00f0,3); +packet(0x00f1,2); +packet(0x00f2,6); +packet(0x00f3,8,clif->pMoveToKafra,2,4); +packet(0x00f4,21); +packet(0x00f5,8,clif->pMoveFromKafra,2,4); +packet(0x00f6,8); +packet(0x00f7,2,clif->pCloseKafra,0); +packet(0x00f8,2); +packet(0x00f9,26,clif->pCreateParty,2); +packet(0x00fa,3); +packet(0x00fb,-1); +packet(0x00fc,6,clif->pPartyInvite,2); +packet(0x00fd,27); +packet(0x00fe,30); +packet(0x00ff,10,clif->pReplyPartyInvite,2,6); +packet(0x0100,2,clif->pLeaveParty,0); +packet(0x0101,6); +packet(0x0102,6,clif->pPartyChangeOption,2); +packet(0x0103,30,clif->pRemovePartyMember,2,6); +packet(0x0104,79); +packet(0x0105,31); +packet(0x0106,10); +packet(0x0107,10); +packet(0x0108,-1,clif->pPartyMessage,2,4); +packet(0x0109,-1); +packet(0x010a,4); +packet(0x010b,6); +packet(0x010c,6); +packet(0x010d,2); +packet(0x010e,11); +packet(0x010f,-1); +packet(0x0110,10); +packet(0x0111,39); +packet(0x0112,4,clif->pSkillUp,2); +packet(0x0113,10,clif->pUseSkillToId,2,4,6); +packet(0x0114,31); +packet(0x0115,35); +packet(0x0116,10,clif->pUseSkillToPos,2,4,6,8); +packet(0x0117,18); +packet(0x0118,2,clif->pStopAttack,0); +packet(0x0119,13); +packet(0x011a,15); +packet(0x011b,20,clif->pUseSkillMap,2,4); +packet(0x011c,68); +packet(0x011d,2,clif->pRequestMemo,0); +packet(0x011e,3); +packet(0x011f,16); +packet(0x0120,6); +packet(0x0121,14); +packet(0x0122,-1); +packet(0x0123,-1); +packet(0x0124,21); +packet(0x0125,8); +packet(0x0126,8,clif->pPutItemToCart,2,4); +packet(0x0127,8,clif->pGetItemFromCart,2,4); +packet(0x0128,8,clif->pMoveFromKafraToCart,2,4); +packet(0x0129,8,clif->pMoveToKafraFromCart,2,4); +packet(0x012a,2,clif->pRemoveOption,0); +packet(0x012b,2); +packet(0x012c,3); +packet(0x012d,4); +packet(0x012e,2,clif->pCloseVending,0); +packet(0x012f,-1); +packet(0x0130,6,clif->pVendingListReq,2); +packet(0x0131,86); +packet(0x0132,6); +packet(0x0133,-1); +packet(0x0134,-1,clif->pPurchaseReq,2,4,8); +packet(0x0135,7); +packet(0x0136,-1); +packet(0x0137,6); +packet(0x0138,3); +packet(0x0139,16); +packet(0x013a,4); +packet(0x013b,4); +packet(0x013c,4); +packet(0x013d,6); +packet(0x013e,24); +packet(0x013f,26,clif->pGM_Monster_Item,2); +packet(0x0140,22,clif->pMapMove,2,18,20); +packet(0x0141,14); +packet(0x0142,6); +packet(0x0143,10,clif->pNpcAmountInput,2,6); +packet(0x0144,23); +packet(0x0145,19); +packet(0x0146,6,clif->pNpcCloseClicked,2); +packet(0x0147,39); +packet(0x0148,8); +packet(0x0149,9,clif->pGMReqNoChat,2,6,7); +packet(0x014a,6); +packet(0x014b,27); +packet(0x014c,-1); +packet(0x014d,2,clif->pGuildCheckMaster,0); +packet(0x014e,6); +packet(0x014f,6,clif->pGuildRequestInfo,2); +packet(0x0150,110); +packet(0x0151,6,clif->pGuildRequestEmblem,2); +packet(0x0152,-1); +packet(0x0153,-1,clif->pGuildChangeEmblem,2,4); +packet(0x0154,-1); +packet(0x0155,-1,clif->pGuildChangeMemberPosition,2); +packet(0x0156,-1); +packet(0x0157,6); +packet(0x0158,-1); +packet(0x0159,54,clif->pGuildLeave,2,6,10,14); +packet(0x015a,66); +packet(0x015b,54,clif->pGuildExpulsion,2,6,10,14); +packet(0x015c,90); +packet(0x015d,42,clif->pGuildBreak,2); +packet(0x015e,6); +packet(0x015f,42); +packet(0x0160,-1); +packet(0x0161,-1,clif->pGuildChangePositionInfo,2); +packet(0x0162,-1); +packet(0x0163,-1); +packet(0x0164,-1); +packet(0x0165,30,clif->pCreateGuild,6); +packet(0x0166,-1); +packet(0x0167,3); +packet(0x0168,14,clif->pGuildInvite,2); +packet(0x0169,3); +packet(0x016a,30); +packet(0x016b,10,clif->pGuildReplyInvite,2,6); +packet(0x016c,43); +packet(0x016d,14); +packet(0x016e,186,clif->pGuildChangeNotice,2,6,66); +packet(0x016f,182); +packet(0x0170,14,clif->pGuildRequestAlliance,2); +packet(0x0171,30); +packet(0x0172,10,clif->pGuildReplyAlliance,2,6); +packet(0x0173,3); +packet(0x0174,-1); +packet(0x0175,6); +packet(0x0176,106); +packet(0x0177,-1); +packet(0x0178,4,clif->pItemIdentify,2); +packet(0x0179,5); +packet(0x017a,4,clif->pUseCard,2); +packet(0x017b,-1); +packet(0x017c,6,clif->pInsertCard,2,4); +packet(0x017d,7); +packet(0x017e,-1,clif->pGuildMessage,2,4); +packet(0x017f,-1); +packet(0x0180,6,clif->pGuildOpposition,2); +packet(0x0181,3); +packet(0x0182,106); +packet(0x0183,10,clif->pGuildDelAlliance,2,6); +packet(0x0184,10); +packet(0x0185,34); +//packet(0x0186,-1); +packet(0x0187,6); +packet(0x0188,8); +packet(0x0189,4); +packet(0x018a,4,clif->pQuitGame,0); +packet(0x018b,4); +packet(0x018c,29); +packet(0x018d,-1); +packet(0x018e,10,clif->pProduceMix,2,4,6,8); +packet(0x018f,6); +packet(0x0190,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); +packet(0x0191,86); +packet(0x0192,24); +packet(0x0193,6,clif->pSolveCharName,2); +packet(0x0194,30); +packet(0x0195,102); +packet(0x0196,9); +packet(0x0197,4,clif->pResetChar,2); +packet(0x0198,8,clif->pGMChangeMapType,2,4,6); +packet(0x0199,4); +packet(0x019a,14); +packet(0x019b,10); +packet(0x019c,-1,clif->pLocalBroadcast,2,4); +packet(0x019d,6,clif->pGMHide,0); +packet(0x019e,2); +packet(0x019f,6,clif->pCatchPet,2); +packet(0x01a0,3); +packet(0x01a1,3,clif->pPetMenu,2); +packet(0x01a2,35); +packet(0x01a3,5); +packet(0x01a4,11); +packet(0x01a5,26,clif->pChangePetName,2); +packet(0x01a6,-1); +packet(0x01a7,4,clif->pSelectEgg,2); +packet(0x01a8,4); +packet(0x01a9,6,clif->pSendEmotion,2); +packet(0x01aa,10); +packet(0x01ab,12); +packet(0x01ac,6); +packet(0x01ad,-1); +packet(0x01ae,4,clif->pSelectArrow,2); +packet(0x01af,4,clif->pChangeCart,2); +packet(0x01b0,11); +packet(0x01b1,7); +packet(0x01b2,-1,clif->pOpenVending,2,4,84,85); +packet(0x01b3,67); +packet(0x01b4,12); +packet(0x01b5,18); +packet(0x01b6,114); +packet(0x01b7,6); +packet(0x01b8,3); +packet(0x01b9,6); +packet(0x01ba,26,clif->pGMShift,2); +packet(0x01bb,26,clif->pGMShift,2); +packet(0x01bc,26,clif->pGMRecall,2); +packet(0x01bd,26,clif->pGMRecall,2); +packet(0x01be,2); +packet(0x01bf,3); +packet(0x01c0,2); +packet(0x01c1,14); +packet(0x01c2,10); +packet(0x01c3,-1); +packet(0x01c4,22); +packet(0x01c5,22); +packet(0x01c6,4); +packet(0x01c7,2); +packet(0x01c8,13); +packet(0x01c9,97); +//packet(0x01ca,-1); +packet(0x01cb,9); +packet(0x01cc,9); +packet(0x01cd,30); +packet(0x01ce,6,clif->pAutoSpell,2); +packet(0x01cf,28); +packet(0x01d0,8); +packet(0x01d1,14); +packet(0x01d2,10); +packet(0x01d3,35); +packet(0x01d4,6); +packet(0x01d5,-1,clif->pNpcStringInput,2,4,8); +packet(0x01d6,4); +packet(0x01d7,11); +packet(0x01d8,54); +packet(0x01d9,53); +packet(0x01da,60); +packet(0x01db,2); +packet(0x01dc,-1); +packet(0x01dd,47); +packet(0x01de,33); +packet(0x01df,6,clif->pGMReqAccountName,2); +packet(0x01e0,30); +packet(0x01e1,8); +packet(0x01e2,34); +packet(0x01e3,14); +packet(0x01e4,2); +packet(0x01e5,6); +packet(0x01e6,26); +packet(0x01e7,2,clif->pNoviceDoriDori,0); +packet(0x01e8,28,clif->pCreateParty2,2); +packet(0x01e9,81); +packet(0x01ea,6); +packet(0x01eb,10); +packet(0x01ec,26); +packet(0x01ed,2,clif->pNoviceExplosionSpirits,0); +packet(0x01ee,-1); +packet(0x01ef,-1); +packet(0x01f0,-1); +packet(0x01f1,-1); +packet(0x01f2,20); +packet(0x01f3,10); +packet(0x01f4,32); +packet(0x01f5,9); +packet(0x01f6,34); +packet(0x01f7,14,clif->pAdopt_reply,0); +packet(0x01f8,2); +packet(0x01f9,6,clif->pAdopt_request,0); +packet(0x01fa,48); +packet(0x01fb,56); +packet(0x01fc,-1); +packet(0x01fd,4,clif->pRepairItem,2); +packet(0x01fe,5); +packet(0x01ff,10); +packet(0x0200,26); +packet(0x0201,-1); +packet(0x0202,26,clif->pFriendsListAdd,2); +packet(0x0203,10,clif->pFriendsListRemove,2,6); +packet(0x0204,18); +packet(0x0205,26); +packet(0x0206,11); +packet(0x0207,34); +packet(0x0208,11,clif->pFriendsListReply,2,6,10); +packet(0x0209,36); +packet(0x020a,10); +//packet(0x020b,-1); +//packet(0x020c,-1); +packet(0x020d,-1); + +//2004-07-05aSakexe +#if PACKETVER >= 20040705 + packet(0x0072,22,clif->pWantToConnection,5,9,13,17,21); + packet(0x0085,8,clif->pWalkToXY,5); + packet(0x00a7,13,clif->pUseItem,5,9); + packet(0x0113,15,clif->pUseSkillToId,4,9,11); + packet(0x0116,15,clif->pUseSkillToPos,4,9,11,13); + packet(0x0190,95,clif->pUseSkillToPosMoreInfo,4,9,11,13,15); + packet(0x0208,14,clif->pFriendsListReply,2,6,10); + packet(0x020e,24); +#endif + +//2004-07-13aSakexe +#if PACKETVER >= 20040713 + packet(0x0072,39,clif->pWantToConnection,12,22,30,34,38); + packet(0x0085,9,clif->pWalkToXY,6); + packet(0x009b,13,clif->pChangeDir,5,12); + packet(0x009f,10,clif->pTakeItem,6); + packet(0x00a7,17,clif->pUseItem,6,13); + packet(0x0113,19,clif->pUseSkillToId,7,9,15); + packet(0x0116,19,clif->pUseSkillToPos,7,9,15,17); + packet(0x0190,99,clif->pUseSkillToPosMoreInfo,7,9,15,17,19); +#endif + +//2004-07-26aSakexe +#if PACKETVER >= 20040726 + packet(0x0072,14,clif->pDropItem,5,12); + packet(0x007e,33,clif->pWantToConnection,12,18,24,28,32); + packet(0x0085,20,clif->pUseSkillToId,7,12,16); + packet(0x0089,15,clif->pGetCharNameRequest,11); + packet(0x008c,23,clif->pUseSkillToPos,3,6,17,21); + packet(0x0094,10,clif->pTakeItem,6); + packet(0x009b,6,clif->pWalkToXY,3); + packet(0x009f,13,clif->pChangeDir,5,12); + packet(0x00a2,103,clif->pUseSkillToPosMoreInfo,3,6,17,21,23); + packet(0x00a7,12,clif->pSolveCharName,8); + packet(0x00f3,-1,clif->pGlobalMessage,2,4); + packet(0x00f5,17,clif->pUseItem,6,12); + packet(0x00f7,10,clif->pTickSend,6); + packet(0x0113,16,clif->pMoveToKafra,5,12); + packet(0x0116,2,clif->pCloseKafra,0); + packet(0x0190,26,clif->pMoveFromKafra,10,22); + packet(0x0193,9,clif->pActionRequest,3,8); +#endif + +//2004-08-09aSakexe +#if PACKETVER >= 20040809 + packet(0x0072,17,clif->pDropItem,8,15); + packet(0x007e,37,clif->pWantToConnection,9,21,28,32,36); + packet(0x0085,26,clif->pUseSkillToId,11,18,22); + packet(0x0089,12,clif->pGetCharNameRequest,8); + packet(0x008c,40,clif->pUseSkillToPos,5,15,29,38); + packet(0x0094,13,clif->pTakeItem,9); + packet(0x009b,15,clif->pWalkToXY,12); + packet(0x009f,12,clif->pChangeDir,7,11); + packet(0x00a2,120,clif->pUseSkillToPosMoreInfo,5,15,29,38,40); + packet(0x00a7,11,clif->pSolveCharName,7); + packet(0x00f5,24,clif->pUseItem,9,20); + packet(0x00f7,13,clif->pTickSend,9); + packet(0x0113,23,clif->pMoveToKafra,5,19); + packet(0x0190,26,clif->pMoveFromKafra,11,22); + packet(0x0193,18,clif->pActionRequest,7,17); +#endif + +//2004-08-16aSakexe +#if PACKETVER >= 20040816 + packet(0x0212,26,clif->pGMRc,2); + packet(0x0213,26,clif->pCheck,2); + packet(0x0214,42); +#endif + +//2004-08-17aSakexe +#if PACKETVER >= 20040817 + packet(0x020f,10,clif->pPVPInfo,2,6); + packet(0x0210,22); +#endif + +//2004-09-06aSakexe +#if PACKETVER >= 20040906 + packet(0x0072,20,clif->pUseItem,9,20); + packet(0x007e,19,clif->pMoveToKafra,3,15); + packet(0x0085,23,clif->pActionRequest,9,22); + packet(0x0089,9,clif->pWalkToXY,6); + packet(0x008c,105,clif->pUseSkillToPosMoreInfo,10,14,18,23,25); + packet(0x0094,17,clif->pDropItem,6,15); + packet(0x009b,14,clif->pGetCharNameRequest,10); + packet(0x009f,-1,clif->pGlobalMessage,2,4); + packet(0x00a2,14,clif->pSolveCharName,10); + packet(0x00a7,25,clif->pUseSkillToPos,10,14,18,23); + packet(0x00f3,10,clif->pChangeDir,4,9); + packet(0x00f5,34,clif->pWantToConnection,7,15,25,29,33); + packet(0x00f7,2,clif->pCloseKafra,0); + packet(0x0113,11,clif->pTakeItem,7); + packet(0x0116,11,clif->pTickSend,7); + packet(0x0190,22,clif->pUseSkillToId,9,15,18); + packet(0x0193,17,clif->pMoveFromKafra,3,13); +#endif + +//2004-09-20aSakexe +#if PACKETVER >= 20040920 + packet(0x0072,18,clif->pUseItem,10,14); + packet(0x007e,25,clif->pMoveToKafra,6,21); + packet(0x0085,9,clif->pActionRequest,3,8); + packet(0x0089,14,clif->pWalkToXY,11); + packet(0x008c,109,clif->pUseSkillToPosMoreInfo,16,20,23,27,29); + packet(0x0094,19,clif->pDropItem,12,17); + packet(0x009b,10,clif->pGetCharNameRequest,6); + packet(0x00a2,10,clif->pSolveCharName,6); + packet(0x00a7,29,clif->pUseSkillToPos,6,20,23,27); + packet(0x00f3,18,clif->pChangeDir,8,17); + packet(0x00f5,32,clif->pWantToConnection,10,17,23,27,31); + packet(0x0113,14,clif->pTakeItem,10); + packet(0x0116,14,clif->pTickSend,10); + packet(0x0190,14,clif->pUseSkillToId,4,7,10); + packet(0x0193,12,clif->pMoveFromKafra,4,8); +#endif + +//2004-10-05aSakexe +#if PACKETVER >= 20041005 + packet(0x0072,17,clif->pUseItem,6,13); + packet(0x007e,16,clif->pMoveToKafra,5,12); + packet(0x0089,6,clif->pWalkToXY,3); + packet(0x008c,103,clif->pUseSkillToPosMoreInfo,2,6,17,21,23); + packet(0x0094,14,clif->pDropItem,5,12); + packet(0x009b,15,clif->pGetCharNameRequest,11); + packet(0x00a2,12,clif->pSolveCharName,8); + packet(0x00a7,23,clif->pUseSkillToPos,3,6,17,21); + packet(0x00f3,13,clif->pChangeDir,5,12); + packet(0x00f5,33,clif->pWantToConnection,12,18,24,28,32); + packet(0x0113,10,clif->pTakeItem,6); + packet(0x0116,10,clif->pTickSend,6); + packet(0x0190,20,clif->pUseSkillToId,7,12,16); + packet(0x0193,26,clif->pMoveFromKafra,10,22); +#endif + +//2004-10-25aSakexe +#if PACKETVER >= 20041025 + packet(0x0072,13,clif->pUseItem,5,9); + packet(0x007e,13,clif->pMoveToKafra,6,9); + packet(0x0085,15,clif->pActionRequest,4,14); + packet(0x008c,108,clif->pUseSkillToPosMoreInfo,6,9,23,26,28); + packet(0x0094,12,clif->pDropItem,6,10); + packet(0x009b,10,clif->pGetCharNameRequest,6); + packet(0x00a2,16,clif->pSolveCharName,12); + packet(0x00a7,28,clif->pUseSkillToPos,6,9,23,26); + packet(0x00f3,15,clif->pChangeDir,6,14); + packet(0x00f5,29,clif->pWantToConnection,5,14,20,24,28); + packet(0x0113,9,clif->pTakeItem,5); + packet(0x0116,9,clif->pTickSend,5); + packet(0x0190,26,clif->pUseSkillToId,4,10,22); + packet(0x0193,22,clif->pMoveFromKafra,12,18); +#endif + +//2004-11-01aSakexe +#if PACKETVER >= 20041101 + packet(0x0084,-1); + packet(0x0215,6); +#endif + +//2004-11-08aSakexe +#if PACKETVER >= 20041108 + packet(0x0084,2); + packet(0x0216,6); + packet(0x0217,2,clif->pBlacksmith,0); + packet(0x0218,2,clif->pAlchemist,0); + packet(0x0219,282); + packet(0x021a,282); + packet(0x021b,10); + packet(0x021c,10); +#endif + +//2004-11-15aSakexe +#if PACKETVER >= 20041115 + packet(0x021d,6,clif->pLessEffect,2); +#endif + +//2004-11-29aSakexe +#if PACKETVER >= 20041129 + packet(0x0072,22,clif->pUseSkillToId,8,12,18); + packet(0x007e,30,clif->pUseSkillToPos,4,9,22,28); + packet(0x0085,-1,clif->pGlobalMessage,2,4); + packet(0x0089,7,clif->pTickSend,3); + packet(0x008c,13,clif->pGetCharNameRequest,9); + packet(0x0094,14,clif->pMoveToKafra,4,10); + packet(0x009b,2,clif->pCloseKafra,0); + packet(0x009f,18,clif->pActionRequest,6,17); + packet(0x00a2,7,clif->pTakeItem,3); + packet(0x00a7,7,clif->pWalkToXY,4); + packet(0x00f3,8,clif->pChangeDir,3,7); + packet(0x00f5,29,clif->pWantToConnection,3,10,20,24,28); + packet(0x00f7,14,clif->pSolveCharName,10); + packet(0x0113,110,clif->pUseSkillToPosMoreInfo,4,9,22,28,30); + packet(0x0116,12,clif->pDropItem,4,10); + packet(0x0190,15,clif->pUseItem,3,11); + packet(0x0193,21,clif->pMoveFromKafra,4,17); + packet(0x0221,-1); + packet(0x0222,6,clif->pWeaponRefine,2); + packet(0x0223,8); +#endif + +//2004-12-13aSakexe +#if PACKETVER >= 20041213 +//skipped: many packets being set to -1 + packet(0x0066,3); + packet(0x0070,3); + packet(0x01ca,3); + packet(0x021e,6); + packet(0x021f,66); + packet(0x0220,10); +#endif + +//2005-01-10bSakexe +#if PACKETVER >= 20050110 + packet(0x0072,26,clif->pUseSkillToId,8,16,22); + packet(0x007e,114,clif->pUseSkillToPosMoreInfo,10,18,22,32,34); + packet(0x0085,23,clif->pChangeDir,12,22); + packet(0x0089,9,clif->pTickSend,5); + packet(0x008c,8,clif->pGetCharNameRequest,4); + packet(0x0094,20,clif->pMoveToKafra,10,16); + packet(0x009b,32,clif->pWantToConnection,3,12,23,27,31); + packet(0x009f,17,clif->pUseItem,5,13); + packet(0x00a2,11,clif->pSolveCharName,7); + packet(0x00a7,13,clif->pWalkToXY,10); + packet(0x00f3,-1,clif->pGlobalMessage,2,4); + packet(0x00f5,9,clif->pTakeItem,5); + packet(0x00f7,21,clif->pMoveFromKafra,11,17); + packet(0x0113,34,clif->pUseSkillToPos,10,18,22,32); + packet(0x0116,20,clif->pDropItem,15,18); + packet(0x0190,20,clif->pActionRequest,9,19); + packet(0x0193,2,clif->pCloseKafra,0); +#endif + +//2005-03-28aSakexe +#if PACKETVER >= 20050328 + packet(0x0224,10); + packet(0x0225,2,clif->pTaekwon,0); + packet(0x0226,282); +#endif + +//2005-04-04aSakexe +#if PACKETVER >= 20050404 + packet(0x0227,18); + packet(0x0228,18); +#endif + +//2005-04-11aSakexe +#if PACKETVER >= 20050411 + packet(0x0229,15); + packet(0x022a,58); + packet(0x022b,57); + packet(0x022c,64); +#endif + +//2005-04-25aSakexe +#if PACKETVER >= 20050425 + packet(0x022d,5,clif->pHomMenu,2,4); + packet(0x0232,9,clif->pHomMoveTo,2,6); + packet(0x0233,11,clif->pHomAttack,2,6,10); + packet(0x0234,6,clif->pHomMoveToMaster,2); +#endif + +//2005-05-09aSakexe +#if PACKETVER >= 20050509 + packet(0x0072,25,clif->pUseSkillToId,6,10,21); + packet(0x007e,102,clif->pUseSkillToPosMoreInfo,5,9,12,20,22); + packet(0x0085,11,clif->pChangeDir,7,10); + packet(0x0089,8,clif->pTickSend,4); + packet(0x008c,11,clif->pGetCharNameRequest,7); + packet(0x0094,14,clif->pMoveToKafra,7,10); + packet(0x009b,26,clif->pWantToConnection,4,9,17,21,25); + packet(0x009f,14,clif->pUseItem,4,10); + packet(0x00a2,15,clif->pSolveCharName,11); + packet(0x00a7,8,clif->pWalkToXY,5); + packet(0x00f5,8,clif->pTakeItem,4); + packet(0x00f7,22,clif->pMoveFromKafra,14,18); + packet(0x0113,22,clif->pUseSkillToPos,5,9,12,20); + packet(0x0116,10,clif->pDropItem,5,8); + packet(0x0190,19,clif->pActionRequest,5,18); +#endif + +//2005-05-23aSakexe +#if PACKETVER >= 20050523 + packet(0x022e,69); + packet(0x0230,12); +#endif + +//2005-05-30aSakexe +#if PACKETVER >= 20050530 + packet(0x022e,71); + packet(0x0235,-1); + packet(0x0236,10); + packet(0x0237,2,clif->pRankingPk,0); + packet(0x0238,282); +#endif + +//2005-05-31aSakexe +#if PACKETVER >= 20050531 + packet(0x0216,2); + packet(0x0239,11); +#endif + +//2005-06-08aSakexe +#if PACKETVER >= 20050608 + packet(0x0216,6); + packet(0x0217,2,clif->pBlacksmith,0); + packet(0x022f,5); + packet(0x0231,26,clif->pChangeHomunculusName,0); + packet(0x023a,4); + packet(0x023b,36,clif->pStoragePassword,2,4,20); + packet(0x023c,6); +#endif + +//2005-06-22aSakexe +#if PACKETVER >= 20050622 + packet(0x022e,71); + +#endif + +//2005-06-28aSakexe +#if PACKETVER >= 20050628 + packet(0x0072,34,clif->pUseSkillToId,6,17,30); + packet(0x007e,113,clif->pUseSkillToPosMoreInfo,12,15,18,31,33); + packet(0x0085,17,clif->pChangeDir,8,16); + packet(0x0089,13,clif->pTickSend,9); + packet(0x008c,8,clif->pGetCharNameRequest,4); + packet(0x0094,31,clif->pMoveToKafra,16,27); + packet(0x009b,32,clif->pWantToConnection,9,15,23,27,31); + packet(0x009f,19,clif->pUseItem,9,15); + packet(0x00a2,9,clif->pSolveCharName,5); + packet(0x00a7,11,clif->pWalkToXY,8); + packet(0x00f5,13,clif->pTakeItem,9); + packet(0x00f7,18,clif->pMoveFromKafra,11,14); + packet(0x0113,33,clif->pUseSkillToPos,12,15,18,31); + packet(0x0116,12,clif->pDropItem,3,10); + packet(0x0190,24,clif->pActionRequest,11,23); + packet(0x0216,-1); + packet(0x023d,-1); + packet(0x023e,4); +#endif + +//2005-07-18aSakexe +#if PACKETVER >= 20050718 + packet(0x0072,19,clif->pUseSkillToId,5,11,15); + packet(0x007e,110,clif->pUseSkillToPosMoreInfo,9,15,23,28,30); + packet(0x0085,11,clif->pChangeDir,6,10); + packet(0x0089,7,clif->pTickSend,3); + packet(0x008c,11,clif->pGetCharNameRequest,7); + packet(0x0094,21,clif->pMoveToKafra,12,17); + packet(0x009b,31,clif->pWantToConnection,3,13,22,26,30); + packet(0x009f,12,clif->pUseItem,3,8); + packet(0x00a2,18,clif->pSolveCharName,14); + packet(0x00a7,15,clif->pWalkToXY,12); + packet(0x00f5,7,clif->pTakeItem,3); + packet(0x00f7,13,clif->pMoveFromKafra,5,9); + packet(0x0113,30,clif->pUseSkillToPos,9,15,23,28); + packet(0x0116,12,clif->pDropItem,6,10); + packet(0x0190,21,clif->pActionRequest,5,20); + packet(0x0216,6); + packet(0x023f,2,clif->pMail_refreshinbox,0); + packet(0x0240,8); + packet(0x0241,6,clif->pMail_read,2); + packet(0x0242,-1); + packet(0x0243,6,clif->pMail_delete,2); + packet(0x0244,6,clif->pMail_getattach,2); + packet(0x0245,7); + packet(0x0246,4,clif->pMail_winopen,2); + packet(0x0247,8,clif->pMail_setattach,2,4); + packet(0x0248,68); + packet(0x0249,3); + packet(0x024a,70); + packet(0x024b,4,clif->pAuction_cancelreg,0); + packet(0x024c,8,clif->pAuction_setitem,0); + packet(0x024d,14); + packet(0x024e,6,clif->pAuction_cancel,0); + packet(0x024f,10,clif->pAuction_bid,0); + packet(0x0250,3); + packet(0x0251,2); + packet(0x0252,-1); +#endif + +//2005-07-19bSakexe +#if PACKETVER >= 20050719 + packet(0x0072,34,clif->pUseSkillToId,6,17,30); + packet(0x007e,113,clif->pUseSkillToPosMoreInfo,12,15,18,31,33); + packet(0x0085,17,clif->pChangeDir,8,16); + packet(0x0089,13,clif->pTickSend,9); + packet(0x008c,8,clif->pGetCharNameRequest,4); + packet(0x0094,31,clif->pMoveToKafra,16,27); + packet(0x009b,32,clif->pWantToConnection,9,15,23,27,31); + packet(0x009f,19,clif->pUseItem,9,15); + packet(0x00a2,9,clif->pSolveCharName,5); + packet(0x00a7,11,clif->pWalkToXY,8); + packet(0x00f5,13,clif->pTakeItem,9); + packet(0x00f7,18,clif->pMoveFromKafra,11,14); + packet(0x0113,33,clif->pUseSkillToPos,12,15,18,31); + packet(0x0116,12,clif->pDropItem,3,10); + packet(0x0190,24,clif->pActionRequest,11,23); +#endif + +//2005-08-01aSakexe +#if PACKETVER >= 20050801 + packet(0x0245,3); + packet(0x0251,4); +#endif + +//2005-08-08aSakexe +#if PACKETVER >= 20050808 + packet(0x024d,12,clif->pAuction_register,0); + packet(0x024e,4); +#endif + +//2005-08-17aSakexe +#if PACKETVER >= 20050817 + packet(0x0253,3); + packet(0x0254,3,clif->pFeelSaveOk,0); +#endif + +//2005-08-29aSakexe +#if PACKETVER >= 20050829 + packet(0x0240,-1); + packet(0x0248,-1,clif->pMail_send,2,4,28,68); + packet(0x0255,5); + packet(0x0256,-1); + packet(0x0257,8); +#endif + +//2005-09-12bSakexe +#if PACKETVER >= 20050912 + packet(0x0256,5); + packet(0x0258,2); + packet(0x0259,3); +#endif + +//2005-10-10aSakexe +#if PACKETVER >= 20051010 + packet(0x020e,32); + packet(0x025a,-1); + packet(0x025b,6,clif->pCooking,0); +#endif + +//2005-10-13aSakexe +#if PACKETVER >= 20051013 + packet(0x007a,6); + packet(0x0251,32); + packet(0x025c,4,clif->pAuction_buysell,0); +#endif + +//2005-10-17aSakexe +#if PACKETVER >= 20051017 + packet(0x007a,58); + packet(0x025d,6,clif->pAuction_close,0); + packet(0x025e,4); +#endif + +//2005-10-24aSakexe +#if PACKETVER >= 20051024 + packet(0x025f,6); + packet(0x0260,6); +#endif + +//2005-11-07aSakexe +#if PACKETVER >= 20051107 + packet(0x024e,6,clif->pAuction_cancel,0); + packet(0x0251,34,clif->pAuction_search,0); +#endif + +//2006-01-09aSakexe +#if PACKETVER >= 20060109 + packet(0x0261,11); + packet(0x0262,11); + packet(0x0263,11); + packet(0x0264,20); + packet(0x0265,20); + packet(0x0266,30); + packet(0x0267,4); + packet(0x0268,4); + packet(0x0269,4); + packet(0x026a,4); + packet(0x026b,4); + packet(0x026c,4); + packet(0x026d,4); + packet(0x026f,2); + packet(0x0270,2); + packet(0x0271,38); + packet(0x0272,44); +#endif + +//2006-01-26aSakexe +#if PACKETVER >= 20060126 + packet(0x0271,40); + +#endif + +//2006-03-06aSakexe +#if PACKETVER >= 20060306 + packet(0x0273,6); + packet(0x0274,8); +#endif + +//2006-03-13aSakexe +#if PACKETVER >= 20060313 + packet(0x0273,30,clif->pMail_return,2,6); +#endif + +//2006-03-27aSakexe +#if PACKETVER >= 20060327 + packet(0x0072,26,clif->pUseSkillToId,11,18,22); + packet(0x007e,120,clif->pUseSkillToPosMoreInfo,5,15,29,38,40); + packet(0x0085,12,clif->pChangeDir,7,11); + //packet(0x0089,13,clif->pTickSend,9); + packet(0x008c,12,clif->pGetCharNameRequest,8); + packet(0x0094,23,clif->pMoveToKafra,5,19); + packet(0x009b,37,clif->pWantToConnection,9,21,28,32,36); + packet(0x009f,24,clif->pUseItem,9,20); + packet(0x00a2,11,clif->pSolveCharName,7); + packet(0x00a7,15,clif->pWalkToXY,12); + packet(0x00f5,13,clif->pTakeItem,9); + packet(0x00f7,26,clif->pMoveFromKafra,11,22); + packet(0x0113,40,clif->pUseSkillToPos,5,15,29,38); + packet(0x0116,17,clif->pDropItem,8,15); + packet(0x0190,18,clif->pActionRequest,7,17); +#endif + +//2006-10-23aSakexe +#if PACKETVER >= 20061023 + packet(0x006d,110); +#endif + +//2006-04-24aSakexe to 2007-01-02aSakexe +#if PACKETVER >= 20060424 + packet(0x023e,8); + packet(0x0277,84); + packet(0x0278,2); + packet(0x0279,2); + packet(0x027a,-1); + packet(0x027b,14); + packet(0x027c,60); + packet(0x027d,62); + packet(0x027e,-1); + packet(0x027f,8); + packet(0x0280,12); + packet(0x0281,4); + packet(0x0282,284); + packet(0x0283,6); + packet(0x0284,14); + packet(0x0285,6); + packet(0x0286,4); + packet(0x0287,-1); + packet(0x0288,6); + packet(0x0289,8); + packet(0x028a,18); + packet(0x028b,-1); + packet(0x028c,46); + packet(0x028d,34); + packet(0x028e,4); + packet(0x028f,6); + packet(0x0290,4); + packet(0x0291,4); + packet(0x0292,2,clif->pAutoRevive,0); + packet(0x0293,70); + packet(0x0294,10); + packet(0x0295,-1); + packet(0x0296,-1); + packet(0x0297,-1); + packet(0x0298,8); + packet(0x0299,6); + packet(0x029a,27); + packet(0x029c,66); + packet(0x029d,-1); + packet(0x029e,11); + packet(0x029f,3,clif->pmercenary_action,0); + packet(0x02a0,-1); + packet(0x02a1,-1); + packet(0x02a2,8); +#endif + +//2007-01-08aSakexe +#if PACKETVER >= 20070108 + packet(0x0072,30,clif->pUseSkillToId,10,14,26); + packet(0x007e,120,clif->pUseSkillToPosMoreInfo,10,19,23,38,40); + packet(0x0085,14,clif->pChangeDir,10,13); + packet(0x0089,11,clif->pTickSend,7); + packet(0x008c,17,clif->pGetCharNameRequest,13); + packet(0x0094,17,clif->pMoveToKafra,4,13); + packet(0x009b,35,clif->pWantToConnection,7,21,26,30,34); + packet(0x009f,21,clif->pUseItem,7,17); + packet(0x00a2,10,clif->pSolveCharName,6); + packet(0x00a7,8,clif->pWalkToXY,5); + packet(0x00f5,11,clif->pTakeItem,7); + packet(0x00f7,15,clif->pMoveFromKafra,3,11); + packet(0x0113,40,clif->pUseSkillToPos,10,19,23,38); + packet(0x0116,19,clif->pDropItem,11,17); + packet(0x0190,10,clif->pActionRequest,4,9); +#endif + +//2007-01-22aSakexe +#if PACKETVER >= 20070122 + packet(0x02a3,18); + packet(0x02a4,2); +#endif + +//2007-01-29aSakexe +#if PACKETVER >= 20070129 + packet(0x029b,72); + packet(0x02a3,-1); + packet(0x02a4,-1); + packet(0x02a5,8); + +#endif + +//2007-02-05aSakexe +#if PACKETVER >= 20070205 + packet(0x02aa,4); + packet(0x02ab,36); + packet(0x02ac,6); +#endif + +//2007-02-12aSakexe +#if PACKETVER >= 20070212 + packet(0x0072,25,clif->pUseSkillToId,6,10,21); + packet(0x007e,102,clif->pUseSkillToPosMoreInfo,5,9,12,20,22); + packet(0x0085,11,clif->pChangeDir,7,10); + packet(0x0089,8,clif->pTickSend,4); + packet(0x008c,11,clif->pGetCharNameRequest,7); + packet(0x0094,14,clif->pMoveToKafra,7,10); + packet(0x009b,26,clif->pWantToConnection,4,9,17,21,25); + packet(0x009f,14,clif->pUseItem,4,10); + packet(0x00a2,15,clif->pSolveCharName,11); + //packet(0x00a7,8,clif->pWalkToXY,5); + packet(0x00f5,8,clif->pTakeItem,4); + packet(0x00f7,22,clif->pMoveFromKafra,14,18); + packet(0x0113,22,clif->pUseSkillToPos,5,9,12,20); + packet(0x0116,10,clif->pDropItem,5,8); + packet(0x0190,19,clif->pActionRequest,5,18); +#endif + +//2007-05-07aSakexe +#if PACKETVER >= 20070507 + packet(0x01fd,15,clif->pRepairItem,2); +#endif + +//2007-02-27aSakexe to 2007-10-02aSakexe +#if PACKETVER >= 20070227 + packet(0x0288,10,clif->pcashshop_buy,2,4,6); + packet(0x0289,12); + packet(0x02a6,22); + packet(0x02a7,22); + packet(0x02a8,162); + packet(0x02a9,58); + packet(0x02ad,8); + packet(0x02b0,85); + packet(0x02b1,-1); + packet(0x02b2,-1); + packet(0x02b3,107); + packet(0x02b4,6); + packet(0x02b5,-1); + packet(0x02b6,7,clif->pquestStateAck,2,6); + packet(0x02b7,7); + packet(0x02b8,22); + packet(0x02b9,191); + packet(0x02ba,11,clif->pHotkey,2,4,5,9); + packet(0x02bb,8); + packet(0x02bc,6); + packet(0x02bf,10); + packet(0x02c0,2); + packet(0x02c1,-1); + packet(0x02c2,-1); + packet(0x02c4,26,clif->pPartyInvite2,2); + packet(0x02c5,30); + packet(0x02c6,30); + packet(0x02c7,7,clif->pReplyPartyInvite2,2,6); + packet(0x02c8,3,clif->pPartyTick,2); + packet(0x02c9,3); + packet(0x02ca,3); + packet(0x02cb,20); + packet(0x02cc,4); + packet(0x02cd,26); + packet(0x02ce,10); + packet(0x02cf,6); + packet(0x02d0,-1); + packet(0x02d1,-1); + packet(0x02d2,-1); + packet(0x02d3,4); + packet(0x02d4,29); + packet(0x02d5,2); + packet(0x02d6,6,clif->pViewPlayerEquip,2); + packet(0x02d7,-1); + packet(0x02d8,10,clif->pEquipTick,6); + packet(0x02d9,10); + packet(0x02da,3); + packet(0x02db,-1,clif->pBattleChat,2,4); + packet(0x02dc,-1); + packet(0x02dd,32); + packet(0x02de,6); + packet(0x02df,36); + packet(0x02e0,34); +#endif + +//2007-10-23aSakexe +#if PACKETVER >= 20071023 + packet(0x02cb,65); + packet(0x02cd,71); +#endif + +//2007-11-06aSakexe +#if PACKETVER >= 20071106 + packet(0x0078,55); + packet(0x007c,42); + packet(0x022c,65); + packet(0x029b,80); +#endif + +//2007-11-13aSakexe +#if PACKETVER >= 20071113 + packet(0x02e1,33); +#endif + +//2007-11-20aSakexe +#if PACKETVER >= 20071120 + //packet(0x01df,10 <- ???); + packet(0x02e2,14); + packet(0x02e3,25); + packet(0x02e4,8); + packet(0x02e5,8); + packet(0x02e6,6); +#endif + +//2007-11-27aSakexe +#if PACKETVER >= 20071127 + packet(0x02e7,-1); +#endif + +//2008-01-02aSakexe +#if PACKETVER >= 20080102 + packet(0x01df,6,clif->pGMReqAccountName,2); + packet(0x02e8,-1); + packet(0x02e9,-1); + packet(0x02ea,-1); + packet(0x02eb,13); + packet(0x02ec,67); + packet(0x02ed,59); + packet(0x02ee,60); + packet(0x02ef,8); +#endif + +//2008-03-18aSakexe +#if PACKETVER >= 20080318 + packet(0x02bf,-1); + packet(0x02c0,-1); + packet(0x02f0,10); + packet(0x02f1,2,clif->pProgressbar,0); + packet(0x02f2,2); +#endif + +//2008-03-25bSakexe +#if PACKETVER >= 20080325 + packet(0x02f3,-1); + packet(0x02f4,-1); + packet(0x02f5,-1); + packet(0x02f6,-1); + packet(0x02f7,-1); + packet(0x02f8,-1); + packet(0x02f9,-1); + packet(0x02fa,-1); + packet(0x02fb,-1); + packet(0x02fc,-1); + packet(0x02fd,-1); + packet(0x02fe,-1); + packet(0x02ff,-1); + packet(0x0300,-1); +#endif + +//2008-04-01aSakexe +#if PACKETVER >= 20080401 + packet(0x0301,-1); + packet(0x0302,-1); + packet(0x0303,-1); + packet(0x0304,-1); + packet(0x0305,-1); + packet(0x0306,-1); + packet(0x0307,-1); + packet(0x0308,-1); + packet(0x0309,-1); + packet(0x030a,-1); + packet(0x030b,-1); + packet(0x030c,-1); + packet(0x030d,-1); + packet(0x030e,-1); + packet(0x030f,-1); + packet(0x0310,-1); + packet(0x0311,-1); + packet(0x0312,-1); + packet(0x0313,-1); + packet(0x0314,-1); + packet(0x0315,-1); + packet(0x0316,-1); + packet(0x0317,-1); + packet(0x0318,-1); + packet(0x0319,-1); + packet(0x031a,-1); + packet(0x031b,-1); + packet(0x031c,-1); + packet(0x031d,-1); + packet(0x031e,-1); + packet(0x031f,-1); + packet(0x0320,-1); + packet(0x0321,-1); + packet(0x0322,-1); + packet(0x0323,-1); + packet(0x0324,-1); + packet(0x0325,-1); + packet(0x0326,-1); + packet(0x0327,-1); + packet(0x0328,-1); + packet(0x0329,-1); + packet(0x032a,-1); + packet(0x032b,-1); + packet(0x032c,-1); + packet(0x032d,-1); + packet(0x032e,-1); + packet(0x032f,-1); + packet(0x0330,-1); + packet(0x0331,-1); + packet(0x0332,-1); + packet(0x0333,-1); + packet(0x0334,-1); + packet(0x0335,-1); + packet(0x0336,-1); + packet(0x0337,-1); + packet(0x0338,-1); + packet(0x0339,-1); + packet(0x033a,-1); + packet(0x033b,-1); + packet(0x033c,-1); + packet(0x033d,-1); + packet(0x033e,-1); + packet(0x033f,-1); + packet(0x0340,-1); + packet(0x0341,-1); + packet(0x0342,-1); + packet(0x0343,-1); + packet(0x0344,-1); + packet(0x0345,-1); + packet(0x0346,-1); + packet(0x0347,-1); + packet(0x0348,-1); + packet(0x0349,-1); + packet(0x034a,-1); + packet(0x034b,-1); + packet(0x034c,-1); + packet(0x034d,-1); + packet(0x034e,-1); + packet(0x034f,-1); + packet(0x0350,-1); + packet(0x0351,-1); + packet(0x0352,-1); + packet(0x0353,-1); + packet(0x0354,-1); + packet(0x0355,-1); + packet(0x0356,-1); + packet(0x0357,-1); + packet(0x0358,-1); + packet(0x0359,-1); + packet(0x035a,-1); +#endif + +//2008-05-27aSakexe +#if PACKETVER >= 20080527 + packet(0x035b,-1); + packet(0x035c,2); + packet(0x035d,-1); + packet(0x035e,2); + packet(0x035f,-1); + packet(0x0389,-1); +#endif + +//2008-08-20aSakexe +#if PACKETVER >= 20080820 + packet(0x040c,-1); + packet(0x040d,-1); + packet(0x040e,-1); + packet(0x040f,-1); + packet(0x0410,-1); + packet(0x0411,-1); + packet(0x0412,-1); + packet(0x0413,-1); + packet(0x0414,-1); + packet(0x0415,-1); + packet(0x0416,-1); + packet(0x0417,-1); + packet(0x0418,-1); + packet(0x0419,-1); + packet(0x041a,-1); + packet(0x041b,-1); + packet(0x041c,-1); + packet(0x041d,-1); + packet(0x041e,-1); + packet(0x041f,-1); + packet(0x0420,-1); + packet(0x0421,-1); + packet(0x0422,-1); + packet(0x0423,-1); + packet(0x0424,-1); + packet(0x0425,-1); + packet(0x0426,-1); + packet(0x0427,-1); + packet(0x0428,-1); + packet(0x0429,-1); + packet(0x042a,-1); + packet(0x042b,-1); + packet(0x042c,-1); + packet(0x042d,-1); + packet(0x042e,-1); + packet(0x042f,-1); + packet(0x0430,-1); + packet(0x0431,-1); + packet(0x0432,-1); + packet(0x0433,-1); + packet(0x0434,-1); + packet(0x0435,-1); +#endif + +//2008-09-10aSakexe +#if PACKETVER >= 20080910 + packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0437,7,clif->pActionRequest,2,6); + packet(0x0438,10,clif->pUseSkillToId,2,4,6); + packet(0x0439,8,clif->pUseItem,2,4); +#endif + +//2008-11-13aSakexe +#if PACKETVER >= 20081113 + packet(0x043d,8); + packet(0x043e,-1); + packet(0x043f,8); +#endif + +//2008-11-26aSakexe +#if PACKETVER >= 20081126 + packet(0x01a2,37); + packet(0x0440,10); + packet(0x0441,4); +#endif + +//2008-12-10aSakexe +#if PACKETVER >= 20081210 + packet(0x0442,-1); + packet(0x0443,8,clif->pSkillSelectMenu,2,6); +#endif + +//2009-01-14aSakexe +#if PACKETVER >= 20090114 + packet(0x043f,25); + packet(0x0444,-1); + packet(0x0445,10); +#endif + +//2009-02-18aSakexe +#if PACKETVER >= 20090218 + packet(0x0446,14); +#endif + +//2009-02-25aSakexe +#if PACKETVER >= 20090225 + packet(0x0448,-1); +#endif + +//2009-03-30aSakexe +#if PACKETVER >= 20090330 + packet(0x0449,4); +#endif + +//2009-04-08aSakexe +#if PACKETVER >= 20090408 + packet(0x02a6,-1); + packet(0x02a7,-1); + packet(0x044a,6); +#endif + +//2008-08-27aRagexeRE +#if PACKETVER >= 20080827 + packet(0x0072,22,clif->pUseSkillToId,9,15,18); + packet(0x007c,44); + packet(0x007e,105,clif->pUseSkillToPosMoreInfo,10,14,18,23,25); + packet(0x0085,10,clif->pChangeDir,4,9); + packet(0x0089,11,clif->pTickSend,7); + packet(0x008c,14,clif->pGetCharNameRequest,10); + packet(0x0094,19,clif->pMoveToKafra,3,15); + packet(0x009b,34,clif->pWantToConnection,7,15,25,29,33); + packet(0x009f,20,clif->pUseItem,7,20); + packet(0x00a2,14,clif->pSolveCharName,10); + packet(0x00a7,9,clif->pWalkToXY,6); + packet(0x00f5,11,clif->pTakeItem,7); + packet(0x00f7,17,clif->pMoveFromKafra,3,13); + packet(0x0113,25,clif->pUseSkillToPos,10,14,18,23); + packet(0x0116,17,clif->pDropItem,6,15); + packet(0x0190,23,clif->pActionRequest,9,22); + packet(0x02e2,20); + packet(0x02e3,22); + packet(0x02e4,11); + packet(0x02e5,9); +#endif + +//2008-09-10aRagexeRE +#if PACKETVER >= 20080910 + packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0437,7,clif->pActionRequest,2,6); + packet(0x0438,10,clif->pUseSkillToId,2,4,6); + packet(0x0439,8,clif->pUseItem,2,4); + +#endif + +//2008-11-12aRagexeRE +#if PACKETVER >= 20081112 + packet(0x043d,8); + //packet(0x043e,-1); + packet(0x043f,8); +#endif + +//2008-12-17aRagexeRE +#if PACKETVER >= 20081217 + packet(0x01a2,37); + //packet(0x0440,10); + //packet(0x0441,4); + //packet(0x0442,8); + //packet(0x0443,8); +#endif + +//2008-12-17bRagexeRE +#if PACKETVER >= 20081217 + packet(0x006d,114); + +#endif + +//2009-01-21aRagexeRE +#if PACKETVER >= 20090121 + packet(0x043f,25); + //packet(0x0444,-1); + //packet(0x0445,10); +#endif + +//2009-02-18aRagexeRE +#if PACKETVER >= 20090218 + //packet(0x0446,14); +#endif + +//2009-02-26cRagexeRE +#if PACKETVER >= 20090226 + //packet(0x0448,-1); +#endif + +//2009-04-01aRagexeRE +#if PACKETVER >= 20090401 + //packet(0x0449,4); +#endif + +//2009-05-14aRagexeRE +#if PACKETVER >= 20090514 + //packet(0x044b,2); +#endif + +//2009-05-20aRagexeRE +#if PACKETVER >= 20090520 + //packet(0x07d0,6); + //packet(0x07d1,2); + //packet(0x07d2,-1); + //packet(0x07d3,4); + //packet(0x07d4,4); + //packet(0x07d5,4); + //packet(0x07d6,4); + //packet(0x0447,2); +#endif + +//2009-06-03aRagexeRE +#if PACKETVER >= 20090603 + packet(0x07d7,8,clif->pPartyChangeOption,2,6,7); + packet(0x07d8,8); + packet(0x07d9,254); + packet(0x07da,6,clif->pPartyChangeLeader,2); +#endif + +//2009-06-10aRagexeRE +#if PACKETVER >= 20090610 + //packet(0x07db,8); +#endif + +//2009-06-17aRagexeRE +#if PACKETVER >= 20090617 + packet(0x07d9,268); + //packet(0x07dc,6); + //packet(0x07dd,54); + //packet(0x07de,30); + //packet(0x07df,54); +#endif + +//2009-07-01aRagexeRE +#if PACKETVER >= 20090701 + //packet(0x0275,37); + //packet(0x0276,-1); +#endif + +//2009-07-08aRagexeRE +#if PACKETVER >= 20090708 + //packet(0x07e0,58); +#endif + +//2009-07-15aRagexeRE +#if PACKETVER >= 20090715 + packet(0x07e1,15); +#endif + +//2009-08-05aRagexeRE +#if PACKETVER >= 20090805 + packet(0x07e2,8); +#endif + +//2009-08-18aRagexeRE +#if PACKETVER >= 20090818 + packet(0x07e3,6); + packet(0x07e4,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x07e6,8); +#endif + +//2009-08-25aRagexeRE +#if PACKETVER >= 20090825 + //packet(0x07e6,28); + packet(0x07e7,5); +#endif + +//2009-09-22aRagexeRE +#if PACKETVER >= 20090922 + packet(0x07e5,8); + packet(0x07e6,8); + packet(0x07e7,32); + packet(0x07e8,-1); + packet(0x07e9,5); +#endif + +//2009-09-29aRagexeRE +#if PACKETVER >= 20090929 + //packet(0x07ea,2); + //packet(0x07eb,-1); + //packet(0x07ec,6); + //packet(0x07ed,8); + //packet(0x07ee,6); + //packet(0x07ef,8); + //packet(0x07f0,4); + //packet(0x07f2,4); + //packet(0x07f3,3); +#endif + +//2009-10-06aRagexeRE +#if PACKETVER >= 20091006 + //packet(0x07ec,8); + //packet(0x07ed,10); + //packet(0x07f0,8); + //packet(0x07f1,15); + //packet(0x07f2,6); + //packet(0x07f3,4); + //packet(0x07f4,3); +#endif + +//2009-10-27aRagexeRE +#if PACKETVER >= 20091027 + packet(0x07f5,6,clif->pGMReqAccountName,2); + packet(0x07f6,14); +#endif + +//2009-11-03aRagexeRE +#if PACKETVER >= 20091103 + packet(0x07f7,-1); + packet(0x07f8,-1); + packet(0x07f9,-1); +#endif + +//2009-11-17aRagexeRE +#if PACKETVER >= 20091117 + packet(0x07fa,8); + +#endif + +//2009-11-24aRagexeRE +#if PACKETVER >= 20091124 + packet(0x07fb,25); +#endif + +//2009-12-01aRagexeRE +#if PACKETVER >= 20091201 + //packet(0x07fc,10); + //packet(0x07fd,-1); + packet(0x07fe,26); + //packet(0x07ff,-1); +#endif + +//2009-12-15aRagexeRE +#if PACKETVER >= 20091215 + packet(0x0800,-1); + //packet(0x0801,-1); +#endif + +//2009-12-22aRagexeRE +#if PACKETVER >= 20091222 + packet(0x0802,18,clif->pPartyBookingRegisterReq,2,4,6); // Booking System + packet(0x0803,4); + packet(0x0804,8); // Booking System + packet(0x0805,-1); + packet(0x0806,4,clif->pPartyBookingDeleteReq,2);// Booking System + //packet(0x0807,2); + packet(0x0808,4); // Booking System + //packet(0x0809,14); + //packet(0x080A,50); + //packet(0x080B,18); + //packet(0x080C,6); +#endif + + //2009-12-29aRagexeRE +#if PACKETVER >= 20091229 + packet(0x0804,14,clif->pPartyBookingSearchReq,2,4,6,8,12);// Booking System + packet(0x0806,2,clif->pPartyBookingDeleteReq,0);// Booking System + packet(0x0807,4); + packet(0x0808,14,clif->pPartyBookingUpdateReq,2); // Booking System + packet(0x0809,50); + packet(0x080A,18); + packet(0x080B,6);// Booking System +#endif + + //2010-01-05aRagexeRE +#if PACKETVER >= 20100105 + packet(0x0801,-1,clif->pPurchaseReq2,2,4,8,12); +#endif + + //2010-01-26aRagexeRE +#if PACKETVER >= 20100126 + //packet(0x080C,2); + //packet(0x080D,3); + packet(0x080E,14); +#endif + + //2010-02-09aRagexeRE +#if PACKETVER >= 20100209 + //packet(0x07F0,6); +#endif + + //2010-02-23aRagexeRE +#if PACKETVER >= 20100223 + packet(0x080F,20); +#endif + + //2010-03-03aRagexeRE +#if PACKETVER >= 20100303 + packet(0x0810,3); + packet(0x0811,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + //packet(0x0812,86); + //packet(0x0813,6); + //packet(0x0814,6); + //packet(0x0815,-1); + //packet(0x0817,-1); + //packet(0x0818,6); + //packet(0x0819,4); +#endif + + //2010-03-09aRagexeRE +#if PACKETVER >= 20100309 + packet(0x0813,-1); + //packet(0x0814,2); + //packet(0x0815,6); + packet(0x0816,6); + packet(0x0818,-1); + //packet(0x0819,10); + //packet(0x081A,4); + //packet(0x081B,4); + //packet(0x081C,6); + packet(0x081d,22); + packet(0x081e,8); +#endif + + //2010-03-23aRagexeRE +#if PACKETVER >= 20100323 + //packet(0x081F,-1); +#endif + + //2010-04-06aRagexeRE +#if PACKETVER >= 20100406 + //packet(0x081A,6); +#endif + + //2010-04-13aRagexeRE +#if PACKETVER >= 20100413 + //packet(0x081A,10); + packet(0x0820,11); + //packet(0x0821,2); + //packet(0x0822,9); + //packet(0x0823,-1); +#endif + + //2010-04-14dRagexeRE +#if PACKETVER >= 20100414 + //packet(0x081B,8); +#endif + + //2010-04-20aRagexeRE +#if PACKETVER >= 20100420 + packet(0x0812,8); + packet(0x0814,86); + packet(0x0815,2,clif->pReqCloseBuyingStore,0); + packet(0x0817,6,clif->pReqClickBuyingStore,2); + packet(0x0819,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x081a,4); + packet(0x081b,10); + packet(0x081c,10); + packet(0x0824,6); +#endif + + //2010-06-01aRagexeRE +#if PACKETVER >= 20100601 + //packet(0x0825,-1); + //packet(0x0826,4); + packet(0x0835,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0836,-1); + packet(0x0837,3); + //packet(0x0838,3); +#endif + + //2010-06-08aRagexeRE +#if PACKETVER >= 20100608 + packet(0x0838,2,clif->pSearchStoreInfoNextPage,0); + packet(0x083A,4); // Search Stalls Feature + packet(0x083B,2,clif->pCloseSearchStoreInfo,0); + packet(0x083C,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x083D,6); +#endif + +//2010-06-15aRagexeRE +#if PACKETVER >= 20100615 + //packet(0x083E,26); +#endif + +//2010-06-22aRagexeRE +#if PACKETVER >= 20100622 + //packet(0x083F,22); +#endif + +//2010-06-29aRagexeRE +#if PACKETVER >= 20100629 + packet(0x00AA,9); + //packet(0x07F1,18); + //packet(0x07F2,8); + //packet(0x07F3,6); +#endif + +//2010-07-01aRagexeRE +#if PACKETVER >= 20100701 + packet(0x083A,5);// Search Stalls Feature +#endif + +//2010-07-13aRagexeRE +#if PACKETVER >= 20100713 + //packet(0x0827,6); + //packet(0x0828,14); + //packet(0x0829,6); + //packet(0x082A,10); + //packet(0x082B,6); + //packet(0x082C,14); + //packet(0x0840,-1); + //packet(0x0841,19); +#endif + +//2010-07-14aRagexeRE +#if PACKETVER >= 20100714 + //packet(0x841,4); +#endif + +//2010-08-03aRagexeRE +#if PACKETVER >= 20100803 + packet(0x0839,66); + packet(0x0842,6,clif->pGMRecall2,2); + packet(0x0843,6,clif->pGMRemove2,2); +#endif + +//2010-11-24aRagexeRE +#if PACKETVER >= 20101124 + packet(0x0288,-1,clif->pcashshop_buy,4,8); + packet(0x0436,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x035f,5,clif->pWalkToXY,2); + packet(0x0360,6,clif->pTickSend,2); + packet(0x0361,5,clif->pChangeDir,2,4); + packet(0x0362,6,clif->pTakeItem,2); + packet(0x0363,6,clif->pDropItem,2,4); + packet(0x0364,8,clif->pMoveToKafra,2,4); + packet(0x0365,8,clif->pMoveFromKafra,2,4); + packet(0x0366,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0367,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x0368,6,clif->pGetCharNameRequest,2); + packet(0x0369,6,clif->pSolveCharName,2); + packet(0x0856,-1); + packet(0x0857,-1); + packet(0x0858,-1); + packet(0x0859,-1); +#endif + +//2011-07-18aRagexe (Thanks to Yommy!) +#if PACKETVER >= 20110718 + packet(0x0844,2,clif->pCashShopOpen,2);/* tell server cashshop window is being open */ + packet(0x084a,2,clif->pCashShopClose,2);/* tell server cashshop window is being closed */ + packet(0x0846,4,clif->pCashShopReqTab,2); + packet(0x08c9,2,clif->pCashShopSchedule,0); + packet(0x0848,-1,clif->pCashShopBuy,2); +#endif + +//2011-10-05aRagexeRE +#if PACKETVER >= 20111005 + packet(0x0364,5,clif->pWalkToXY,2); + packet(0x0817,6,clif->pTickSend,2); + packet(0x0366,5,clif->pChangeDir,2,4); + packet(0x0815,6,clif->pTakeItem,2); + packet(0x0885,6,clif->pDropItem,2,4); + packet(0x0893,8,clif->pMoveToKafra,2,4); + packet(0x0897,8,clif->pMoveFromKafra,2,4); + packet(0x0369,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x08ad,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x088a,6,clif->pGetCharNameRequest,2); + packet(0x0838,6,clif->pSolveCharName,2); + packet(0x0439,8,clif->pUseItem,2,4); + packet(0x08d2,10); +#endif + +//2011-11-02aRagexe +#if PACKETVER >= 20111102 + packet(0x0436,26,clif->pFriendsListAdd,2); + packet(0x0898,5,clif->pHomMenu,4); + packet(0x0281,36,clif->pStoragePassword,0); + packet(0x088d,26,clif->pPartyInvite2,2); + packet(0x083c,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x08aa,7,clif->pActionRequest,2,6); + packet(0x02c4,10,clif->pUseSkillToId,2,4,6); + packet(0x0811,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x890,8); + packet(0x08a5,18,clif->pPartyBookingRegisterReq,2,4,6); + packet(0x0835,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x089b,2,clif->pReqCloseBuyingStore,0); + packet(0x08a1,6,clif->pReqClickBuyingStore,2); + packet(0x089e,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x08ab,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x088b,2,clif->pSearchStoreInfoNextPage,0); + packet(0x08a2,12,clif->pSearchStoreInfoListItemClick,2,6,10); + #ifndef PACKETVER_RE + packet(0x0835,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0892,5,clif->pWalkToXY,2); + packet(0x0899,6,clif->pTickSend,2); + #endif +#endif + +//2012-03-07fRagexeRE +#if PACKETVER >= 20120307 + packet(0x086A,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x0887,6,clif->pTickSend,2); + packet(0x0890,5,clif->pChangeDir,2,4); + packet(0x0865,6,clif->pTakeItem,2); + packet(0x02C4,6,clif->pDropItem,2,4); + packet(0x093B,8,clif->pMoveToKafra,2,4); + packet(0x0963,8,clif->pMoveFromKafra,2,4); + packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x0369,26,clif->pFriendsListAdd,2); + packet(0x0863,5,clif->pHomMenu,4); + packet(0x0861,36,clif->pStoragePassword,0); + packet(0x0929,26,clif->pPartyInvite2,2); + packet(0x0885,7,clif->pActionRequest,2,6); + packet(0x0889,10,clif->pUseSkillToId,2,4,6); + packet(0x0870,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0926,18,clif->pPartyBookingRegisterReq,2,4,6); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0817,2,clif->pReqCloseBuyingStore,0); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0884,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0439,8,clif->pUseItem,2,4); +#endif + +//2012-04-10aRagexeRE +#if PACKETVER >= 20120410 + packet(0x01FD,15,clif->pRepairItem,2); + packet(0x089C,26,clif->pFriendsListAdd,2); + packet(0x0885,5,clif->pHomMenu,2,4); + packet(0x0961,36,clif->pStoragePassword,0); + packet(0x0288,-1,clif->pcashshop_buy,4,8); + packet(0x091C,26,clif->pPartyInvite2,2); + packet(0x094B,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0369,7,clif->pActionRequest,2,6); + packet(0x083C,10,clif->pUseSkillToId,2,4,6); + packet(0x0439,8,clif->pUseItem,2,4); + packet(0x0945,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x0817,2,clif->pReqCloseBuyingStore,0); + packet(0x0360,6,clif->pReqClickBuyingStore,2); + packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0835,2,clif->pSearchStoreInfoNextPage,0); + packet(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x0437,5,clif->pWalkToXY,2); + packet(0x0886,6,clif->pTickSend,2); + packet(0x0871,5,clif->pChangeDir,2,4); + packet(0x0938,6,clif->pTakeItem,2); + packet(0x0891,6,clif->pDropItem,2,4); + packet(0x086C,8,clif->pMoveToKafra,2,4); + packet(0x08A6,8,clif->pMoveFromKafra,2,4); + packet(0x0438,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0366,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x0889,6,clif->pGetCharNameRequest,2); + packet(0x0884,6,clif->pSolveCharName,2); + packet(0x08E5,41,clif->pPartyBookingRegisterReq,2,4); + packet(0x08E6,4); + packet(0x08E7,10,clif->pPartyBookingSearchReq,2); + packet(0x08E8,-1); + packet(0x08E9,2,clif->pPartyBookingDeleteReq,2); + packet(0x08EA,4); + packet(0x08EB,39,clif->pPartyBookingUpdateReq,2); + packet(0x08EC,73); + packet(0x08ED,43); + packet(0x08EE,6); + packet(0x08EF,6,clif->pDull,2); //bookingignorereq + packet(0x08F0,6); + packet(0x08F1,6,clif->pDull,2); //bookingjoinpartyreq + packet(0x08F2,36); + packet(0x08F3,-1); + packet(0x08F4,6); + packet(0x08F5,-1,clif->pDull,2,4); //bookingsummonmember + packet(0x08F6,22); + packet(0x08F7,3); + packet(0x08F8,7); + packet(0x08F9,6); + packet(0x08FA,6); + packet(0x08FB,6,clif->pDull,2); //bookingcanceljoinparty + packet(0x0907,5,clif->pMoveItem,2,4); + packet(0x0908,5); + packet(0x08D7,28,clif->pDull,2,4); //battlegroundreg + packet(0x08CF,10);//Amulet spirits + packet(0x0977,14);//Monster HP Bar +#endif + +//2012-04-18aRagexeRE [Special Thanks to Judas!] +#if PACKETVER >= 20120418 + packet(0x023B,26,clif->pFriendsListAdd,2); + packet(0x0361,5,clif->pHomMenu,2,4); + packet(0x08A8,36,clif->pStoragePassword,0); + packet(0x0802,26,clif->pPartyInvite2,2); + packet(0x022D,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x035F,6,clif->pTickSend,2); + packet(0x0202,5,clif->pChangeDir,2,4); + packet(0x07E4,6,clif->pTakeItem,2); + packet(0x0362,6,clif->pDropItem,2,4); + packet(0x07EC,8,clif->pMoveToKafra,2,4); + packet(0x0364,8,clif->pMoveFromKafra,2,4); + packet(0x096A,6,clif->pGetCharNameRequest,2); + packet(0x0368,6,clif->pSolveCharName,2); + packet(0x08E5,41,clif->pPartyBookingRegisterReq,2,4); + packet(0x08d2,10); + packet(0x0916,26,clif->pGuildInvite2,2); +#endif + +//2012-06-18aRagexeRE +#if PACKETVER >= 20120618 + packet(0x0983,29); +#endif + +// ========== 2012-07-02aRagexeRE ============= +// - 2012-07-02 is NOT STABLE. +// - The packets are kept here for reference, DONT USE THEM. +#if PACKETVER >= 20120702 + packet(0x0363,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x0364,6,clif->pTickSend,2); + packet(0x085a,7,clif->pActionRequest,2,6); + packet(0x0861,8,clif->pMoveFromKafra,2,4); + packet(0x0862,10,clif->pUseSkillToId,2,4,6); + packet(0x0863,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x0886,6,clif->pSolveCharName,2); + packet(0x0889,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x089e,6,clif->pDropItem,2,4); + packet(0x089f,6,clif->pTakeItem,2); + packet(0x08a0,8,clif->pMoveToKafra,2,4); + packet(0x094a,6,clif->pGetCharNameRequest,2); + packet(0x0953,5,clif->pWalkToXY,2); + packet(0x0960,5,clif->pChangeDir,2,4); +#endif + +//2012-07-10 +#if PACKETVER >= 20120710 + packet(0x0886,2,clif->pReqCloseBuyingStore,0); +#endif + +//2012-07-16aRagExe (special thanks to Yommy!) +#if PACKETVER >= 20120716 + packet(0x0364,8,clif->pMoveFromKafra,2,4); +#endif + +//2013-03-20Ragexe (Judas + Yommy) +#if PACKETVER >= 20130320 + // Shuffle Start + packet(0x088E,7,clif->pActionRequest,2,6); + packet(0x089B,10,clif->pUseSkillToId,2,4,6); + packet(0x0881,5,clif->pWalkToXY,2); + packet(0x0363,6,clif->pTickSend,2); + packet(0x0897,5,clif->pChangeDir,2,4); + packet(0x0933,6,clif->pTakeItem,2); + packet(0x0438,6,clif->pDropItem,2,4); + packet(0x08AC,8,clif->pMoveToKafra,2,4); + packet(0x0874,8,clif->pMoveFromKafra,2,4); + packet(0x0959,10,clif->pUseSkillToPos,2,4,6,8); + packet(0x085A,90,clif->pUseSkillToPosMoreInfo,2,4,6,8,10); + packet(0x0898,6,clif->pGetCharNameRequest,2); + packet(0x094C,6,clif->pSolveCharName,2); + packet(0x0365,12,clif->pSearchStoreInfoListItemClick,2,6,10); + packet(0x092E,2,clif->pSearchStoreInfoNextPage,0); + packet(0x094E,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15); + packet(0x0922,-1,clif->pReqTradeBuyingStore,2,4,8,12); + packet(0x035F,6,clif->pReqClickBuyingStore,2); + packet(0x0886,2,clif->pReqCloseBuyingStore,0); + packet(0x0938,-1,clif->pReqOpenBuyingStore,2,4,8,9,89); + packet(0x085D,41,clif->pPartyBookingRegisterReq,2,4); + //packet(0x095A,8); // unknown usage + packet(0x0868,-1,clif->pItemListWindowSelected,2,4,8); + packet(0x0888,19,clif->pWantToConnection,2,6,10,14,18); + packet(0x086D,26,clif->pPartyInvite2,2); + //packet(0x0890,4); // unknown usage + packet(0x086F,26,clif->pFriendsListAdd,2); + packet(0x093F,5,clif->pHomMenu,2,4); + packet(0x0947,36,clif->pStoragePassword,0); + // Shuffle End + + // New Packets + packet(0x0998,8,clif->pEquipItem,2,4); + packet(0x0447,2); // PACKET_CZ_BLOCKING_PLAY_CANCEL + // New Packets End +#endif + +#endif /* _PACKETS_H_ */ diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h new file mode 100644 index 000000000..c873d3ad3 --- /dev/null +++ b/src/map/packets_struct.h @@ -0,0 +1,396 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file + +/* Hercules Renewal: Phase Two http://hercules.ws/board/topic/383-hercules-renewal-phase-two/ */ + +#ifndef _PACKETS_STRUCT_H_ +#define _PACKETS_STRUCT_H_ + +#include "../common/mmo.h" + +/** + * structs for data + */ +struct EQUIPSLOTINFO { + unsigned short card[4]; +}; +/** + * + **/ +enum packet_headers { + sc_notickType = 0x196, +#if PACKETVER < 20061218 + additemType = 0xa0, +#elif PACKETVER < 20071002 + additemType = 0x29a, +#elif PACKETVER < 20120925 + additemType = 0x2d4, +#else + additemType = 0x990, +#endif +#if PACKETVER < 4 + idle_unitType = 0x78, +#elif PACKETVER < 7 + idle_unitType = 0x1d8, +#elif PACKETVER < 20080102 + idle_unitType = 0x22a, +#elif PACKETVER < 20091103 + idle_unitType = 0x2ee, +#elif PACKETVER < 20101124 + idle_unitType = 0x7f9, +#elif PACKETVER < 20140000 //actual 20120221 + idle_unitType = 0x857, +#else + idle_unitType = 0x915, +#endif +#if PACKETVER >= 20120618 + status_changeType = 0x983, +#elif PACKETVER >= 20090121 + status_changeType = 0x43f, +#else + status_changeType = sc_notickType,/* 0x196 */ +#endif + status_change2Type = 0x43f, + status_change_endType = 0x196, +#if PACKETVER < 4 + spawn_unitType = 0x79, +#elif PACKETVER < 7 + spawn_unitType = 0x1d9, +#elif PACKETVER < 20080102 + spawn_unitType = 0x22b, +#elif PACKETVER < 20091103 + spawn_unitType = 0x2ed, +#elif PACKETVER < 20101124 + spawn_unitType = 0x7f8, +#elif PACKETVER < 20140000 //actual 20120221 + spawn_unitType = 0x858, +#else + spawn_unitType = 0x90f, +#endif +#if PACKETVER < 20080102 + authokType = 0x73, +#else + authokType = 0x2eb, +#endif +#if PACKETVER < 4 + unit_walkingType = 0x7b, +#elif PACKETVER < 7 + unit_walkingType = 0x1da, +#elif PACKETVER < 20080102 + unit_walkingType = 0x22c, +#elif PACKETVER < 20091103 + unit_walkingType = 0x2ec, +#elif PACKETVER < 20101124 + unit_walkingType = 0x7f7, +#elif PACKETVER < 20140000 //actual 20120221 + unit_walkingType = 0x856, +#else + unit_walkingType = 0x914, +#endif +#if PACKETVER > 20130000 /* not sure date */ + dropflooritemType = 0x84b, +#else + dropflooritemType = 0x9e, +#endif + monsterhpType = 0x977, + maptypeproperty2Type = 0x99b, +}; + +#pragma pack(push, 1) + +struct packet_authok { + short PacketType; + unsigned int startTime; + char PosDir[3]; + unsigned char xSize; + unsigned char ySize; +#if PACKETVER >= 20080102 + short font; +#endif +} __attribute__((packed)); + +struct packet_monster_hp { + short PacketType; + unsigned int GID; + int HP; + int MaxHP; +} __attribute__((packed)); + +struct packet_sc_notick { + short PacketType; + short index; + unsigned int AID; + unsigned char state; +} __attribute__((packed)); + +struct packet_additem { + short PacketType; + unsigned short Index; + unsigned short count; + unsigned short nameid; + bool IsIdentified; + bool IsDamaged; + unsigned char refiningLevel; + struct EQUIPSLOTINFO slot; +#if PACKETVER >= 20120925 + unsigned int location; +#else + unsigned short location; +#endif + unsigned char type; + unsigned char result; +#if PACKETVER >= 20061218 + int HireExpireDate; +#endif +#if PACKETVER >= 20071002 + unsigned short bindOnEquipType; +#endif +} __attribute__((packed)); + +struct packet_dropflooritem { + short PacketType; + unsigned int ITAID; + unsigned short ITID; +#if PACKETVER >= 20130000 /* not sure date */ + unsigned short type; +#endif + bool IsIdentified; + short xPos; + short yPos; + unsigned char subX; + unsigned char subY; + short count; +} __attribute__((packed)); + +struct packet_spawn_unit { + short PacketType; +#if PACKETVER >= 20091103 + short PacketLength; + unsigned char objecttype; +#endif + unsigned int GID; + short speed; + short bodyState; + short healthState; +#if PACKETVER < 20080102 + short effectState; +#else + int effectState; +#endif + short job; + short head; +#if PACKETVER < 7 + short weapon; +#else + int weapon; +#endif + short accessory; +#if PACKETVER < 7 + short shield; +#endif + short accessory2; + short accessory3; + short headpalette; + short bodypalette; + short headDir; +#if PACKETVER >= 20101124 + short robe; +#endif + unsigned int GUID; + short GEmblemVer; + short honor; +#if PACKETVER >= 20091103 + int virtue; +#else + short virtue; +#endif + bool isPKModeON; + unsigned char sex; + char PosDir[3]; + unsigned char xSize; + unsigned char ySize; + short clevel; +#if PACKETVER >= 20080102 + short font; +#endif +#if PACKETVER >= 20140000 //actual 20120221 + int maxHP; + int HP; + unsigned char isBoss; +#endif +} __attribute__((packed)); + +struct packet_unit_walking { + short PacketType; +#if PACKETVER >= 20091103 + short PacketLength; + unsigned char objecttype; +#endif + unsigned int GID; + short speed; + short bodyState; + short healthState; +#if PACKETVER < 20080102 + short effectState; +#else + int effectState; +#endif + short job; + short head; +#if PACKETVER < 7 + short weapon; +#else + int weapon; +#endif + short accessory; + unsigned int moveStartTime; +#if PACKETVER < 7 + short shield; +#endif + short accessory2; + short accessory3; + short headpalette; + short bodypalette; + short headDir; +#if PACKETVER >= 20101124 + short robe; +#endif + unsigned int GUID; + short GEmblemVer; + short honor; +#if PACKETVER >= 20091103 + int virtue; +#else + short virtue; +#endif + bool isPKModeON; + unsigned char sex; + char MoveData[6]; + unsigned char xSize; + unsigned char ySize; + short clevel; +#if PACKETVER >= 20080102 + short font; +#endif +#if PACKETVER >= 20140000 //actual 20120221 + int maxHP; + int HP; + unsigned char isBoss; +#endif +} __attribute__((packed)); + +struct packet_idle_unit { + short PacketType; +#if PACKETVER >= 20091103 + short PacketLength; + unsigned char objecttype; +#endif + unsigned int GID; + short speed; + short bodyState; + short healthState; +#if PACKETVER < 20080102 + short effectState; +#else + int effectState; +#endif + short job; + short head; +#if PACKETVER < 7 + short weapon; +#else + int weapon; +#endif + short accessory; +#if PACKETVER < 7 + short shield; +#endif + short accessory2; + short accessory3; + short headpalette; + short bodypalette; + short headDir; +#if PACKETVER >= 20101124 + short robe; +#endif + unsigned int GUID; + short GEmblemVer; + short honor; +#if PACKETVER >= 20091103 + int virtue; +#else + short virtue; +#endif + bool isPKModeON; + unsigned char sex; + char PosDir[3]; + unsigned char xSize; + unsigned char ySize; + unsigned char state; + short clevel; +#if PACKETVER >= 20080102 + short font; +#endif +#if PACKETVER >= 20140000 //actual 20120221 + int maxHP; + int HP; + unsigned char isBoss; +#endif +} __attribute__((packed)); + +struct packet_status_change { + short PacketType; + short index; + unsigned int AID; + unsigned char state; +#if PACKETVER >= 20120618 + unsigned int Total; +#endif +#if PACKETVER >= 20090121 + unsigned int Left; + int val1; + int val2; + int val3; +#endif +} __attribute__((packed)); + +struct packet_status_change_end { + short PacketType; + short index; + unsigned int AID; + unsigned char state; +} __attribute__((packed)); + +struct packet_status_change2 { + short PacketType; + short index; + unsigned int AID; + unsigned char state; + unsigned int Left; + int val1; + int val2; + int val3; +} __attribute__((packed)); + +struct packet_maptypeproperty2 { + short PacketType; + short type; + struct { + unsigned int party : 1; + unsigned int guild : 1; + unsigned int siege : 1; + unsigned int mineffect : 1; + unsigned int nolockon : 1; + unsigned int countpk : 1; + unsigned int nopartyformation : 1; + unsigned int bg : 1; + unsigned int noitemconsumption : 1; + unsigned int usecart : 1; + unsigned int summonstarmiracle : 1; + unsigned int SpareBits : 15; + } flag; +} __attribute__((packed)); + +#pragma pack(pop) + +#endif /* _PACKETS_STRUCT_H_ */ diff --git a/src/map/party.c b/src/map/party.c index f6b711791..d8bb321f1 100644 --- a/src/map/party.c +++ b/src/map/party.c @@ -159,7 +159,7 @@ int party_create(struct map_session_data *sd,char *name,int item,int item2) if( sd->status.party_id > 0 || sd->party_joining || sd->party_creating ) {// already associated with a party - clif_party_created(sd,2); + clif->party_created(sd,2); return 0; } @@ -188,10 +188,10 @@ void party_created(int account_id,int char_id,int fail,int party_id,char *name) if( !fail ) { sd->status.party_id = party_id; - clif_party_created(sd,0); //Success message + clif->party_created(sd,0); //Success message //We don't do any further work here because the char-server sends a party info packet right after creating the party. } else { - clif_party_created(sd,1); // "party name already exists" + clif->party_created(sd,1); // "party name already exists" } } @@ -204,11 +204,10 @@ int party_request_info(int party_id, int char_id) /// Invoked (from char-server) when the party info is not found. int party_recv_noinfo(int party_id, int char_id) { - struct map_session_data* sd; - party_broken(party_id); if( char_id != 0 )// requester { + struct map_session_data* sd; sd = map_charid2sd(char_id); if( sd && sd->status.party_id == party_id ) sd->status.party_id = 0; @@ -316,12 +315,12 @@ int party_recv_info(struct party* sp, int char_id) sd = p->data[member_id].sd; if( sd == NULL ) continue;// not online - clif_charnameupdate(sd); //Update other people's display. [Skotlex] - clif_party_member_info(p,sd); - clif_party_option(p,sd,0x100); - clif_party_info(p,NULL); + clif->charnameupdate(sd); //Update other people's display. [Skotlex] + clif->party_member_info(p,sd); + clif->party_option(p,sd,0x100); + clif->party_info(p,NULL); if( p->instance_id != 0 ) - clif_instance_join(sd->fd, p->instance_id); + clif->instance_join(sd->fd, p->instance_id); } if( char_id != 0 )// requester { @@ -346,7 +345,7 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd) ARR_FIND(0, MAX_PARTY, i, p->data[i].sd == sd); if( i == MAX_PARTY || !p->party.member[i].leader ) { - clif_displaymessage(sd->fd, msg_txt(282)); + clif->message(sd->fd, msg_txt(282)); return 0; } @@ -354,43 +353,43 @@ int party_invite(struct map_session_data *sd,struct map_session_data *tsd) ARR_FIND(0, MAX_PARTY, i, p->party.member[i].account_id == 0); if( i == MAX_PARTY ) { - clif_party_inviteack(sd, (tsd?tsd->status.name:""), 3); + clif->party_inviteack(sd, (tsd?tsd->status.name:""), 3); return 0; } // confirm whether the account has the ability to invite before checking the player if( !pc_has_permission(sd, PC_PERM_PARTY) || (tsd && !pc_has_permission(tsd, PC_PERM_PARTY)) ) { - clif_displaymessage(sd->fd, msg_txt(81)); // "Your GM level doesn't authorize you to preform this action on the specified player." + clif->message(sd->fd, msg_txt(81)); // "Your GM level doesn't authorize you to preform this action on the specified player." return 0; } if( tsd == NULL) { - clif_party_inviteack(sd, "", 7); + clif->party_inviteack(sd, "", 7); return 0; } if(!battle_config.invite_request_check) { if (tsd->guild_invite>0 || tsd->trade_partner || tsd->adopt_invite) { - clif_party_inviteack(sd,tsd->status.name,0); + clif->party_inviteack(sd,tsd->status.name,0); return 0; } } if (!tsd->fd) { //You can't invite someone who has already disconnected. - clif_party_inviteack(sd,tsd->status.name,1); + clif->party_inviteack(sd,tsd->status.name,1); return 0; } if( tsd->status.party_id > 0 || tsd->party_invite > 0 ) {// already associated with a party - clif_party_inviteack(sd,tsd->status.name,0); + clif->party_inviteack(sd,tsd->status.name,0); return 0; } tsd->party_invite=sd->status.party_id; tsd->party_invite_account=sd->status.account_id; - clif_party_invite(sd,tsd); + clif->party_invite(sd,tsd); return 1; } @@ -418,7 +417,7 @@ void party_reply_invite(struct map_session_data *sd,int party_id,int flag) sd->party_invite = 0; sd->party_invite_account = 0; if( tsd != NULL ) - clif_party_inviteack(tsd,sd->status.name,1); + clif->party_inviteack(tsd,sd->status.name,1); } } @@ -440,7 +439,7 @@ void party_member_joined(struct map_session_data *sd) { p->data[i].sd = sd; if( p->instance_id ) - clif_instance_join(sd->fd,p->instance_id); + clif->instance_join(sd->fd,p->instance_id); } else sd->status.party_id = 0; //He does not belongs to the party really? @@ -475,31 +474,31 @@ int party_member_added(int party_id,int account_id,int char_id, int flag) if( flag ) {// failed if( sd2 != NULL ) - clif_party_inviteack(sd2,sd->status.name,3); + clif->party_inviteack(sd2,sd->status.name,3); return 0; } sd->status.party_id = party_id; - clif_party_member_info(p,sd); - clif_party_option(p,sd,0x100); - clif_party_info(p,sd); + clif->party_member_info(p,sd); + clif->party_option(p,sd,0x100); + clif->party_info(p,sd); if( sd2 != NULL ) - clif_party_inviteack(sd2,sd->status.name,2); + clif->party_inviteack(sd2,sd->status.name,2); for( i = 0; i < ARRAYLENGTH(p->data); ++i ) {// hp of the other party members sd2 = p->data[i].sd; if( sd2 && sd2->status.account_id != account_id && sd2->status.char_id != char_id ) - clif_hpmeter_single(sd->fd, sd2->bl.id, sd2->battle_status.hp, sd2->battle_status.max_hp); + clif->hpmeter_single(sd->fd, sd2->bl.id, sd2->battle_status.hp, sd2->battle_status.max_hp); } - clif_party_hp(sd); - clif_party_xy(sd); - clif_charnameupdate(sd); //Update char name's display [Skotlex] + clif->party_hp(sd); + clif->party_xy(sd); + clif->charnameupdate(sd); //Update char name's display [Skotlex] if( p->instance_id ) - clif_instance_join(sd->fd, p->instance_id); + clif->instance_join(sd->fd, p->instance_id); return 0; } @@ -559,7 +558,7 @@ int party_member_withdraw(int party_id, int account_id, int char_id) ARR_FIND( 0, MAX_PARTY, i, p->party.member[i].account_id == account_id && p->party.member[i].char_id == char_id ); if( i < MAX_PARTY ) { - clif_party_withdraw(p,sd,account_id,p->party.member[i].name,0x0); + clif->party_withdraw(p,sd,account_id,p->party.member[i].name,0x0); memset(&p->party.member[i], 0, sizeof(p->party.member[0])); memset(&p->data[i], 0, sizeof(p->data[0])); p->party.count--; @@ -570,7 +569,7 @@ int party_member_withdraw(int party_id, int account_id, int char_id) if( sd && sd->status.party_id == party_id && sd->status.char_id == char_id ) { sd->status.party_id = 0; - clif_charnameupdate(sd); //Update name display [Skotlex] + clif->charnameupdate(sd); //Update name display [Skotlex] //TODO: hp bars should be cleared too if( p->instance_id ) instance_check_kick(sd); @@ -599,7 +598,7 @@ int party_broken(int party_id) { if( p->data[i].sd!=NULL ) { - clif_party_withdraw(p,p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,0x10); + clif->party_withdraw(p,p->data[i].sd,p->party.member[i].account_id,p->party.member[i].name,0x10); p->data[i].sd->status.party_id=0; } } @@ -632,7 +631,7 @@ int party_optionchanged(int party_id,int account_id,int exp,int item,int flag) p->party.item=item; } - clif_party_option(p,sd,flag); + clif->party_option(p,sd,flag); return 0; } @@ -645,13 +644,13 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts return false; if (!tsd || tsd->status.party_id != sd->status.party_id) { - clif_displaymessage(sd->fd, msg_txt(283)); + clif->message(sd->fd, msg_txt(283)); return false; } if( map[sd->bl.m].flag.partylock ) { - clif_displaymessage(sd->fd, msg_txt(287)); + clif->message(sd->fd, msg_txt(287)); return false; } @@ -664,7 +663,7 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts if (!p->party.member[mi].leader) { //Need to be a party leader. - clif_displaymessage(sd->fd, msg_txt(282)); + clif->message(sd->fd, msg_txt(282)); return false; } @@ -675,15 +674,15 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts //Change leadership. p->party.member[mi].leader = 0; if (p->data[mi].sd->fd) - clif_displaymessage(p->data[mi].sd->fd, msg_txt(284)); + clif->message(p->data[mi].sd->fd, msg_txt(284)); p->party.member[tmi].leader = 1; if (p->data[tmi].sd->fd) - clif_displaymessage(p->data[tmi].sd->fd, msg_txt(285)); + clif->message(p->data[tmi].sd->fd, msg_txt(285)); //Update info. intif_party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id); - clif_party_info(p,NULL); + clif->party_info(p,NULL); return true; } @@ -715,13 +714,12 @@ int party_recv_movemap(int party_id,int account_id,int char_id, unsigned short m //Check if they still exist on this map server p->data[i].sd = party_sd_check(party_id, account_id, char_id); - clif_party_info(p,NULL); + clif->party_info(p,NULL); return 0; } void party_send_movemap(struct map_session_data *sd) { - int i; struct party_data *p; if( sd->status.party_id==0 ) @@ -734,19 +732,20 @@ void party_send_movemap(struct map_session_data *sd) if(sd->state.connect_new) { //Note that this works because this function is invoked before connect_new is cleared. - clif_party_option(p,sd,0x100); - clif_party_info(p,sd); - clif_party_member_info(p,sd); + clif->party_option(p,sd,0x100); + clif->party_info(p,sd); + clif->party_member_info(p,sd); } if (sd->fd) { // synchronize minimap positions with the rest of the party + int i; for(i=0; i < MAX_PARTY; i++) { if (p->data[i].sd && p->data[i].sd != sd && p->data[i].sd->bl.m == sd->bl.m) { - clif_party_xy_single(sd->fd, p->data[i].sd); - clif_party_xy_single(p->data[i].sd->fd, sd); + clif->party_xy_single(sd->fd, p->data[i].sd); + clif->party_xy_single(p->data[i].sd->fd, sd); } } } @@ -787,7 +786,7 @@ int party_send_message(struct map_session_data *sd,const char *mes,int len) party_recv_message(sd->status.party_id,sd->status.account_id,mes,len); // Chat logging type 'P' / Party Chat - log_chat(LOG_CHAT_PARTY, sd->status.party_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); + logs->chat(LOG_CHAT_PARTY, sd->status.party_id, sd->status.char_id, sd->status.account_id, mapindex_id2name(sd->mapindex), sd->bl.x, sd->bl.y, NULL, mes); return 0; } @@ -797,7 +796,7 @@ int party_recv_message(int party_id,int account_id,const char *mes,int len) struct party_data *p; if( (p=party_search(party_id))==NULL) return 0; - clif_party_message(p,account_id,mes,len); + clif->party_message(p,account_id,mes,len); return 0; } @@ -835,7 +834,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id && pc_checkskill(p_sd,MO_TRIPLEATTACK)) { sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,MO_TRIPLEATTACK, 50+50*skill_lv, //+100/150/200% rate - 0,0,skill_get_time(SG_FRIEND, 1)); + 0,0,skill->get_time(SG_FRIEND, 1)); } break; case MO_COMBOFINISH: //Increase Counter rate of Star Gladiators @@ -844,7 +843,7 @@ int party_skill_check(struct map_session_data *sd, int party_id, uint16 skill_id && pc_checkskill(p_sd,SG_FRIEND)) { sc_start4(&p_sd->bl,SC_SKILLRATE_UP,100,TK_COUNTER, 50+50*pc_checkskill(p_sd,SG_FRIEND), //+100/150/200% rate - 0,0,skill_get_time(SG_FRIEND, 1)); + 0,0,skill->get_time(SG_FRIEND, 1)); } break; } @@ -875,13 +874,13 @@ int party_send_xy_timer(int tid, unsigned int tick, int id, intptr_t data) if( p->data[i].x != sd->bl.x || p->data[i].y != sd->bl.y ) {// perform position update - clif_party_xy(sd); + clif->party_xy(sd); p->data[i].x = sd->bl.x; p->data[i].y = sd->bl.y; } if (battle_config.party_hp_mode && p->data[i].hp != sd->battle_status.hp) {// perform hp update - clif_party_hp(sd); + clif->party_hp(sd); p->data[i].hp = sd->battle_status.hp; } } @@ -911,6 +910,9 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b { struct map_session_data* sd[MAX_PARTY]; unsigned int i, c; +#ifdef RENEWAL_EXP + unsigned int job_exp_bonus, base_exp_bonus; +#endif nullpo_ret(p); @@ -927,8 +929,7 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b job_exp/=c; zeny/=c; - if (battle_config.party_even_share_bonus && c > 1) - { + if (battle_config.party_even_share_bonus && c > 1) { double bonus = 100 + battle_config.party_even_share_bonus*(c-1); if (base_exp) base_exp = (unsigned int) cap_value(base_exp * bonus/100, 0, UINT_MAX); @@ -938,12 +939,17 @@ int party_exp_share(struct party_data* p, struct block_list* src, unsigned int b zeny = (unsigned int) cap_value(zeny * bonus/100, INT_MIN, INT_MAX); } +#ifdef RENEWAL_EXP + base_exp_bonus = base_exp; + job_exp_bonus = job_exp; +#endif + for (i = 0; i < c; i++) { #ifdef RENEWAL_EXP if( !(src && src->type == BL_MOB && ((TBL_MOB*)src)->db->mexp) ){ int rate = pc_level_penalty_mod(sd[i], (TBL_MOB*)src, 1); - base_exp = (unsigned int)cap_value(base_exp * rate / 100, 1, UINT_MAX); - job_exp = (unsigned int)cap_value(job_exp * rate / 100, 1, UINT_MAX); + base_exp = (unsigned int)cap_value(base_exp_bonus * rate / 100, 1, UINT_MAX); + job_exp = (unsigned int)cap_value(job_exp_bonus * rate / 100, 1, UINT_MAX); } #endif pc_gainexp(sd[i], src, base_exp, job_exp, false); @@ -1015,7 +1021,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i } if( p && battle_config.party_show_share_picker && battle_config.show_picker_item_type&(1<<itemdb_type(item_data->nameid)) ) - clif_party_show_picker(target, item_data); + clif->party_show_picker(target, item_data); return 0; } @@ -1023,7 +1029,7 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i int party_send_dot_remove(struct map_session_data *sd) { if (sd->status.party_id) - clif_party_xy_remove(sd); + clif->party_xy_remove(sd); return 0; } @@ -1117,7 +1123,7 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi } else {// already registered - clif_PartyBookingRegisterAck(sd, 2); + clif->PartyBookingRegisterAck(sd, 2); return; } @@ -1131,8 +1137,8 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi pb_ad->p_detail.job[i] = job[i]; else pb_ad->p_detail.job[i] = -1; - clif_PartyBookingRegisterAck(sd, 0); - clif_PartyBookingInsertNotify(sd, pb_ad); // Notice + clif->PartyBookingRegisterAck(sd, 0); + clif->PartyBookingInsertNotify(sd, pb_ad); // Notice } void party_booking_update(struct map_session_data *sd, short* job) @@ -1152,7 +1158,7 @@ void party_booking_update(struct map_session_data *sd, short* job) pb_ad->p_detail.job[i] = job[i]; else pb_ad->p_detail.job[i] = -1; - clif_PartyBookingUpdateNotify(sd, pb_ad); + clif->PartyBookingUpdateNotify(sd, pb_ad); } void party_booking_search(struct map_session_data *sd, short level, short mapid, short job, unsigned long lastindex, short resultcount) @@ -1189,7 +1195,7 @@ void party_booking_search(struct map_session_data *sd, short level, short mapid, } } dbi_destroy(iter); - clif_PartyBookingSearchAck(sd->fd, result_list, count, more_result); + clif->PartyBookingSearchAck(sd->fd, result_list, count, more_result); } bool party_booking_delete(struct map_session_data *sd) @@ -1198,7 +1204,7 @@ bool party_booking_delete(struct map_session_data *sd) if((pb_ad = (struct party_booking_ad_info*)idb_get(party_booking_db, sd->status.char_id))!=NULL) { - clif_PartyBookingDeleteNotify(sd, pb_ad->index); + clif->PartyBookingDeleteNotify(sd, pb_ad->index); idb_remove(party_booking_db,sd->status.char_id); } return true; diff --git a/src/map/pc.c b/src/map/pc.c index f06d48779..9b1545c51 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/core.h" // get_svn_revision() @@ -33,7 +34,7 @@ #include "npc.h" // fake_nd #include "pet.h" // pet_unlocktarget() #include "party.h" // party_search() -#include "guild.h" // guild_search(), guild_request_info() +#include "guild.h" // guild->search(), guild_request_info() #include "script.h" // script_config #include "skill.h" #include "status.h" // struct status_data @@ -65,7 +66,7 @@ struct fame_list smith_fame_list[MAX_FAME_LIST]; struct fame_list chemist_fame_list[MAX_FAME_LIST]; struct fame_list taekwon_fame_list[MAX_FAME_LIST]; -static unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_AMMO}; +static unsigned short equip_pos[EQI_MAX]={EQP_ACC_L,EQP_ACC_R,EQP_SHOES,EQP_GARMENT,EQP_HEAD_LOW,EQP_HEAD_MID,EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_GARMENT,EQP_AMMO}; #define MOTD_LINE_SIZE 128 static char motd_text[MOTD_LINE_SIZE][CHAT_SIZE_MAX]; // Message of the day buffer [Valaris] @@ -98,10 +99,6 @@ int pc_class2idx(int class_) { return class_; } -inline int pc_get_group_id(struct map_session_data *sd) { - return sd->group_id; -} - inline int pc_get_group_level(struct map_session_data *sd) { return sd->group_level; } @@ -118,15 +115,16 @@ static int pc_invincible_timer(int tid, unsigned int tick, int id, intptr_t data return 0; } sd->invincible_timer = INVALID_TIMER; - skill_unit_move(&sd->bl,tick,1); + skill->unit_move(&sd->bl,tick,1); return 0; } -void pc_setinvincibletimer(struct map_session_data* sd, int val) -{ +void pc_setinvincibletimer(struct map_session_data* sd, int val) { nullpo_retv(sd); + val += map[sd->bl.m].invincible_time_inc; + if( sd->invincible_timer != INVALID_TIMER ) delete_timer(sd->invincible_timer,pc_invincible_timer); sd->invincible_timer = add_timer(gettick()+val,pc_invincible_timer,sd->bl.id,0); @@ -140,7 +138,7 @@ void pc_delinvincibletimer(struct map_session_data* sd) { delete_timer(sd->invincible_timer,pc_invincible_timer); sd->invincible_timer = INVALID_TIMER; - skill_unit_move(&sd->bl,gettick(),1); + skill->unit_move(&sd->bl,gettick(),1); } } @@ -171,7 +169,7 @@ static int pc_spiritball_timer(int tid, unsigned int tick, int id, intptr_t data memmove(sd->spirit_timer+i, sd->spirit_timer+i+1, (sd->spiritball-i)*sizeof(int)); sd->spirit_timer[sd->spiritball] = INVALID_TIMER; - clif_spiritball(&sd->bl); + clif->spiritball(&sd->bl); return 0; } @@ -182,13 +180,12 @@ int pc_addspiritball(struct map_session_data *sd,int interval,int max) nullpo_ret(sd); - if(max > MAX_SKILL_LEVEL) - max = MAX_SKILL_LEVEL; + if(max > MAX_SPIRITBALL) + max = MAX_SPIRITBALL; if(sd->spiritball < 0) sd->spiritball = 0; - if( sd->spiritball && sd->spiritball >= max ) - { + if( sd->spiritball && sd->spiritball >= max ) { if(sd->spirit_timer[0] != INVALID_TIMER) delete_timer(sd->spirit_timer[0],pc_spiritball_timer); sd->spiritball--; @@ -204,9 +201,9 @@ 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,sd->spiritball); else - clif_spiritball(&sd->bl); + clif->spiritball(&sd->bl); return 0; } @@ -227,8 +224,8 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type) if(count > sd->spiritball) count = sd->spiritball; sd->spiritball -= count; - if(count > MAX_SKILL_LEVEL) - count = MAX_SKILL_LEVEL; + if(count > MAX_SPIRITBALL) + count = MAX_SPIRITBALL; for(i=0;i<count;i++) { if(sd->spirit_timer[i] != INVALID_TIMER) { @@ -236,16 +233,16 @@ int pc_delspiritball(struct map_session_data *sd,int count,int type) sd->spirit_timer[i] = INVALID_TIMER; } } - for(i=count;i<MAX_SKILL_LEVEL;i++) { + for(i=count;i<MAX_SPIRITBALL;i++) { sd->spirit_timer[i-count] = sd->spirit_timer[i]; sd->spirit_timer[i] = INVALID_TIMER; } if(!type) { if( (sd->class_&MAPID_THIRDMASK) == MAPID_ROYAL_GUARD ) - clif_millenniumshield(sd,sd->spiritball); + clif->millenniumshield(sd,sd->spiritball); else - clif_spiritball(&sd->bl); + clif->spiritball(&sd->bl); } return 0; } @@ -283,7 +280,7 @@ int pc_banding(struct map_session_data *sd, uint16 skill_lv) { int i, j, hp, extra_hp = 0, tmp_qty = 0, tmp_hp; struct map_session_data *bsd; struct status_change *sc; - int range = skill_get_splash(LG_BANDING,skill_lv); + int range = skill->get_splash(LG_BANDING,skill_lv); nullpo_ret(sd); @@ -356,13 +353,13 @@ void pc_addfame(struct map_session_data *sd,int count) sd->status.fame = MAX_FAME; switch(sd->class_&MAPID_UPPERMASK){ case MAPID_BLACKSMITH: // Blacksmith - clif_fame_blacksmith(sd,count); + clif->fame_blacksmith(sd,count); break; case MAPID_ALCHEMIST: // Alchemist - clif_fame_alchemist(sd,count); + clif->fame_alchemist(sd,count); break; case MAPID_TAEKWON: // Taekwon - clif_fame_taekwon(sd,count); + clif->fame_taekwon(sd,count); break; } chrif_updatefamelist(sd); @@ -459,14 +456,14 @@ void pc_inventory_rentals(struct map_session_data *sd) if( sd->status.inventory[i].expire_time <= time(NULL) ) { if( sd->status.inventory[i].nameid == ITEMID_REINS_OF_MOUNT - && sd->sc.option&OPTION_MOUNTING ) { - pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING); + && sd->sc.data[SC_ALL_RIDING] ) { + status_change_end(&sd->bl,SC_ALL_RIDING,INVALID_TIMER); } - clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); + clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); } else { expire_tick = (unsigned int)(sd->status.inventory[i].expire_time - time(NULL)) * 1000; - clif_rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000)); + clif->rental_time(sd->fd, sd->status.inventory[i].nameid, (int)(expire_tick / 1000)); next_tick = min(expire_tick, next_tick); c++; } @@ -480,7 +477,6 @@ void pc_inventory_rentals(struct map_session_data *sd) void pc_inventory_rental_add(struct map_session_data *sd, int seconds) { - const struct TimerData * td; int tick = seconds * 1000; if( sd == NULL ) @@ -488,6 +484,7 @@ void pc_inventory_rental_add(struct map_session_data *sd, int seconds) if( sd->rental_timer != INVALID_TIMER ) { + const struct TimerData * td; td = get_timer(sd->rental_timer); if( DIFF_TICK(td->tick, gettick()) > tick ) { // Update Timer as this one ends first than the current one @@ -520,9 +517,9 @@ int pc_makesavestatus(struct map_session_data *sd) //Only copy the Cart/Peco/Falcon options, the rest are handled via //status change load/saving. [Skotlex] #ifdef NEW_CARTS - sd->status.option = sd->sc.option&(OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING); + sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR); #else - sd->status.option = sd->sc.option&(OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR|OPTION_MOUNTING); + sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_CART|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR); #endif if (sd->sc.data[SC_JAILED]) { //When Jailed, do not move last point. @@ -700,24 +697,24 @@ int pc_setequipindex(struct map_session_data *sd) return 0; } +//static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) +//{ +// int i; +// struct item *item = &sd->status.inventory[eqindex]; +// struct item_data *data; +// +// //Crafted/made/hatched items. +// if (itemdb_isspecial(item->card[0])) +// return 1; +// +// /* scan for enchant armor gems */ +// if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 ) +// s = MAX_SLOTS - 1; +// +// ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag ); +// return( i < s ) ? 0 : 1; +//} -static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag) -{ - int i; - struct item *item = &sd->status.inventory[eqindex]; - struct item_data *data; - - //Crafted/made/hatched items. - if (itemdb_isspecial(item->card[0])) - return 1; - - /* scan for enchant armor gems */ - if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 ) - s = MAX_SLOTS - 1; - - ARR_FIND( 0, s, i, item->card[i] && (data = itemdb_exists(item->card[i])) != NULL && data->flag.no_equip&flag ); - return( i < s ) ? 0 : 1; -} bool pc_isequipped(struct map_session_data *sd, int nameid) { @@ -771,18 +768,18 @@ bool pc_can_Adopt(struct map_session_data *p1_sd, struct map_session_data *p2_sd // Already adopted a baby if( p1_sd->status.child || p2_sd->status.child ) { - clif_Adopt_reply(p1_sd, 0); + clif->adopt_reply(p1_sd, 0); return false; } // Parents need at least lvl 70 to adopt if( p1_sd->status.base_level < 70 || p2_sd->status.base_level < 70 ) { - clif_Adopt_reply(p1_sd, 1); + clif->adopt_reply(p1_sd, 1); return false; } if( b_sd->status.partner_id ) { - clif_Adopt_reply(p1_sd, 2); + clif->adopt_reply(p1_sd, 2); return false; } @@ -817,9 +814,9 @@ bool pc_adoption(struct map_session_data *p1_sd, struct map_session_data *p2_sd, // Restore progress b_sd->status.job_level = joblevel; - clif_updatestatus(b_sd, SP_JOBLEVEL); + clif->updatestatus(b_sd, SP_JOBLEVEL); b_sd->status.job_exp = jobexp; - clif_updatestatus(b_sd, SP_JOBEXP); + clif->updatestatus(b_sd, SP_JOBEXP); // Baby Skills pc_skill(b_sd, WE_BABY, 1, 0); @@ -860,20 +857,6 @@ int pc_isequip(struct map_session_data *sd,int n) #endif if(item->sex != 2 && sd->status.sex != item->sex) return 0; - if(!map_flag_vs(sd->bl.m) && ((item->flag.no_equip&1) || !pc_isAllowedCardOn(sd,item->slot,n,1))) - return 0; - if(map[sd->bl.m].flag.pvp && ((item->flag.no_equip&2) || !pc_isAllowedCardOn(sd,item->slot,n,2))) - return 0; - if(map_flag_gvg(sd->bl.m) && ((item->flag.no_equip&4) || !pc_isAllowedCardOn(sd,item->slot,n,4))) - return 0; - if(map[sd->bl.m].flag.battleground && ((item->flag.no_equip&8) || !pc_isAllowedCardOn(sd,item->slot,n,8))) - return 0; - if(map[sd->bl.m].flag.restricted) - { - int flag =8*map[sd->bl.m].zone; - if (item->flag.no_equip&flag || !pc_isAllowedCardOn(sd,item->slot,n,flag)) - return 0; - } if (sd->sc.count) { @@ -940,7 +923,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim memcpy(&sd->status, st, sizeof(*st)); if (st->sex != sd->status.sex) { - clif_authfail_fd(sd->fd, 0); + clif->authfail_fd(sd->fd, 0); return false; } @@ -956,19 +939,16 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim // Checks and fixes to character status data, that are required // in case of configuration change or stuff, which cannot be // checked on char-server. - if( sd->status.hair < MIN_HAIR_STYLE || sd->status.hair > MAX_HAIR_STYLE ) - { + if( sd->status.hair < MIN_HAIR_STYLE || sd->status.hair > MAX_HAIR_STYLE ) { sd->status.hair = MIN_HAIR_STYLE; } - if( sd->status.hair_color < MIN_HAIR_COLOR || sd->status.hair_color > MAX_HAIR_COLOR ) - { + if( sd->status.hair_color < MIN_HAIR_COLOR || sd->status.hair_color > MAX_HAIR_COLOR ) { sd->status.hair_color = MIN_HAIR_COLOR; } - if( sd->status.clothes_color < MIN_CLOTH_COLOR || sd->status.clothes_color > MAX_CLOTH_COLOR ) - { + if( sd->status.clothes_color < MIN_CLOTH_COLOR || sd->status.clothes_color > MAX_CLOTH_COLOR ) { sd->status.clothes_color = MIN_CLOTH_COLOR; } - + //Initializations to null/0 unneeded since map_session_data was filled with 0 upon allocation. if(!sd->status.hp) pc_setdead(sd); sd->state.connect_new = 1; @@ -977,15 +957,17 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->invincible_timer = INVALID_TIMER; sd->npc_timer_id = INVALID_TIMER; sd->pvp_timer = INVALID_TIMER; + sd->fontcolor_tid = INVALID_TIMER; /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT /** * Initialize to defaults/expected **/ sd->npc_idle_timer = INVALID_TIMER; sd->npc_idle_tick = tick; + sd->npc_idle_type = NPCT_INPUT; #endif sd->canuseitem_tick = tick; @@ -994,8 +976,9 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->cantalk_tick = tick; sd->canskill_tick = tick; sd->cansendmail_tick = tick; + sd->hchsysch_tick = tick; - for(i = 0; i < MAX_SKILL_LEVEL; i++) + for(i = 0; i < MAX_SPIRITBALL; i++) sd->spirit_timer[i] = INVALID_TIMER; for(i = 0; i < ARRAYLENGTH(sd->autobonus); i++) sd->autobonus[i].active = INVALID_TIMER; @@ -1018,14 +1001,13 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim pc_setinventorydata(sd); pc_setequipindex(sd); + if( sd->status.option & OPTION_INVISIBLE && !pc_can_use_command(sd, "@hide") ) + sd->status.option &=~ OPTION_INVISIBLE; + status_change_init(&sd->bl); - - if (pc_can_use_command(sd, "hide", COMMAND_ATCOMMAND)) - sd->status.option &= (OPTION_MASK | OPTION_INVISIBLE); - else - sd->status.option &= OPTION_MASK; - + sd->sc.option = sd->status.option; //This is the actual option used in battle. + //Set here because we need the inventory data for weapon sprite parsing. status_set_viewdata(&sd->bl, sd->status.class_); unit_dataset(&sd->bl); @@ -1033,6 +1015,8 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim sd->guild_x = -1; sd->guild_y = -1; + sd->disguise = -1; + // Event Timers for( i = 0; i < MAX_EVENTTIMER; i++ ) sd->eventtimer[i] = INVALID_TIMER; @@ -1049,12 +1033,12 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim // try warping to a default map instead (church graveyard) if (pc_setpos(sd, mapindex_name2id(MAP_PRONTERA), 273, 354, CLR_OUTSIGHT) != 0) { // if we fail again - clif_authfail_fd(sd->fd, 0); + clif->authfail_fd(sd->fd, 0); return false; } } - clif_authok(sd); + clif->authok(sd); //Prevent S. Novices from getting the no-death bonus just yet. [Skotlex] sd->die_counter=-1; @@ -1062,52 +1046,63 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim //display login notice ShowInfo("'"CL_WHITE"%s"CL_RESET"' logged in." " (AID/CID: '"CL_WHITE"%d/%d"CL_RESET"'," - " Packet Ver: '"CL_WHITE"%d"CL_RESET"', IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," + " IP: '"CL_WHITE"%d.%d.%d.%d"CL_RESET"'," " Group '"CL_WHITE"%d"CL_RESET"').\n", sd->status.name, sd->status.account_id, sd->status.char_id, - sd->packet_ver, CONVIP(ip), sd->group_id); + CONVIP(ip), sd->group_id); // Send friends list - clif_friendslist_send(sd); + clif->friendslist_send(sd); if( !changing_mapservers ) { - if (battle_config.display_version == 1){ + if (battle_config.display_version == 1) { + const char* svn = get_svn_revision(); + const char* git = get_git_hash(); char buf[256]; - sprintf(buf, "SVN version: %s", get_svn_revision()); - clif_displaymessage(sd->fd, buf); + if( git[0] != HERC_UNKNOWN_VER ) + sprintf(buf,"Git Hash: %s", git); + else if( svn[0] != HERC_UNKNOWN_VER ) + sprintf(buf,"SVN Revision: %s", svn); + else + sprintf(buf,"Unknown Version"); + clif->message(sd->fd, buf); } // Message of the Day [Valaris] for(i=0; motd_text[i][0] && i < MOTD_LINE_SIZE; i++) { if (battle_config.motd_type) - clif_disp_onlyself(sd,motd_text[i],strlen(motd_text[i])); + clif->disp_onlyself(sd,motd_text[i],strlen(motd_text[i])); else - clif_displaymessage(sd->fd, motd_text[i]); + clif->message(sd->fd, motd_text[i]); } // message of the limited time of the account if (expiration_time != 0) { // don't display if it's unlimited or unknow value char tmpstr[1024]; strftime(tmpstr, sizeof(tmpstr) - 1, msg_txt(501), localtime(&expiration_time)); // "Your account time limit is: %d-%m-%Y %H:%M:%S." - clif_wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1); + clif->wis_message(sd->fd, wisp_server_name, tmpstr, strlen(tmpstr)+1); } /** * Fixes login-without-aura glitch (the screen won't blink at this point, don't worry :P) **/ - clif_changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); + clif->changemap(sd,sd->mapindex,sd->bl.x,sd->bl.y); } /** * Check if player have any cool downs on **/ - skill_cooldown_load(sd); + skill->cooldown_load(sd); /** * Check if player have any item cooldowns on **/ pc_itemcd_do(sd,true); - + + /* [Ind/Hercules] */ + sd->sc_display = NULL; + sd->sc_display_count = 0; + // Request all registries (auth is considered completed whence they arrive) intif_request_registry(sd,7); return true; @@ -1118,7 +1113,7 @@ bool pc_authok(struct map_session_data *sd, int login_id2, time_t expiration_tim *------------------------------------------*/ void pc_authfail(struct map_session_data *sd) { - clif_authfail_fd(sd->fd, 0); + clif->authfail_fd(sd->fd, 0); return; } @@ -1130,7 +1125,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl) return 0; if (sd->hate_mob[pos] != -1) { //Can't change hate targets. - clif_hate_info(sd, pos, sd->hate_mob[pos], 0); //Display current + clif->hate_info(sd, pos, sd->hate_mob[pos], 0); //Display current return 0; } @@ -1144,7 +1139,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl) } sd->hate_mob[pos] = class_; pc_setglobalreg(sd,sg_info[pos].hate_var,class_+1); - clif_hate_info(sd, pos, class_, 1); + clif->hate_info(sd, pos, class_, 1); return 1; } @@ -1153,7 +1148,7 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl) *------------------------------------------*/ int pc_reg_received(struct map_session_data *sd) { - int i,j; + int i,j, idx = 0; sd->change_level_2nd = pc_readglobalreg(sd,"jobchange_level"); sd->change_level_3rd = pc_readglobalreg(sd,"jobchange_level_3rd"); @@ -1166,15 +1161,14 @@ int pc_reg_received(struct map_session_data *sd) // Cooking Exp sd->cook_mastery = pc_readglobalreg(sd,"COOK_MASTERY"); - if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) - { // Better check for class rather than skill to prevent "skill resets" from unsetting this + if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) { + // Better check for class rather than skill to prevent "skill resets" from unsetting this sd->mission_mobid = pc_readglobalreg(sd,"TK_MISSION_ID"); sd->mission_count = pc_readglobalreg(sd,"TK_MISSION_COUNT"); } //SG map and mob read [Komurka] - for(i=0;i<MAX_PC_FEELHATE;i++) //for now - someone need to make reading from txt/sql - { + for(i=0;i<MAX_PC_FEELHATE;i++) { //for now - someone need to make reading from txt/sql if ((j = pc_readglobalreg(sd,sg_info[i].feel_var))!=0) { sd->feel_map[i].index = j; sd->feel_map[i].m = map_mapindex2mapid(j); @@ -1187,22 +1181,22 @@ int pc_reg_received(struct map_session_data *sd) if ((i = pc_checkskill(sd,RG_PLAGIARISM)) > 0) { sd->cloneskill_id = pc_readglobalreg(sd,"CLONE_SKILL"); - if (sd->cloneskill_id > 0) { - sd->status.skill[sd->cloneskill_id].id = sd->cloneskill_id; - sd->status.skill[sd->cloneskill_id].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV"); - if (sd->status.skill[sd->cloneskill_id].lv > i) - sd->status.skill[sd->cloneskill_id].lv = i; - sd->status.skill[sd->cloneskill_id].flag = SKILL_FLAG_PLAGIARIZED; + if (sd->cloneskill_id > 0 && (idx = skill->get_index(sd->cloneskill_id))) { + sd->status.skill[idx].id = sd->cloneskill_id; + sd->status.skill[idx].lv = pc_readglobalreg(sd,"CLONE_SKILL_LV"); + if (sd->status.skill[idx].lv > i) + sd->status.skill[idx].lv = i; + sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED; } } if ((i = pc_checkskill(sd,SC_REPRODUCE)) > 0) { sd->reproduceskill_id = pc_readglobalreg(sd,"REPRODUCE_SKILL"); - if( sd->reproduceskill_id > 0) { - sd->status.skill[sd->reproduceskill_id].id = sd->reproduceskill_id; - sd->status.skill[sd->reproduceskill_id].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV"); - if( i < sd->status.skill[sd->reproduceskill_id].lv) - sd->status.skill[sd->reproduceskill_id].lv = i; - sd->status.skill[sd->reproduceskill_id].flag = SKILL_FLAG_PLAGIARIZED; + if( sd->reproduceskill_id > 0 && (idx = skill->get_index(sd->reproduceskill_id))) { + sd->status.skill[idx].id = sd->reproduceskill_id; + sd->status.skill[idx].lv = pc_readglobalreg(sd,"REPRODUCE_SKILL_LV"); + if( i < sd->status.skill[idx].lv) + sd->status.skill[idx].lv = i; + sd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED; } } //Weird... maybe registries were reloaded? @@ -1213,7 +1207,7 @@ int pc_reg_received(struct map_session_data *sd) if (sd->status.party_id) party_member_joined(sd); if (sd->status.guild_id) - guild_member_joined(sd); + guild->member_joined(sd); // pet if (sd->status.pet_id > 0) @@ -1240,33 +1234,45 @@ int pc_reg_received(struct map_session_data *sd) intif_Mail_requestinbox(sd->status.char_id, 0); // MAIL SYSTEM - Request Mail Inbox intif_request_questlog(sd); - if (sd->state.connect_new == 0 && sd->fd) - { //Character already loaded map! Gotta trigger LoadEndAck manually. + if (sd->state.connect_new == 0 && sd->fd) { //Character already loaded map! Gotta trigger LoadEndAck manually. sd->state.connect_new = 1; - clif_parse_LoadEndAck(sd->fd, sd); + clif->pLoadEndAck(sd->fd, sd); } pc_inventory_rentals(sd); + if( sd->sc.option & OPTION_INVISIBLE ) { + sd->vd.class_ = INVISIBLE_CLASS; + clif->message(sd->fd, msg_txt(11)); // Invisible: On + // decrement the number of pvp players on the map + map[sd->bl.m].users_pvp--; + + if( map[sd->bl.m].flag.pvp && !map[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {// unregister the player for ranking + delete_timer( sd->pvp_timer, pc_calc_pvprank_timer ); + sd->pvp_timer = INVALID_TIMER; + } + clif->changeoption(&sd->bl); + } + + return 1; } static int pc_calc_skillpoint(struct map_session_data* sd) { - int i,skill,inf2,skill_point=0; + int i,skill_lv,inf2,skill_point=0; nullpo_ret(sd); for(i=1;i<MAX_SKILL;i++){ - if( (skill = pc_checkskill(sd,i)) > 0) { - inf2 = skill_get_inf2(i); + if( (skill_lv = pc_checkskill2(sd,i)) > 0) { + inf2 = skill_db[i].inf2; if((!(inf2&INF2_QUEST_SKILL) || battle_config.quest_skill_learn) && !(inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) //Do not count wedding/link skills. [Skotlex] ) { if(sd->status.skill[i].flag == SKILL_FLAG_PERMANENT) - skill_point += skill; - else - if(sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0) + skill_point += skill_lv; + else if(sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0) skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); } } @@ -1293,36 +1299,44 @@ int pc_calc_skilltree(struct map_session_data *sd) return 1; } c = pc_class2idx(c); - - for( i = 0; i < MAX_SKILL; i++ ) - { - if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) //Don't touch plagiarized skills + + for( i = 0; i < MAX_SKILL; i++ ) { + if( sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED ) //Don't touch these sd->status.skill[i].id = 0; //First clear skills. + /* permanent skills that must be re-checked */ + if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) { + switch( skill_db[i].nameid ) { + case NV_TRICKDEAD: + if( (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) { + sd->status.skill[i].id = 0; + sd->status.skill[i].lv = 0; + sd->status.skill[i].flag = 0; + } + break; + } + } } - for( i = 0; i < MAX_SKILL; i++ ) - { - if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) + for( i = 0; i < MAX_SKILL; i++ ) { + if( sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED ) { // Restore original level of skills after deleting earned skills. sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; } - if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && i >= DC_HUMMING && i<= DC_SERVICEFORYOU ) + if( sd->sc.count && sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_BARDDANCER && skill_db[i].nameid >= DC_HUMMING && skill_db[i].nameid <= DC_SERVICEFORYOU ) { //Enable Bard/Dancer spirit linked skills. if( sd->status.sex ) { //Link dancer skills to bard. if( sd->status.skill[i-8].lv < 10 ) continue; - sd->status.skill[i].id = i; + sd->status.skill[i].id = skill_db[i].nameid; sd->status.skill[i].lv = sd->status.skill[i-8].lv; // Set the level to the same as the linking skill sd->status.skill[i].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill - } - else - { //Link bard skills to dancer. + } else { //Link bard skills to dancer. if( sd->status.skill[i].lv < 10 ) continue; - sd->status.skill[i-8].id = i - 8; + sd->status.skill[i-8].id = skill_db[i-8].nameid; sd->status.skill[i-8].lv = sd->status.skill[i].lv; // Set the level to the same as the linking skill sd->status.skill[i-8].flag = SKILL_FLAG_TEMPORARY; // Tag it as a non-savable, non-uppable, bonus skill } @@ -1331,7 +1345,7 @@ int pc_calc_skilltree(struct map_session_data *sd) if( pc_has_permission(sd, PC_PERM_ALL_SKILL) ) { for( i = 0; i < MAX_SKILL; i++ ) { - switch(i) { + switch(skill_db[i].nameid) { /** * Dummy skills must be added here otherwise they'll be displayed in the, * skill tree and since they have no icons they'll give resource errors @@ -1355,37 +1369,35 @@ int pc_calc_skilltree(struct map_session_data *sd) default: break; } - if( skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) + if( skill_db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL) ) continue; //Only skills you can't have are npc/guild ones - if( skill_get_max(i) > 0 ) - sd->status.skill[i].id = i; + if( skill_db[i].max > 0 ) + sd->status.skill[i].id = skill_db[i].nameid; } return 0; } do { flag = 0; - for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) - { - int j, f, k, inf2; - - if( sd->status.skill[id].id ) + for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) { + int f, idx = skill_tree[c][i].idx; + if( sd->status.skill[idx].id ) continue; //Skill already known. f = 1; if(!battle_config.skillfree) { + int j; for(j = 0; j < MAX_PC_SKILL_REQUIRE; j++) { - if((k=skill_tree[c][i].need[j].id)) - { - if (sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED) + int k; + if((k=skill_tree[c][i].need[j].id)) { + int idx2 = skill_tree[c][i].need[j].idx; + if (sd->status.skill[idx2].id == 0 || sd->status.skill[idx2].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[idx2].flag == SKILL_FLAG_PLAGIARIZED) k = 0; //Not learned. + else if (sd->status.skill[idx2].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level + k = sd->status.skill[idx2].flag - SKILL_FLAG_REPLACED_LV_0; else - if (sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level - k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; - else - k = pc_checkskill(sd,k); - if (k < skill_tree[c][i].need[j].lv) - { + k = pc_checkskill2(sd,idx2); + if (k < skill_tree[c][i].need[j].lv) { f = 0; break; } @@ -1394,22 +1406,22 @@ int pc_calc_skilltree(struct map_session_data *sd) if( sd->status.job_level < skill_tree[c][i].joblv ) f = 0; // job level requirement wasn't satisfied } - if( f ) { - inf2 = skill_get_inf2(id); - - if(!sd->status.skill[id].lv && ( + int inf2; + inf2 = skill_db[idx].inf2; + + if(!sd->status.skill[idx].lv && ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || inf2&INF2_WEDDING_SKILL || (inf2&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) )) continue; //Cannot be learned via normal means. Note this check DOES allows raising already known skills. - sd->status.skill[id].id = id; + sd->status.skill[idx].id = id; if(inf2&INF2_SPIRIT_SKILL) { //Spirit skills cannot be learned, they will only show up on your tree when you get buffed. - sd->status.skill[id].lv = 1; // need to manually specify a skill level - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. + sd->status.skill[idx].lv = 1; // need to manually specify a skill level + sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; //So it is not saved, and tagged as a "bonus" skill. } flag = 1; // skill list has changed, perform another pass } @@ -1425,22 +1437,19 @@ int pc_calc_skilltree(struct map_session_data *sd) - (c > 0) to avoid grant Novice Skill Tree in case of Skill Reset (need more logic) - (sd->status.skill_point == 0) to wait until all skill points are asigned to avoid problems with Job Change quest. */ - for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) - { - if( (skill_get_inf2(id)&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) + for( i = 0; i < MAX_SKILL_TREE && (id = skill_tree[c][i].id) > 0; i++ ) { + int idx = skill_tree[c][i].idx; + if( (skill_db[idx].inf2&(INF2_QUEST_SKILL|INF2_WEDDING_SKILL)) ) continue; //Do not include Quest/Wedding skills. - if( sd->status.skill[id].id == 0 ) - { - sd->status.skill[id].id = id; - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. - } - else - { - sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Remember original level + if( sd->status.skill[idx].id == 0 ) { + sd->status.skill[idx].id = id; + sd->status.skill[idx].flag = SKILL_FLAG_TEMPORARY; // So it is not saved, and tagged as a "bonus" skill. + } else if( id != NV_BASIC) { + sd->status.skill[idx].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[idx].lv; // Remember original level } - sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); + sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); } } @@ -1448,7 +1457,7 @@ int pc_calc_skilltree(struct map_session_data *sd) } //Checks if you can learn a new skill after having leveled up a skill. -static void pc_check_skilltree(struct map_session_data *sd, int skill) +static void pc_check_skilltree(struct map_session_data *sd, int skill_id) { int i,id=0,flag; int c=0; @@ -1465,26 +1474,22 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill) c = pc_class2idx(c); do { flag = 0; - for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ ) - { - int j, f = 1, k; + for( i = 0; i < MAX_SKILL_TREE && (id=skill_tree[c][i].id)>0; i++ ) { + int j, f = 1, k, idx = skill_tree[c][i].idx; - if( sd->status.skill[id].id ) //Already learned + if( sd->status.skill[idx].id ) //Already learned continue; - for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) - { - if( (k = skill_tree[c][i].need[j].id) ) - { - if( sd->status.skill[k].id == 0 || sd->status.skill[k].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[k].flag == SKILL_FLAG_PLAGIARIZED ) + for( j = 0; j < MAX_PC_SKILL_REQUIRE; j++ ) { + if( (k = skill_tree[c][i].need[j].id) ) { + int idx2 = skill_tree[c][i].need[j].idx; + if( sd->status.skill[idx2].id == 0 || sd->status.skill[idx2].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[idx2].flag == SKILL_FLAG_PLAGIARIZED ) k = 0; //Not learned. + else if( sd->status.skill[idx2].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level + k = sd->status.skill[idx2].flag - SKILL_FLAG_REPLACED_LV_0; else - if( sd->status.skill[k].flag >= SKILL_FLAG_REPLACED_LV_0) //Real lerned level - k = sd->status.skill[skill_tree[c][i].need[j].id].flag - SKILL_FLAG_REPLACED_LV_0; - else - k = pc_checkskill(sd,k); - if( k < skill_tree[c][i].need[j].lv ) - { + k = pc_checkskill2(sd,idx2); + if( k < skill_tree[c][i].need[j].lv ) { f = 0; break; } @@ -1495,15 +1500,15 @@ static void pc_check_skilltree(struct map_session_data *sd, int skill) if( sd->status.job_level < skill_tree[c][i].joblv ) continue; - j = skill_get_inf2(id); - if( !sd->status.skill[id].lv && ( + j = skill_db[idx].inf2; + if( !sd->status.skill[idx].lv && ( (j&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || j&INF2_WEDDING_SKILL || (j&INF2_SPIRIT_SKILL && !sd->sc.data[SC_SPIRIT]) ) ) continue; //Cannot be learned via normal means. - sd->status.skill[id].id = id; + sd->status.skill[idx].id = id; flag = 1; } } while(flag); @@ -1515,14 +1520,11 @@ int pc_clean_skilltree(struct map_session_data *sd) { int i; for (i = 0; i < MAX_SKILL; i++){ - if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) - { + if (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY || sd->status.skill[i].flag == SKILL_FLAG_PLAGIARIZED) { sd->status.skill[i].id = 0; sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; - } - else - if (sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0){ + } else if (sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0) { sd->status.skill[i].lv = sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = 0; } @@ -1576,16 +1578,11 @@ int pc_calc_skilltree_normalize_job(struct map_session_data *sd) pc_setglobalreg (sd, "jobchange_level", sd->change_level_2nd); } - if (skill_point < novice_skills + (sd->change_level_2nd - 1)) - { + if (skill_point < novice_skills + (sd->change_level_2nd - 1)) { c &= MAPID_BASEMASK; - } - // limit 3rd class to 2nd class/trans job levels - else if(sd->class_&JOBL_THIRD) - { + } else if(sd->class_&JOBL_THIRD) { // limit 3rd class to 2nd class/trans job levels // regenerate change_level_3rd - if (!sd->change_level_3rd) - { + if (!sd->change_level_3rd) { sd->change_level_3rd = 1 + skill_point + sd->status.skill_point - (sd->status.job_level - 1) - (sd->change_level_2nd - 1) @@ -1642,39 +1639,37 @@ int pc_updateweightstatus(struct map_session_data *sd) return 0; } -int pc_disguise(struct map_session_data *sd, int class_) -{ - if (!class_ && !sd->disguise) +int pc_disguise(struct map_session_data *sd, int class_) { + if (class_ == -1 && sd->disguise == -1) return 0; - if (class_ && sd->disguise == class_) + if (class_ >= 0 && sd->disguise == class_) return 0; - if(sd->sc.option&OPTION_INVISIBLE) - { //Character is invisible. Stealth class-change. [Skotlex] + if(sd->sc.option&OPTION_INVISIBLE) { //Character is invisible. Stealth class-change. [Skotlex] sd->disguise = class_; //viewdata is set on uncloaking. return 2; } if (sd->bl.prev != NULL) { pc_stop_walking(sd, 0); - clif_clearunit_area(&sd->bl, CLR_OUTSIGHT); + clif->clearunit_area(&sd->bl, CLR_OUTSIGHT); } - if (!class_) { - sd->disguise = 0; + if (class_ == -1) { + sd->disguise = -1; class_ = sd->status.class_; } else - sd->disguise=class_; + sd->disguise = class_; status_set_viewdata(&sd->bl, class_); - clif_changeoption(&sd->bl); + clif->changeoption(&sd->bl); if (sd->bl.prev != NULL) { - clif_spawn(&sd->bl); - if (class_ == sd->status.class_ && pc_iscarton(sd)) - { //It seems the cart info is lost on undisguise. - clif_cartlist(sd); - clif_updatestatus(sd,SP_CARTINFO); + clif->spawn(&sd->bl); + if (class_ == sd->status.class_ && pc_iscarton(sd)) { + //It seems the cart info is lost on undisguise. + clif->cartlist(sd); + clif->updatestatus(sd,SP_CARTINFO); } } return 1; @@ -2026,593 +2021,604 @@ int pc_bonus(struct map_session_data *sd,int type,int val) status = &sd->base_status; switch(type){ - case SP_STR: - case SP_AGI: - case SP_VIT: - case SP_INT: - case SP_DEX: - case SP_LUK: - if(sd->state.lr_flag != 2) - sd->param_bonus[type-SP_STR]+=val; - break; - case SP_ATK1: - if(!sd->state.lr_flag) { - bonus = status->rhw.atk + val; - status->rhw.atk = cap_value(bonus, 0, USHRT_MAX); - } - else if(sd->state.lr_flag == 1) { - bonus = status->lhw.atk + val; - status->lhw.atk = cap_value(bonus, 0, USHRT_MAX); - } - break; - case SP_ATK2: - if(!sd->state.lr_flag) { - bonus = status->rhw.atk2 + val; - status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX); - } - else if(sd->state.lr_flag == 1) { - bonus = status->lhw.atk2 + val; - status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX); - } - break; - case SP_BASE_ATK: - if(sd->state.lr_flag != 2) { -//#ifdef RENEWAL -// sd->bonus.eatk += val; -//#else - bonus = status->batk + val; - status->batk = cap_value(bonus, 0, USHRT_MAX); -//#endif - } - break; - case SP_DEF1: - if(sd->state.lr_flag != 2) { - bonus = status->def + val; -#ifdef RENEWAL - status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX); -#else - status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX); -#endif - } - break; - case SP_DEF2: - if(sd->state.lr_flag != 2) { - bonus = status->def2 + val; - status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_MDEF1: - if(sd->state.lr_flag != 2) { - bonus = status->mdef + val; -#ifdef RENEWAL - status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX); -#else - status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX); -#endif - if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard - sd->bonus.shieldmdef += bonus; + case SP_STR: + case SP_AGI: + case SP_VIT: + case SP_INT: + case SP_DEX: + case SP_LUK: + if(sd->state.lr_flag != 2) + sd->param_bonus[type-SP_STR]+=val; + break; + case SP_ATK1: + if(!sd->state.lr_flag) { + bonus = status->rhw.atk + val; + status->rhw.atk = cap_value(bonus, 0, USHRT_MAX); + } + else if(sd->state.lr_flag == 1) { + bonus = status->lhw.atk + val; + status->lhw.atk = cap_value(bonus, 0, USHRT_MAX); } - } - break; - case SP_MDEF2: - if(sd->state.lr_flag != 2) { - bonus = status->mdef2 + val; - status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_HIT: - if(sd->state.lr_flag != 2) { - bonus = status->hit + val; - status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } else - sd->bonus.arrow_hit+=val; - break; - case SP_FLEE1: - if(sd->state.lr_flag != 2) { - bonus = status->flee + val; - status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_FLEE2: - if(sd->state.lr_flag != 2) { - bonus = status->flee2 + val*10; - status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } - break; - case SP_CRITICAL: - if(sd->state.lr_flag != 2) { - bonus = status->cri + val*10; - status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX); - } else - sd->bonus.arrow_cri += val*10; - break; - case SP_ATKELE: - if(val >= ELE_MAX) { - ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val); break; - } - switch (sd->state.lr_flag) - { - case 2: - switch (sd->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - //Become weapon element. - status->rhw.ele=val; - break; - default: //Become arrow element. - sd->bonus.arrow_ele=val; - break; + case SP_ATK2: + if(!sd->state.lr_flag) { + bonus = status->rhw.atk2 + val; + status->rhw.atk2 = cap_value(bonus, 0, USHRT_MAX); + } + else if(sd->state.lr_flag == 1) { + bonus = status->lhw.atk2 + val; + status->lhw.atk2 = cap_value(bonus, 0, USHRT_MAX); } break; - case 1: - status->lhw.ele=val; + case SP_BASE_ATK: + if(sd->state.lr_flag != 2) { + //#ifdef RENEWAL + // sd->bonus.eatk += val; + //#else + bonus = status->batk + val; + status->batk = cap_value(bonus, 0, USHRT_MAX); + //#endif + } break; - default: - status->rhw.ele=val; + case SP_DEF1: + if(sd->state.lr_flag != 2) { + bonus = status->def + val; + #ifdef RENEWAL + status->def = cap_value(bonus, SHRT_MIN, SHRT_MAX); + #else + status->def = cap_value(bonus, CHAR_MIN, CHAR_MAX); + #endif + } break; - } - break; - case SP_DEFELE: - if(val >= ELE_MAX) { - ShowError("pc_bonus: SP_DEFELE: Invalid element %d\n", val); + case SP_DEF2: + if(sd->state.lr_flag != 2) { + bonus = status->def2 + val; + status->def2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } break; - } - if(sd->state.lr_flag != 2) - status->def_ele=val; - break; - case SP_MAXHP: - if(sd->state.lr_flag == 2) + case SP_MDEF1: + if(sd->state.lr_flag != 2) { + bonus = status->mdef + val; + #ifdef RENEWAL + status->mdef = cap_value(bonus, SHRT_MIN, SHRT_MAX); + #else + status->mdef = cap_value(bonus, CHAR_MIN, CHAR_MAX); + #endif + if( sd->state.lr_flag == 3 ) {//Shield, used for royal guard + sd->bonus.shieldmdef += bonus; + } + } break; - val += (int)status->max_hp; - //Negative bonuses will underflow, this will be handled in status_calc_pc through casting - //If this is called outside of status_calc_pc, you'd better pray they do not underflow and end with UINT_MAX max_hp. - status->max_hp = (unsigned int)val; - break; - case SP_MAXSP: - if(sd->state.lr_flag == 2) + case SP_MDEF2: + if(sd->state.lr_flag != 2) { + bonus = status->mdef2 + val; + status->mdef2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } break; - val += (int)status->max_sp; - status->max_sp = (unsigned int)val; - break; -#ifndef RENEWAL_CAST - case SP_VARCASTRATE: -#endif - case SP_CASTRATE: - if(sd->state.lr_flag != 2) - sd->castrate+=val; - break; - case SP_MAXHPRATE: - if(sd->state.lr_flag != 2) - sd->hprate+=val; - break; - case SP_MAXSPRATE: - if(sd->state.lr_flag != 2) - sd->sprate+=val; - break; - case SP_SPRATE: - if(sd->state.lr_flag != 2) - sd->dsprate+=val; - break; - case SP_ATTACKRANGE: - switch (sd->state.lr_flag) { - case 2: - switch (sd->status.weapon) { - case W_BOW: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - status->rhw.range += val; + case SP_HIT: + if(sd->state.lr_flag != 2) { + bonus = status->hit + val; + status->hit = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } else + sd->bonus.arrow_hit+=val; + break; + case SP_FLEE1: + if(sd->state.lr_flag != 2) { + bonus = status->flee + val; + status->flee = cap_value(bonus, SHRT_MIN, SHRT_MAX); } break; - case 1: - status->lhw.range += val; + case SP_FLEE2: + if(sd->state.lr_flag != 2) { + bonus = status->flee2 + val*10; + status->flee2 = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } break; - default: - status->rhw.range += val; + case SP_CRITICAL: + if(sd->state.lr_flag != 2) { + bonus = status->cri + val*10; + status->cri = cap_value(bonus, SHRT_MIN, SHRT_MAX); + } else + sd->bonus.arrow_cri += val*10; break; - } - break; - case SP_SPEED_RATE: //Non stackable increase - if(sd->state.lr_flag != 2) - sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val); - break; - case SP_SPEED_ADDRATE: //Stackable increase - if(sd->state.lr_flag != 2) - sd->bonus.speed_add_rate -= val; - break; - case SP_ASPD: //Raw increase - if(sd->state.lr_flag != 2) - sd->bonus.aspd_add -= 10*val; - break; - case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone - if(sd->state.lr_flag != 2) -#ifndef RENEWAL_ASPD - status->aspd_rate -= 10*val; -#else - status->aspd_rate2 += val; -#endif - break; - case SP_HP_RECOV_RATE: - if(sd->state.lr_flag != 2) - sd->hprecov_rate += val; - break; - case SP_SP_RECOV_RATE: - if(sd->state.lr_flag != 2) - sd->sprecov_rate += val; - break; - case SP_CRITICAL_DEF: - if(sd->state.lr_flag != 2) - sd->bonus.critical_def += val; - break; - case SP_NEAR_ATK_DEF: - if(sd->state.lr_flag != 2) - sd->bonus.near_attack_def_rate += val; - break; - case SP_LONG_ATK_DEF: - if(sd->state.lr_flag != 2) - sd->bonus.long_attack_def_rate += val; - break; - case SP_DOUBLE_RATE: - if(sd->state.lr_flag == 0 && sd->bonus.double_rate < val) - sd->bonus.double_rate = val; - break; - case SP_DOUBLE_ADD_RATE: - if(sd->state.lr_flag == 0) - sd->bonus.double_add_rate += val; - break; - case SP_MATK_RATE: - if(sd->state.lr_flag != 2) - sd->matk_rate += val; - break; - case SP_IGNORE_DEF_ELE: - if(val >= ELE_MAX) { - ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val); + case SP_ATKELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_ATKELE: Invalid element %d\n", val); + break; + } + switch (sd->state.lr_flag) + { + case 2: + switch (sd->status.weapon) { + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + //Become weapon element. + status->rhw.ele=val; + break; + default: //Become arrow element. + sd->bonus.arrow_ele=val; + break; + } + break; + case 1: + status->lhw.ele=val; + break; + default: + status->rhw.ele=val; + break; + } break; - } - if(!sd->state.lr_flag) - sd->right_weapon.ignore_def_ele |= 1<<val; - else if(sd->state.lr_flag == 1) - sd->left_weapon.ignore_def_ele |= 1<<val; - break; - case SP_IGNORE_DEF_RACE: - if(!sd->state.lr_flag) - sd->right_weapon.ignore_def_race |= 1<<val; - else if(sd->state.lr_flag == 1) - sd->left_weapon.ignore_def_race |= 1<<val; - break; - case SP_ATK_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.atk_rate += val; - break; - case SP_MAGIC_ATK_DEF: - if(sd->state.lr_flag != 2) - sd->bonus.magic_def_rate += val; - break; - case SP_MISC_ATK_DEF: - if(sd->state.lr_flag != 2) - sd->bonus.misc_def_rate += val; - break; - case SP_IGNORE_MDEF_RATE: - if(sd->state.lr_flag != 2) { - sd->ignore_mdef[RC_NONBOSS] += val; - sd->ignore_mdef[RC_BOSS] += val; - } - break; - case SP_IGNORE_MDEF_ELE: - if(val >= ELE_MAX) { - ShowError("pc_bonus: SP_IGNORE_MDEF_ELE: Invalid element %d\n", val); + case SP_DEFELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_DEFELE: Invalid element %d\n", val); + break; + } + if(sd->state.lr_flag != 2) + status->def_ele=val; break; - } - if(sd->state.lr_flag != 2) - sd->bonus.ignore_mdef_ele |= 1<<val; - break; - case SP_IGNORE_MDEF_RACE: - if(sd->state.lr_flag != 2) - sd->bonus.ignore_mdef_race |= 1<<val; - break; - case SP_PERFECT_HIT_RATE: - if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val) - sd->bonus.perfect_hit = val; - break; - case SP_PERFECT_HIT_ADD_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.perfect_hit_add += val; - break; - case SP_CRITICAL_RATE: - if(sd->state.lr_flag != 2) - sd->critical_rate+=val; - break; - case SP_DEF_RATIO_ATK_ELE: - if(val >= ELE_MAX) { - ShowError("pc_bonus: SP_DEF_RATIO_ATK_ELE: Invalid element %d\n", val); + case SP_MAXHP: + if(sd->state.lr_flag == 2) + break; + val += (int)status->max_hp; + //Negative bonuses will underflow, this will be handled in status_calc_pc through casting + //If this is called outside of status_calc_pc, you'd better pray they do not underflow and end with UINT_MAX max_hp. + status->max_hp = (unsigned int)val; break; - } - if(!sd->state.lr_flag) - sd->right_weapon.def_ratio_atk_ele |= 1<<val; - else if(sd->state.lr_flag == 1) - sd->left_weapon.def_ratio_atk_ele |= 1<<val; - break; - case SP_DEF_RATIO_ATK_RACE: - if(val >= RC_MAX) { - ShowError("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid race %d\n", val); + case SP_MAXSP: + if(sd->state.lr_flag == 2) + break; + val += (int)status->max_sp; + status->max_sp = (unsigned int)val; break; - } - if(!sd->state.lr_flag) - sd->right_weapon.def_ratio_atk_race |= 1<<val; - else if(sd->state.lr_flag == 1) - sd->left_weapon.def_ratio_atk_race |= 1<<val; - break; - case SP_HIT_RATE: - if(sd->state.lr_flag != 2) - sd->hit_rate += val; - break; - case SP_FLEE_RATE: - if(sd->state.lr_flag != 2) - sd->flee_rate += val; - break; - case SP_FLEE2_RATE: - if(sd->state.lr_flag != 2) - sd->flee2_rate += val; - break; - case SP_DEF_RATE: - if(sd->state.lr_flag != 2) - sd->def_rate += val; - break; - case SP_DEF2_RATE: - if(sd->state.lr_flag != 2) - sd->def2_rate += val; - break; - case SP_MDEF_RATE: - if(sd->state.lr_flag != 2) - sd->mdef_rate += val; - break; - case SP_MDEF2_RATE: - if(sd->state.lr_flag != 2) - sd->mdef2_rate += val; - break; - case SP_RESTART_FULL_RECOVER: - if(sd->state.lr_flag != 2) - sd->special_state.restart_full_recover = 1; - break; - case SP_NO_CASTCANCEL: - if(sd->state.lr_flag != 2) - sd->special_state.no_castcancel = 1; - break; - case SP_NO_CASTCANCEL2: - if(sd->state.lr_flag != 2) - sd->special_state.no_castcancel2 = 1; - break; - case SP_NO_SIZEFIX: - if(sd->state.lr_flag != 2) - sd->special_state.no_sizefix = 1; - break; - case SP_NO_MAGIC_DAMAGE: - if(sd->state.lr_flag == 2) + #ifndef RENEWAL_CAST + case SP_VARCASTRATE: + #endif + case SP_CASTRATE: + if(sd->state.lr_flag != 2) + sd->castrate+=val; break; - val+= sd->special_state.no_magic_damage; - sd->special_state.no_magic_damage = cap_value(val,0,100); - break; - case SP_NO_WEAPON_DAMAGE: - if(sd->state.lr_flag == 2) + case SP_MAXHPRATE: + if(sd->state.lr_flag != 2) + sd->hprate+=val; break; - val+= sd->special_state.no_weapon_damage; - sd->special_state.no_weapon_damage = cap_value(val,0,100); - break; - case SP_NO_MISC_DAMAGE: - if(sd->state.lr_flag == 2) + case SP_MAXSPRATE: + if(sd->state.lr_flag != 2) + sd->sprate+=val; + break; + case SP_SPRATE: + if(sd->state.lr_flag != 2) + sd->dsprate+=val; + break; + case SP_ATTACKRANGE: + switch (sd->state.lr_flag) { + case 2: + switch (sd->status.weapon) { + case W_BOW: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + status->rhw.range += val; + } + break; + case 1: + status->lhw.range += val; + break; + default: + status->rhw.range += val; + break; + } + break; + case SP_SPEED_RATE: //Non stackable increase + if(sd->state.lr_flag != 2) + sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val); + break; + case SP_SPEED_ADDRATE: //Stackable increase + if(sd->state.lr_flag != 2) + sd->bonus.speed_add_rate -= val; + break; + case SP_ASPD: //Raw increase + if(sd->state.lr_flag != 2) + sd->bonus.aspd_add -= 10*val; + break; + case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone + if(sd->state.lr_flag != 2) + #ifndef RENEWAL_ASPD + status->aspd_rate -= 10*val; + #else + status->aspd_rate2 += val; + #endif + break; + case SP_HP_RECOV_RATE: + if(sd->state.lr_flag != 2) + sd->hprecov_rate += val; + break; + case SP_SP_RECOV_RATE: + if(sd->state.lr_flag != 2) + sd->sprecov_rate += val; + break; + case SP_CRITICAL_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.critical_def += val; + break; + case SP_NEAR_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.near_attack_def_rate += val; + break; + case SP_LONG_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.long_attack_def_rate += val; + break; + case SP_DOUBLE_RATE: + if(sd->state.lr_flag == 0 && sd->bonus.double_rate < val) + sd->bonus.double_rate = val; + break; + case SP_DOUBLE_ADD_RATE: + if(sd->state.lr_flag == 0) + sd->bonus.double_add_rate += val; + break; + case SP_MATK_RATE: + if(sd->state.lr_flag != 2) + sd->matk_rate += val; + break; + case SP_IGNORE_DEF_ELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_IGNORE_DEF_ELE: Invalid element %d\n", val); + break; + } + if(!sd->state.lr_flag) + sd->right_weapon.ignore_def_ele |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.ignore_def_ele |= 1<<val; + break; + case SP_IGNORE_DEF_RACE: + if(!sd->state.lr_flag) + sd->right_weapon.ignore_def_race |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.ignore_def_race |= 1<<val; + break; + case SP_ATK_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.atk_rate += val; + break; + case SP_MAGIC_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.magic_def_rate += val; + break; + case SP_MISC_ATK_DEF: + if(sd->state.lr_flag != 2) + sd->bonus.misc_def_rate += val; + break; + case SP_IGNORE_MDEF_RATE: + if(sd->state.lr_flag != 2) { + sd->ignore_mdef[RC_NONBOSS] += val; + sd->ignore_mdef[RC_BOSS] += val; + } + break; + case SP_IGNORE_MDEF_ELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_IGNORE_MDEF_ELE: Invalid element %d\n", val); + break; + } + if(sd->state.lr_flag != 2) + sd->bonus.ignore_mdef_ele |= 1<<val; + break; + case SP_IGNORE_MDEF_RACE: + if(sd->state.lr_flag != 2) + sd->bonus.ignore_mdef_race |= 1<<val; + break; + case SP_PERFECT_HIT_RATE: + if(sd->state.lr_flag != 2 && sd->bonus.perfect_hit < val) + sd->bonus.perfect_hit = val; + break; + case SP_PERFECT_HIT_ADD_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.perfect_hit_add += val; + break; + case SP_CRITICAL_RATE: + if(sd->state.lr_flag != 2) + sd->critical_rate+=val; + break; + case SP_DEF_RATIO_ATK_ELE: + if(val >= ELE_MAX) { + ShowError("pc_bonus: SP_DEF_RATIO_ATK_ELE: Invalid element %d\n", val); + break; + } + if(!sd->state.lr_flag) + sd->right_weapon.def_ratio_atk_ele |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.def_ratio_atk_ele |= 1<<val; + break; + case SP_DEF_RATIO_ATK_RACE: + if(val >= RC_MAX) { + ShowError("pc_bonus: SP_DEF_RATIO_ATK_RACE: Invalid race %d\n", val); + break; + } + if(!sd->state.lr_flag) + sd->right_weapon.def_ratio_atk_race |= 1<<val; + else if(sd->state.lr_flag == 1) + sd->left_weapon.def_ratio_atk_race |= 1<<val; + break; + case SP_HIT_RATE: + if(sd->state.lr_flag != 2) + sd->hit_rate += val; + break; + case SP_FLEE_RATE: + if(sd->state.lr_flag != 2) + sd->flee_rate += val; + break; + case SP_FLEE2_RATE: + if(sd->state.lr_flag != 2) + sd->flee2_rate += val; + break; + case SP_DEF_RATE: + if(sd->state.lr_flag != 2) + sd->def_rate += val; + break; + case SP_DEF2_RATE: + if(sd->state.lr_flag != 2) + sd->def2_rate += val; + break; + case SP_MDEF_RATE: + if(sd->state.lr_flag != 2) + sd->mdef_rate += val; + break; + case SP_MDEF2_RATE: + if(sd->state.lr_flag != 2) + sd->mdef2_rate += val; + break; + case SP_RESTART_FULL_RECOVER: + if(sd->state.lr_flag != 2) + sd->special_state.restart_full_recover = 1; + break; + case SP_NO_CASTCANCEL: + if(sd->state.lr_flag != 2) + sd->special_state.no_castcancel = 1; + break; + case SP_NO_CASTCANCEL2: + if(sd->state.lr_flag != 2) + sd->special_state.no_castcancel2 = 1; + break; + case SP_NO_SIZEFIX: + if(sd->state.lr_flag != 2) + sd->special_state.no_sizefix = 1; + break; + case SP_NO_MAGIC_DAMAGE: + if(sd->state.lr_flag == 2) + break; + val+= sd->special_state.no_magic_damage; + sd->special_state.no_magic_damage = cap_value(val,0,100); + break; + case SP_NO_WEAPON_DAMAGE: + if(sd->state.lr_flag == 2) + break; + val+= sd->special_state.no_weapon_damage; + sd->special_state.no_weapon_damage = cap_value(val,0,100); + break; + case SP_NO_MISC_DAMAGE: + if(sd->state.lr_flag == 2) + break; + val+= sd->special_state.no_misc_damage; + sd->special_state.no_misc_damage = cap_value(val,0,100); + break; + case SP_NO_GEMSTONE: + if(sd->state.lr_flag != 2) + sd->special_state.no_gemstone = 1; + break; + case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG] + if(sd->state.lr_flag != 2) { + sd->special_state.intravision = 1; + clif->status_change(&sd->bl, SI_INTRAVISION, 1, 0, 0, 0, 0); + } + break; + case SP_NO_KNOCKBACK: + if(sd->state.lr_flag != 2) + sd->special_state.no_knockback = 1; + break; + case SP_SPLASH_RANGE: + if(sd->bonus.splash_range < val) + sd->bonus.splash_range = val; + break; + case SP_SPLASH_ADD_RANGE: + sd->bonus.splash_add_range += val; + break; + case SP_SHORT_WEAPON_DAMAGE_RETURN: + if(sd->state.lr_flag != 2) + sd->bonus.short_weapon_damage_return += val; + break; + case SP_LONG_WEAPON_DAMAGE_RETURN: + if(sd->state.lr_flag != 2) + sd->bonus.long_weapon_damage_return += val; + break; + case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here + if(sd->state.lr_flag != 2) + sd->bonus.magic_damage_return += val; + break; + case SP_ALL_STATS: // [Valaris] + if(sd->state.lr_flag!=2) { + sd->param_bonus[SP_STR-SP_STR]+=val; + sd->param_bonus[SP_AGI-SP_STR]+=val; + sd->param_bonus[SP_VIT-SP_STR]+=val; + sd->param_bonus[SP_INT-SP_STR]+=val; + sd->param_bonus[SP_DEX-SP_STR]+=val; + sd->param_bonus[SP_LUK-SP_STR]+=val; + } + break; + case SP_AGI_VIT: // [Valaris] + if(sd->state.lr_flag!=2) { + sd->param_bonus[SP_AGI-SP_STR]+=val; + sd->param_bonus[SP_VIT-SP_STR]+=val; + } + break; + case SP_AGI_DEX_STR: // [Valaris] + if(sd->state.lr_flag!=2) { + sd->param_bonus[SP_AGI-SP_STR]+=val; + sd->param_bonus[SP_DEX-SP_STR]+=val; + sd->param_bonus[SP_STR-SP_STR]+=val; + } + break; + case SP_PERFECT_HIDE: // [Valaris] + if(sd->state.lr_flag!=2) + sd->special_state.perfect_hiding=1; + break; + case SP_UNBREAKABLE: + if(sd->state.lr_flag!=2) + sd->bonus.unbreakable += val; + break; + case SP_UNBREAKABLE_WEAPON: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_WEAPON; + break; + case SP_UNBREAKABLE_ARMOR: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_ARMOR; + break; + case SP_UNBREAKABLE_HELM: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_HELM; + break; + case SP_UNBREAKABLE_SHIELD: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_SHIELD; + break; + case SP_UNBREAKABLE_GARMENT: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_GARMENT; + break; + case SP_UNBREAKABLE_SHOES: + if(sd->state.lr_flag != 2) + sd->bonus.unbreakable_equip |= EQP_SHOES; + break; + case SP_CLASSCHANGE: // [Valaris] + if(sd->state.lr_flag !=2) + sd->bonus.classchange=val; + break; + case SP_LONG_ATK_RATE: + if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses + sd->bonus.long_attack_atk_rate+=val; + break; + case SP_BREAK_WEAPON_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.break_weapon_rate+=val; + break; + case SP_BREAK_ARMOR_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.break_armor_rate+=val; + break; + case SP_ADD_STEAL_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.add_steal_rate+=val; + break; + case SP_DELAYRATE: + if(sd->state.lr_flag != 2) + sd->delayrate+=val; + break; + case SP_CRIT_ATK_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.crit_atk_rate += val; + break; + case SP_NO_REGEN: + if(sd->state.lr_flag != 2) + sd->regen.state.block|=val; + break; + case SP_UNSTRIPABLE_WEAPON: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_WEAPON; + break; + case SP_UNSTRIPABLE: + case SP_UNSTRIPABLE_ARMOR: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_ARMOR; + break; + case SP_UNSTRIPABLE_HELM: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_HELM; + break; + case SP_UNSTRIPABLE_SHIELD: + if(sd->state.lr_flag != 2) + sd->bonus.unstripable_equip |= EQP_SHIELD; + break; + case SP_HP_DRAIN_VALUE: + if(!sd->state.lr_flag) { + sd->right_weapon.hp_drain[RC_NONBOSS].value += val; + sd->right_weapon.hp_drain[RC_BOSS].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.hp_drain[RC_NONBOSS].value += val; + sd->left_weapon.hp_drain[RC_BOSS].value += val; + } + break; + case SP_SP_DRAIN_VALUE: + if(!sd->state.lr_flag) { + sd->right_weapon.sp_drain[RC_NONBOSS].value += val; + sd->right_weapon.sp_drain[RC_BOSS].value += val; + } + else if(sd->state.lr_flag == 1) { + sd->left_weapon.sp_drain[RC_NONBOSS].value += val; + sd->left_weapon.sp_drain[RC_BOSS].value += val; + } + break; + case SP_SP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.sp_gain_value += val; + break; + case SP_HP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.hp_gain_value += val; + break; + case SP_MAGIC_SP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.magic_sp_gain_value += val; + break; + case SP_MAGIC_HP_GAIN_VALUE: + if(!sd->state.lr_flag) + sd->bonus.magic_hp_gain_value += val; + break; + case SP_ADD_HEAL_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.add_heal_rate += val; + break; + case SP_ADD_HEAL2_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.add_heal2_rate += val; + break; + case SP_ADD_ITEM_HEAL_RATE: + if(sd->state.lr_flag != 2) + sd->bonus.itemhealrate2 += val; + break; + case SP_EMATK: + if(sd->state.lr_flag != 2) + sd->bonus.ematk += val; + break; + case SP_FIXCASTRATE: + if(sd->state.lr_flag != 2) + sd->bonus.fixcastrate -= val; + break; + case SP_ADD_FIXEDCAST: + if(sd->state.lr_flag != 2) + sd->bonus.add_fixcast += val; + + break; + #ifdef RENEWAL_CAST + case SP_VARCASTRATE: + if(sd->state.lr_flag != 2) + sd->bonus.varcastrate -= val; + break; + case SP_ADD_VARIABLECAST: + if(sd->state.lr_flag != 2) + + sd->bonus.add_varcast += val; + + break; + #endif + default: + ShowWarning("pc_bonus: unknown type %d %d !\n",type,val); break; - val+= sd->special_state.no_misc_damage; - sd->special_state.no_misc_damage = cap_value(val,0,100); - break; - case SP_NO_GEMSTONE: - if(sd->state.lr_flag != 2) - sd->special_state.no_gemstone = 1; - break; - case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG] - if(sd->state.lr_flag != 2) { - sd->special_state.intravision = 1; - clif_status_load(&sd->bl, SI_INTRAVISION, 1); - } - break; - case SP_NO_KNOCKBACK: - if(sd->state.lr_flag != 2) - sd->special_state.no_knockback = 1; - break; - case SP_SPLASH_RANGE: - if(sd->bonus.splash_range < val) - sd->bonus.splash_range = val; - break; - case SP_SPLASH_ADD_RANGE: - sd->bonus.splash_add_range += val; - break; - case SP_SHORT_WEAPON_DAMAGE_RETURN: - if(sd->state.lr_flag != 2) - sd->bonus.short_weapon_damage_return += val; - break; - case SP_LONG_WEAPON_DAMAGE_RETURN: - if(sd->state.lr_flag != 2) - sd->bonus.long_weapon_damage_return += val; - break; - case SP_MAGIC_DAMAGE_RETURN: //AppleGirl Was Here - if(sd->state.lr_flag != 2) - sd->bonus.magic_damage_return += val; - break; - case SP_ALL_STATS: // [Valaris] - if(sd->state.lr_flag!=2) { - sd->param_bonus[SP_STR-SP_STR]+=val; - sd->param_bonus[SP_AGI-SP_STR]+=val; - sd->param_bonus[SP_VIT-SP_STR]+=val; - sd->param_bonus[SP_INT-SP_STR]+=val; - sd->param_bonus[SP_DEX-SP_STR]+=val; - sd->param_bonus[SP_LUK-SP_STR]+=val; - } - break; - case SP_AGI_VIT: // [Valaris] - if(sd->state.lr_flag!=2) { - sd->param_bonus[SP_AGI-SP_STR]+=val; - sd->param_bonus[SP_VIT-SP_STR]+=val; - } - break; - case SP_AGI_DEX_STR: // [Valaris] - if(sd->state.lr_flag!=2) { - sd->param_bonus[SP_AGI-SP_STR]+=val; - sd->param_bonus[SP_DEX-SP_STR]+=val; - sd->param_bonus[SP_STR-SP_STR]+=val; - } - break; - case SP_PERFECT_HIDE: // [Valaris] - if(sd->state.lr_flag!=2) - sd->special_state.perfect_hiding=1; - break; - case SP_UNBREAKABLE: - if(sd->state.lr_flag!=2) - sd->bonus.unbreakable += val; - break; - case SP_UNBREAKABLE_WEAPON: - if(sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_WEAPON; - break; - case SP_UNBREAKABLE_ARMOR: - if(sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_ARMOR; - break; - case SP_UNBREAKABLE_HELM: - if(sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_HELM; - break; - case SP_UNBREAKABLE_SHIELD: - if(sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_SHIELD; - break; - case SP_UNBREAKABLE_GARMENT: - if(sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_GARMENT; - break; - case SP_UNBREAKABLE_SHOES: - if(sd->state.lr_flag != 2) - sd->bonus.unbreakable_equip |= EQP_SHOES; - break; - case SP_CLASSCHANGE: // [Valaris] - if(sd->state.lr_flag !=2) - sd->bonus.classchange=val; - break; - case SP_LONG_ATK_RATE: - if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses - sd->bonus.long_attack_atk_rate+=val; - break; - case SP_BREAK_WEAPON_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.break_weapon_rate+=val; - break; - case SP_BREAK_ARMOR_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.break_armor_rate+=val; - break; - case SP_ADD_STEAL_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.add_steal_rate+=val; - break; - case SP_DELAYRATE: - if(sd->state.lr_flag != 2) - sd->delayrate+=val; - break; - case SP_CRIT_ATK_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.crit_atk_rate += val; - break; - case SP_NO_REGEN: - if(sd->state.lr_flag != 2) - sd->regen.state.block|=val; - break; - case SP_UNSTRIPABLE_WEAPON: - if(sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_WEAPON; - break; - case SP_UNSTRIPABLE: - case SP_UNSTRIPABLE_ARMOR: - if(sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_ARMOR; - break; - case SP_UNSTRIPABLE_HELM: - if(sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_HELM; - break; - case SP_UNSTRIPABLE_SHIELD: - if(sd->state.lr_flag != 2) - sd->bonus.unstripable_equip |= EQP_SHIELD; - break; - case SP_HP_DRAIN_VALUE: - if(!sd->state.lr_flag) { - sd->right_weapon.hp_drain[RC_NONBOSS].value += val; - sd->right_weapon.hp_drain[RC_BOSS].value += val; - } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.hp_drain[RC_NONBOSS].value += val; - sd->left_weapon.hp_drain[RC_BOSS].value += val; - } - break; - case SP_SP_DRAIN_VALUE: - if(!sd->state.lr_flag) { - sd->right_weapon.sp_drain[RC_NONBOSS].value += val; - sd->right_weapon.sp_drain[RC_BOSS].value += val; - } - else if(sd->state.lr_flag == 1) { - sd->left_weapon.sp_drain[RC_NONBOSS].value += val; - sd->left_weapon.sp_drain[RC_BOSS].value += val; - } - break; - case SP_SP_GAIN_VALUE: - if(!sd->state.lr_flag) - sd->bonus.sp_gain_value += val; - break; - case SP_HP_GAIN_VALUE: - if(!sd->state.lr_flag) - sd->bonus.hp_gain_value += val; - break; - case SP_MAGIC_SP_GAIN_VALUE: - if(!sd->state.lr_flag) - sd->bonus.magic_sp_gain_value += val; - break; - case SP_MAGIC_HP_GAIN_VALUE: - if(!sd->state.lr_flag) - sd->bonus.magic_hp_gain_value += val; - break; - case SP_ADD_HEAL_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.add_heal_rate += val; - break; - case SP_ADD_HEAL2_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.add_heal2_rate += val; - break; - case SP_ADD_ITEM_HEAL_RATE: - if(sd->state.lr_flag != 2) - sd->bonus.itemhealrate2 += val; - break; - case SP_EMATK: - if(sd->state.lr_flag != 2) - sd->bonus.ematk += val; - break; - case SP_FIXCASTRATE: - if(sd->state.lr_flag != 2) - sd->bonus.fixcastrate -= val; - break; -#ifdef RENEWAL_CAST - case SP_VARCASTRATE: - if(sd->state.lr_flag != 2) - sd->bonus.varcastrate -= val; - break; -#endif - default: - ShowWarning("pc_bonus: unknown type %d %d !\n",type,val); - break; } return 0; } @@ -2966,7 +2972,15 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2); if (i == ARRAYLENGTH(sd->skillcast)) { //Better mention this so the array length can be updated. [Skotlex] - ShowDebug("run_script: bonus2 bCastRate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcast), type2, val); + ShowDebug("run_script: bonus2 %s reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", + +#ifndef RENEWAL_CAST + "bCastRate", +#else + "bVariableCastrate", +#endif + + ARRAYLENGTH(sd->skillcast), type2, val); break; } if(sd->skillcast[i].id == type2) @@ -2977,6 +2991,30 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) } break; + case SP_FIXCASTRATE: + if(sd->state.lr_flag == 2) + break; + + ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2); + + if (i == ARRAYLENGTH(sd->skillfixcastrate)) + + { + + ShowDebug("run_script: bonus2 bFixedCastrate reached it's limit (%d skills per character), bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcastrate), type2, val); + break; + } + + if(sd->skillfixcastrate[i].id == type2) + sd->skillfixcastrate[i].val += val; + + else { + sd->skillfixcastrate[i].id = type2; + sd->skillfixcastrate[i].val = val; + } + + break; + case SP_HP_LOSS_RATE: if(sd->state.lr_flag != 2) { sd->hp_loss.value = type2; @@ -3202,8 +3240,8 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) case SP_AUTOSPELL: if(sd->state.lr_flag != 2) { - int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. - target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); + int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self. + target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF)); pc_bonus_autospell(sd->autospell, ARRAYLENGTH(sd->autospell), target?-type2:type2, type3, val, 0, current_equip_card_id); } @@ -3211,8 +3249,8 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) case SP_AUTOSPELL_WHENHIT: if(sd->state.lr_flag != 2) { - int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. - target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); + int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self. + target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF)); pc_bonus_autospell(sd->autospell2, ARRAYLENGTH(sd->autospell2), target?-type2:type2, type3, val, BF_NORMAL|BF_SKILL, current_equip_card_id); } @@ -3332,8 +3370,8 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4 case SP_AUTOSPELL_ONSKILL: if(sd->state.lr_flag != 2) { - int target = skill_get_inf(type2); //Support or Self (non-auto-target) skills should pick self. - target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill_get_inf2(type2)&INF2_NO_TARGET_SELF)); + int target = skill->get_inf(type2); //Support or Self (non-auto-target) skills should pick self. + target = target&INF_SUPPORT_SKILL || (target&INF_SELF_SKILL && !(skill->get_inf2(type2)&INF2_NO_TARGET_SELF)); pc_bonus_autospell_onskill(sd->autospell3, ARRAYLENGTH(sd->autospell3), type2, target?-type3:type3, type4, val, current_equip_card_id); } @@ -3385,17 +3423,17 @@ int pc_bonus5(struct map_session_data *sd,int type,int type2,int type3,int type4 } /*========================================== - * Grants a player a given skill. Flag values are: - * 0 - Grant skill unconditionally and forever (only this one invokes status_calc_pc, - * as the other two are assumed to be invoked from within it) - * 1 - Grant an item skill (temporary) - * 2 - Like 1, except the level granted can stack with previously learned level. + * Grants a player a given skill. Flag values are: + * 0 - Grant permanent skill to be bound to skill tree + * 1 - Grant an item skill (temporary) + * 2 - Like 1, except the level granted can stack with previously learned level. + * 3 - Grant skill unconditionally and forever (persistent to job changes and skill resets) *------------------------------------------*/ -int pc_skill(TBL_PC* sd, int id, int level, int flag) -{ +int pc_skill(TBL_PC* sd, int id, int level, int flag) { + uint16 index = 0; nullpo_ret(sd); - if( id <= 0 || id >= MAX_SKILL || skill_db[id].name == NULL) { + if( !(index = skill->get_index(id)) || skill_db[index].name == NULL) { ShowError("pc_skill: Skill with id %d does not exist in the skill database\n", id); return 0; } @@ -3403,48 +3441,58 @@ int pc_skill(TBL_PC* sd, int id, int level, int flag) ShowError("pc_skill: Skill level %d too high. Max lv supported is %d\n", level, MAX_SKILL_LEVEL); return 0; } - if( flag == 2 && sd->status.skill[id].lv + level > MAX_SKILL_LEVEL ) { - ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[id].lv); + if( flag == 2 && sd->status.skill[index].lv + level > MAX_SKILL_LEVEL ) { + ShowError("pc_skill: Skill level bonus %d too high. Max lv supported is %d. Curr lv is %d\n", level, MAX_SKILL_LEVEL, sd->status.skill[index].lv); return 0; } switch( flag ){ - case 0: //Set skill data overwriting whatever was there before. - sd->status.skill[id].id = id; - sd->status.skill[id].lv = level; - sd->status.skill[id].flag = SKILL_FLAG_PERMANENT; - if( level == 0 ) //Remove skill. - { - sd->status.skill[id].id = 0; - clif_deleteskill(sd,id); - } - else - clif_addskill(sd,id); - if( !skill_get_inf(id) ) //Only recalculate for passive skills. - status_calc_pc(sd, 0); - break; - case 1: //Item bonus skill. - if( sd->status.skill[id].id == id ){ - if( sd->status.skill[id].lv >= level ) - return 0; - if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level. - sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; - } else { - sd->status.skill[id].id = id; - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; - } - sd->status.skill[id].lv = level; - break; - case 2: //Add skill bonus on top of what you had. - if( sd->status.skill[id].id == id ){ - if( sd->status.skill[id].flag == SKILL_FLAG_PERMANENT ) - sd->status.skill[id].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[id].lv; // Store previous level. - } else { - sd->status.skill[id].id = id; - sd->status.skill[id].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill. - } - sd->status.skill[id].lv += level; - break; + case 0: //Set skill data overwriting whatever was there before. + sd->status.skill[index].id = id; + sd->status.skill[index].lv = level; + sd->status.skill[index].flag = SKILL_FLAG_PERMANENT; + if( level == 0 ) { //Remove skill. + sd->status.skill[index].id = 0; + clif->deleteskill(sd,id); + } else + clif->addskill(sd,id); + if( !skill_db[index].inf ) //Only recalculate for passive skills. + status_calc_pc(sd, 0); + break; + case 1: //Item bonus skill. + if( sd->status.skill[index].id == id ) { + if( sd->status.skill[index].lv >= level ) + return 0; + if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT ) //Non-granted skill, store it's level. + sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv; + } else { + sd->status.skill[index].id = id; + sd->status.skill[index].flag = SKILL_FLAG_TEMPORARY; + } + sd->status.skill[index].lv = level; + break; + case 2: //Add skill bonus on top of what you had. + if( sd->status.skill[index].id == id ) { + if( sd->status.skill[index].flag == SKILL_FLAG_PERMANENT ) + sd->status.skill[index].flag = SKILL_FLAG_REPLACED_LV_0 + sd->status.skill[index].lv; // Store previous level. + } else { + sd->status.skill[index].id = id; + sd->status.skill[index].flag = SKILL_FLAG_TEMPORARY; //Set that this is a bonus skill. + } + sd->status.skill[index].lv += level; + break; + case 3: + sd->status.skill[index].id = id; + sd->status.skill[index].lv = level; + sd->status.skill[index].flag = SKILL_FLAG_PERM_GRANTED; + if( level == 0 ) { //Remove skill. + sd->status.skill[index].id = 0; + clif->deleteskill(sd,id); + } else + clif->addskill(sd,id); + if( !skill_db[index].inf ) //Only recalculate for passive skills. + status_calc_pc(sd, 0); + break; default: //Unknown flag? return 0; } @@ -3492,14 +3540,14 @@ int pc_insert_card(struct map_session_data* sd, int idx_card, int idx_equip) if( pc_delitem(sd,idx_card,1,1,0,LOG_TYPE_OTHER) == 1 ) {// failed - clif_insert_card(sd,idx_equip,idx_card,1); + clif->insert_card(sd,idx_equip,idx_card,1); } else {// success - log_pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip]); + logs->pick_pc(sd, LOG_TYPE_OTHER, -1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); sd->status.inventory[idx_equip].card[i] = nameid; - log_pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip]); - clif_insert_card(sd,idx_equip,idx_card,0); + logs->pick_pc(sd, LOG_TYPE_OTHER, 1, &sd->status.inventory[idx_equip],sd->inventory_data[idx_equip]); + clif->insert_card(sd,idx_equip,idx_card,0); } return 0; @@ -3614,14 +3662,14 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, return 1; //Not enough. sd->status.zeny -= zeny; - clif_updatestatus(sd,SP_ZENY); + clif->updatestatus(sd,SP_ZENY); if(!tsd) tsd = sd; - log_zeny(sd, type, tsd, -zeny); + logs->zeny(sd, type, tsd, -zeny); if( zeny > 0 && sd->state.showzeny ) { char output[255]; sprintf(output, "Removed %dz.", zeny); - clif_disp_onlyself(sd,output,strlen(output)); + clif->disp_onlyself(sd,output,strlen(output)); } return 0; @@ -3632,7 +3680,6 @@ int pc_payzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, int pc_paycash(struct map_session_data *sd, int price, int points) { - char output[128]; int cash; nullpo_retr(-1,sd); @@ -3662,8 +3709,9 @@ int pc_paycash(struct map_session_data *sd, int price, int points) if( battle_config.cashshop_show_points ) { + char output[128]; sprintf(output, msg_txt(504), points, cash, sd->kafraPoints, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } return cash+points; } @@ -3688,7 +3736,7 @@ int pc_getcash(struct map_session_data *sd, int cash, int points) if( battle_config.cashshop_show_points ) { sprintf(output, msg_txt(505), cash, sd->cashPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } return cash; } @@ -3711,7 +3759,7 @@ int pc_getcash(struct map_session_data *sd, int cash, int points) if( battle_config.cashshop_show_points ) { sprintf(output, msg_txt(506), points, sd->kafraPoints); - clif_disp_onlyself(sd, output, strlen(output)); + clif->disp_onlyself(sd, output, strlen(output)); } return points; } @@ -3742,14 +3790,14 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type, zeny = MAX_ZENY - sd->status.zeny; sd->status.zeny += zeny; - clif_updatestatus(sd,SP_ZENY); + clif->updatestatus(sd,SP_ZENY); if(!tsd) tsd = sd; - log_zeny(sd, type, tsd, zeny); + logs->zeny(sd, type, tsd, zeny); if( zeny > 0 && sd->state.showzeny ) { char output[255]; sprintf(output, "Gained %dz.", zeny); - clif_disp_onlyself(sd,output,strlen(output)); + clif->disp_onlyself(sd,output,strlen(output)); } return 0; @@ -3815,7 +3863,7 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l 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; - clif_additem(sd,i,amount,0); + clif->additem(sd,i,amount,0); break; } } @@ -3834,16 +3882,16 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l sd->status.inventory[i].amount = amount; sd->inventory_data[i] = data; - clif_additem(sd,i,amount,0); + clif->additem(sd,i,amount,0); } #ifdef NSI_UNIQUE_ID if( !itemdb_isstackable2(data) && !item_data->unique_id ) sd->status.inventory[i].unique_id = itemdb_unique_id(0,0); #endif - log_pick_pc(sd, log_type, amount, &sd->status.inventory[i]); + logs->pick_pc(sd, log_type, amount, &sd->status.inventory[i],sd->inventory_data[i]); sd->weight += w; - clif_updatestatus(sd,SP_WEIGHT); + clif->updatestatus(sd,SP_WEIGHT); //Auto-equip if(data->flag.autoequip) pc_equipitem(sd, i, data->equip); @@ -3851,11 +3899,11 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l /* rental item check */ if( item_data->expire_time ) { if( time(NULL) > item_data->expire_time ) { - clif_rental_expired(sd->fd, i, sd->status.inventory[i].nameid); + clif->rental_expired(sd->fd, i, sd->status.inventory[i].nameid); pc_delitem(sd, i, sd->status.inventory[i].amount, 1, 0, LOG_TYPE_OTHER); } else { int seconds = (int)( item_data->expire_time - time(NULL) ); - clif_rental_time(sd->fd, sd->status.inventory[i].nameid, seconds); + clif->rental_time(sd->fd, sd->status.inventory[i].nameid, seconds); pc_inventory_rental_add(sd, seconds); } } @@ -3880,7 +3928,7 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reas if(sd->status.inventory[n].nameid==0 || amount <= 0 || sd->status.inventory[n].amount<amount || sd->inventory_data[n] == NULL) return 1; - log_pick_pc(sd, log_type, -amount, &sd->status.inventory[n]); + logs->pick_pc(sd, log_type, -amount, &sd->status.inventory[n],sd->inventory_data[n]); sd->status.inventory[n].amount -= amount; sd->weight -= sd->inventory_data[n]->weight*amount ; @@ -3891,9 +3939,9 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reas sd->inventory_data[n] = NULL; } if(!(type&1)) - clif_delitem(sd,n,amount,reason); + clif->delitem(sd,n,amount,reason); if(!(type&2)) - clif_updatestatus(sd,SP_WEIGHT); + clif->updatestatus(sd,SP_WEIGHT); return 0; } @@ -3924,13 +3972,13 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount) if( map[sd->bl.m].flag.nodrop ) { - clif_displaymessage (sd->fd, msg_txt(271)); + clif->message (sd->fd, msg_txt(271)); return 0; //Can't drop items in nodrop mapflag maps. } if( !pc_candrop(sd,&sd->status.inventory[n]) ) { - clif_displaymessage (sd->fd, msg_txt(263)); + clif->message (sd->fd, msg_txt(263)); return 0; } @@ -3938,7 +3986,7 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount) return 0; pc_delitem(sd, n, amount, 1, 0, LOG_TYPE_PICKDROP_PLAYER); - clif_dropitem(sd, n, amount); + clif->dropitem(sd, n, amount); return 1; } @@ -4002,13 +4050,13 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem) //This function takes care of giving the item to whoever should have it, considering party-share options. if ((flag = party_share_loot(p,sd,&fitem->item_data, fitem->first_get_charid))) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); return 1; } //Display pickup animation. pc_stop_attack(sd); - clif_takeitem(&sd->bl,&fitem->bl); + clif->takeitem(&sd->bl,&fitem->bl); map_clearflooritem(&fitem->bl); return 1; } @@ -4037,6 +4085,12 @@ int pc_isUseitem(struct map_session_data *sd,int n) if( !item->script ) //if it has no script, you can't really consume it! return 0; + if( (item->item_usage.flag&NOUSE_SITTING) && (pc_issit(sd) == 1) && (pc_get_group_level(sd) < item->item_usage.override) ) { + clif->msgtable(sd->fd,664); + //clif->colormes(sd->fd,COLOR_WHITE,msg_txt(1474)); + return 0; // You cannot use this item while sitting. + } + switch( nameid ) //@TODO, lot oh harcoded nameid here { case 605: // Anodyne @@ -4050,7 +4104,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) case 12212: // Giant Fly Wing if( map[sd->bl.m].flag.noteleport || map_flag_gvg(sd->bl.m) ) { - clif_skill_teleportmessage(sd,0); + clif->skill_teleportmessage(sd,0); return 0; } case 602: // ButterFly Wing @@ -4063,7 +4117,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) case 14591: // Siege Teleport Scroll if( sd->duel_group && !battle_config.duel_allow_teleport ) { - clif_displaymessage(sd->fd, msg_txt(663)); + clif->message(sd->fd, msg_txt(663)); return 0; } if( nameid != 601 && nameid != 12212 && map[sd->bl.m].flag.noreturn ) @@ -4133,16 +4187,6 @@ int pc_isUseitem(struct map_session_data *sd,int n) else if( itemdb_is_poison(nameid) && (sd->class_&MAPID_THIRDMASK) != MAPID_GUILLOTINE_CROSS ) return 0; - //added item_noequip.txt items check by Maya&[Lupus] - if ( - (!map_flag_vs(sd->bl.m) && item->flag.no_equip&1) || // Normal - (map[sd->bl.m].flag.pvp && item->flag.no_equip&2) || // PVP - (map_flag_gvg(sd->bl.m) && item->flag.no_equip&4) || // GVG - (map[sd->bl.m].flag.battleground && item->flag.no_equip&8) || // Battleground - (map[sd->bl.m].flag.restricted && item->flag.no_equip&(8*map[sd->bl.m].zone)) // Zone restriction - ) - return 0; - //Gender check if(item->sex != 2 && sd->status.sex != item->sex) return 0; @@ -4173,7 +4217,7 @@ int pc_isUseitem(struct map_session_data *sd,int n) //Dead Branch & Bloody Branch & Porings Box // FIXME: outdated, use constants or database if( nameid == 604 || nameid == 12103 || nameid == 12109 ) - log_branch(sd); + logs->branch(sd); return 1; } @@ -4187,11 +4231,19 @@ int pc_isUseitem(struct map_session_data *sd,int n) int pc_useitem(struct map_session_data *sd,int n) { unsigned int tick = gettick(); - int amount, i, nameid; + int amount, nameid, i; struct script_code *script; nullpo_ret(sd); + if( sd->npc_id ){ + /* TODO: add to clif->messages enum */ +#ifdef RENEWAL + clif->msg(sd, 0x783); // TODO look for the client date that has this message. +#endif + return 0; + } + if( sd->status.inventory[n].nameid <= 0 || sd->status.inventory[n].amount <= 0 ) return 0; @@ -4221,10 +4273,10 @@ int pc_useitem(struct map_session_data *sd,int n) (itemdb_iscashfood(nameid) && DIFF_TICK(sd->canusecashfood_tick, tick) > 0) ) return 0; - + /* Items with delayed consume are not meant to work while in mounts except reins of mount(12622) */ if( sd->inventory_data[n]->flag.delay_consume ) { - if( nameid != ITEMID_REINS_OF_MOUNT && sd->sc.option&OPTION_MOUNTING ) + if( nameid != ITEMID_REINS_OF_MOUNT && sd->sc.data[SC_ALL_RIDING] ) return 0; else if( pc_issit(sd) ) return 0; @@ -4237,6 +4289,7 @@ int pc_useitem(struct map_session_data *sd,int n) return 0; if( sd->inventory_data[n]->delay > 0 ) { + int i; ARR_FIND(0, MAX_ITEMDELAYS, i, sd->item_delay[i].nameid == nameid ); if( i == MAX_ITEMDELAYS ) /* item not found. try first empty now */ ARR_FIND(0, MAX_ITEMDELAYS, i, !sd->item_delay[i].nameid ); @@ -4253,7 +4306,7 @@ int pc_useitem(struct map_session_data *sd,int n) sprintf(e_msg,"Item Failed. [%s] is cooling down. wait %d seconds.", itemdb_jname(sd->status.inventory[n].nameid), e_tick+1); - clif_colormes(sd,COLOR_RED,e_msg); + clif->colormes(sd->fd,COLOR_RED,e_msg); return 0; // Delay has not expired yet } } else {// not yet used item (all slots are initially empty) @@ -4272,6 +4325,17 @@ int pc_useitem(struct map_session_data *sd,int n) } } + /* on restricted maps the item is consumed but the effect is not used */ + for(i = 0; i < map[sd->bl.m].zone->disabled_items_count; i++) { + if( map[sd->bl.m].zone->disabled_items[i] == nameid ) { + if( battle_config.item_restricted_consumption_type ) { + clif->useitemack(sd,n,sd->status.inventory[n].amount-1,true); + pc_delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); + } + return 0; + } + } + sd->itemid = sd->status.inventory[n].nameid; sd->itemindex = n; if(sd->catch_target_class != -1) //Abort pet catching. @@ -4281,13 +4345,13 @@ int pc_useitem(struct map_session_data *sd,int n) script = sd->inventory_data[n]->script; //Check if the item is to be consumed immediately [Skotlex] if( sd->inventory_data[n]->flag.delay_consume ) - clif_useitemack(sd,n,amount,true); + clif->useitemack(sd,n,amount,true); else { if( sd->status.inventory[n].expire_time == 0 ) { - clif_useitemack(sd,n,amount-1,true); + clif->useitemack(sd,n,amount-1,true); pc_delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration } else - clif_useitemack(sd,n,0,false); + clif->useitemack(sd,n,0,false); } if(sd->status.inventory[n].card[0]==CARD0_CREATE && pc_famerank(MakeDWord(sd->status.inventory[n].card[2],sd->status.inventory[n].card[3]), MAPID_ALCHEMIST)) @@ -4332,7 +4396,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) ) { // Check item trade restrictions [Skotlex] - clif_displaymessage (sd->fd, msg_txt(264)); + clif->message (sd->fd, msg_txt(264)); return 1; } @@ -4354,7 +4418,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun return 1; // no room sd->status.cart[i].amount+=amount; - clif_cart_additem(sd,i,amount,0); + clif->cart_additem(sd,i,amount,0); } else {// item not stackable or not present, add it @@ -4365,13 +4429,13 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun memcpy(&sd->status.cart[i],item_data,sizeof(sd->status.cart[0])); sd->status.cart[i].amount=amount; sd->cart_num++; - clif_cart_additem(sd,i,amount,0); + clif->cart_additem(sd,i,amount,0); } sd->status.cart[i].favorite = 0;/* clear */ - log_pick_pc(sd, log_type, amount, &sd->status.cart[i]); + logs->pick_pc(sd, log_type, amount, &sd->status.cart[i],data); sd->cart_weight += w; - clif_updatestatus(sd,SP_CARTINFO); + clif->updatestatus(sd,SP_CARTINFO); return 0; } @@ -4382,25 +4446,24 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun * 0 = success * 1 = fail *------------------------------------------*/ -int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type) -{ +int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type) { + struct item_data * data; nullpo_retr(1, sd); - if(sd->status.cart[n].nameid==0 || - sd->status.cart[n].amount<amount) + if( sd->status.cart[n].nameid == 0 || sd->status.cart[n].amount < amount || !(data = itemdb_exists(sd->status.cart[n].nameid)) ) return 1; - log_pick_pc(sd, log_type, -amount, &sd->status.cart[n]); + logs->pick_pc(sd, log_type, -amount, &sd->status.cart[n],data); sd->status.cart[n].amount -= amount; - sd->cart_weight -= itemdb_weight(sd->status.cart[n].nameid)*amount ; + sd->cart_weight -= data->weight*amount ; if(sd->status.cart[n].amount <= 0){ memset(&sd->status.cart[n],0,sizeof(sd->status.cart[0])); sd->cart_num--; } if(!type) { - clif_cart_delitem(sd,n,amount); - clif_updatestatus(sd,SP_CARTINFO); + clif->cart_delitem(sd,n,amount); + clif->updatestatus(sd,SP_CARTINFO); } return 0; @@ -4474,7 +4537,7 @@ int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount) if((flag = pc_additem(sd,item_data,amount,LOG_TYPE_NONE)) == 0) return pc_cart_delitem(sd,idx,amount,0,LOG_TYPE_NONE); - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); return 1; } @@ -4496,7 +4559,7 @@ int pc_show_steal(struct block_list *bl,va_list ap) sprintf(output,"%s stole an Unknown Item (id: %i).",sd->status.name, itemid); else sprintf(output,"%s stole %s.",sd->status.name,item->jname); - clif_displaymessage( ((struct map_session_data *)bl)->fd, output); + clif->message( ((struct map_session_data *)bl)->fd, output); return 0; } @@ -4513,6 +4576,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil struct status_data *sd_status, *md_status; struct mob_data *md; struct item tmp_item; + struct item_data *data = NULL; if(!sd || !bl || bl->type!=BL_MOB) return 0; @@ -4544,7 +4608,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil // Try dropping one item, in the order from first to last possible slot. // Droprate is affected by the skill success rate. for( i = 0; i < MAX_STEAL_DROP; i++ ) - if( md->db->dropitem[i].nameid > 0 && itemdb_exists(md->db->dropitem[i].nameid) && rnd() % 10000 < md->db->dropitem[i].p * rate/100. ) + if( md->db->dropitem[i].nameid > 0 && (data = itemdb_exists(md->db->dropitem[i].nameid)) && rnd() % 10000 < md->db->dropitem[i].p * rate/100. ) break; if( i == MAX_STEAL_DROP ) return 0; @@ -4553,14 +4617,14 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.nameid = itemid; tmp_item.amount = 1; - tmp_item.identify = itemdb_isidentified(itemid); + tmp_item.identify = itemdb_isidentified2(data); flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER); //TODO: Should we disable stealing when the item you stole couldn't be added to your inventory? Perhaps players will figure out a way to exploit this behaviour otherwise? md->state.steal_flag = UCHAR_MAX; //you can't steal from this mob any more if(flag) { //Failed to steal due to overweight - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); return 0; } @@ -4568,14 +4632,12 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil party_foreachsamemap(pc_show_steal,sd,AREA_SIZE,sd,tmp_item.nameid); //Logs items, Stolen from mobs [Lupus] - log_pick_mob(md, LOG_TYPE_STEAL, -1, &tmp_item); + logs->pick_mob(md, LOG_TYPE_STEAL, -1, &tmp_item, data); //A Rare Steal Global Announce by Lupus if(md->db->dropitem[i].p<=battle_config.rare_drop_announce) { - struct item_data *i_data; char message[128]; - i_data = itemdb_search(itemid); - sprintf (message, msg_txt(542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, i_data->jname, (float)md->db->dropitem[i].p/100); + sprintf (message, msg_txt(542), (sd->status.name != NULL)?sd->status.name :"GM", md->db->jname, data->jname, (float)md->db->dropitem[i].p/100); //MSG: "'%s' stole %s's %s (chance: %0.02f%%)" intif_broadcast(message,strlen(message)+1,0); } @@ -4674,7 +4736,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y struct status_change_entry *sce = sd->sc.data[SC_KNOWLEDGE]; if (sce->timer != INVALID_TIMER) delete_timer(sce->timer, status_change_timer); - sce->timer = add_timer(gettick() + skill_get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE); + sce->timer = add_timer(gettick() + skill->get_time(SG_KNOWLEDGE, sce->val1), status_change_timer, sd->bl.id, SC_KNOWLEDGE); } status_change_end(&sd->bl, SC_PROPERTYWALK, INVALID_TIMER); status_change_end(&sd->bl, SC_CLOAKING, INVALID_TIMER); @@ -4686,17 +4748,22 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y pc_unequipitem( sd , sd->equip_index[ i ] , 2 ); } if (battle_config.clear_unit_onwarp&BL_PC) - skill_clear_unitgroup(&sd->bl); + skill->clear_unitgroup(&sd->bl); party_send_dot_remove(sd); //minimap dot fix [Kevin] - guild_send_dot_remove(sd); + guild->send_dot_remove(sd); bg_send_dot_remove(sd); if (sd->regen.state.gc) sd->regen.state.gc = 0; // make sure vending is allowed here if (sd->state.vending && map[m].flag.novending) { - clif_displaymessage (sd->fd, msg_txt(276)); // "You can't open a shop on this map" - vending_closevending(sd); + clif->message (sd->fd, msg_txt(276)); // "You can't open a shop on this map" + vending->close(sd); } + + if( hChSys.local && map[sd->bl.m].channel && idb_exists(map[sd->bl.m].channel->users, sd->status.char_id) ) { + clif->chsys_left(map[sd->bl.m].channel,sd); + } + } if( m < 0 ) @@ -4740,13 +4807,13 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y } if (sd->state.vending && map_getcell(m,x,y,CELL_CHKNOVENDING)) { - clif_displaymessage (sd->fd, msg_txt(204)); // "You can't open a shop on this cell." - vending_closevending(sd); + clif->message (sd->fd, msg_txt(204)); // "You can't open a shop on this cell." + vending->close(sd); } if(sd->bl.prev != NULL){ unit_remove_map_pc(sd,clrtype); - clif_changemap(sd,map[m].index,x,y); // [MouseJstr] + clif->changemap(sd,map[m].index,x,y); // [MouseJstr] } else if(sd->state.active) //Tag player for rewarping after map-loading is done. [Skotlex] sd->state.rewarp = 1; @@ -4758,7 +4825,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y if( sd->status.guild_id > 0 && map[m].flag.gvg_castle ) { // Increased guild castle regen [Valaris] - struct guild_castle *gc = guild_mapindex2gc(sd->mapindex); + struct guild_castle *gc = guild->mapindex2gc(sd->mapindex); if(gc && gc->guild_id == sd->status.guild_id) sd->regen.state.gc = 1; } @@ -4771,7 +4838,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short mapindex, int x, int y sd->pd->ud.dir = sd->ud.dir; } - if( merc_is_hom_active(sd->hd) ) + if( homun_alive(sd->hd) ) { sd->hd->bl.m = m; sd->hd->bl.x = sd->hd->ud.to_x = x; @@ -4832,7 +4899,7 @@ int pc_memo(struct map_session_data* sd, int pos) // check mapflags if( sd->bl.m >= 0 && (map[sd->bl.m].flag.nomemo || map[sd->bl.m].flag.nowarpto) && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE) ) { - clif_skill_teleportmessage(sd, 1); // "Saved point cannot be memorized." + clif->skill_teleportmessage(sd, 1); // "Saved point cannot be memorized." return 0; } @@ -4843,11 +4910,11 @@ int pc_memo(struct map_session_data* sd, int pos) // check required skill level skill = pc_checkskill(sd, AL_WARP); if( skill < 1 ) { - clif_skill_memomessage(sd,2); // "You haven't learned Warp." + clif->skill_memomessage(sd,2); // "You haven't learned Warp." return 0; } if( skill < 2 || skill - 2 < pos ) { - clif_skill_memomessage(sd,1); // "Skill Level is not high enough." + clif->skill_memomessage(sd,1); // "Skill Level is not high enough." return 0; } @@ -4864,7 +4931,7 @@ int pc_memo(struct map_session_data* sd, int pos) sd->status.memo_point[pos].x = sd->bl.x; sd->status.memo_point[pos].y = sd->bl.y; - clif_skill_memomessage(sd, 0); + clif->skill_memomessage(sd, 0); return 1; } @@ -4875,28 +4942,43 @@ int pc_memo(struct map_session_data* sd, int pos) /*========================================== * Return player sd skill_lv learned for given skill *------------------------------------------*/ -int pc_checkskill(struct map_session_data *sd,uint16 skill_id) -{ +int pc_checkskill(struct map_session_data *sd,uint16 skill_id) { + uint16 index = 0; if(sd == NULL) return 0; - if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) - { + if( skill_id >= GD_SKILLBASE && skill_id < GD_MAX ) { struct guild *g; - if( sd->status.guild_id>0 && (g=guild_search(sd->status.guild_id))!=NULL) - return guild_checkskill(g,skill_id); + if( sd->status.guild_id>0 && (g=sd->guild)!=NULL) + return guild->checkskill(g,skill_id); return 0; - } - else if(skill_id >= ARRAYLENGTH(sd->status.skill) ) - { + } else if(!(index = skill->get_index(skill_id)) || index >= ARRAYLENGTH(sd->status.skill) ) { ShowError("pc_checkskill: Invalid skill id %d (char_id=%d).\n", skill_id, sd->status.char_id); return 0; } - if(sd->status.skill[skill_id].id == skill_id) - return (sd->status.skill[skill_id].lv); + if(sd->status.skill[index].id == skill_id) + return (sd->status.skill[index].lv); return 0; } +int pc_checkskill2(struct map_session_data *sd,uint16 index) { + if(sd == NULL) return 0; + if(index >= ARRAYLENGTH(sd->status.skill) ) { + ShowError("pc_checkskill: Invalid skill index %d (char_id=%d).\n", index, sd->status.char_id); + return 0; + } + if( skill_db[index].nameid >= GD_SKILLBASE && skill_db[index].nameid < GD_MAX ) { + struct guild *g; + + if( sd->status.guild_id>0 && (g=sd->guild)!=NULL) + return guild->checkskill(g,skill_db[index].nameid); + return 0; + } + if(sd->status.skill[index].id == skill_db[index].nameid) + return (sd->status.skill[index].lv); + + return 0; +} /*========================================== * Chk if we still have the correct weapon to continue the skill (actually status) @@ -4935,7 +5017,7 @@ int pc_checkallowskill(struct map_session_data *sd) if( scw_list[i] == SC_DANCING && !battle_config.dancing_weaponswitch_fix ) continue; if(sd->sc.data[scw_list[i]] && - !pc_check_weapontype(sd,skill_get_weapontype(status_sc2skill(scw_list[i])))) + !pc_check_weapontype(sd,skill->get_weapontype(status_sc2skill(scw_list[i])))) status_change_end(&sd->bl, scw_list[i], INVALID_TIMER); } @@ -5518,6 +5600,8 @@ int pc_stop_following (struct map_session_data *sd) sd->followtarget = -1; sd->ud.target_to = 0; + unit_stop_walking(&sd->bl, 1); + return 0; } @@ -5556,26 +5640,26 @@ int pc_checkbaselevelup(struct map_session_data *sd) { if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level status_calc_pet(sd->pd,0); - clif_updatestatus(sd,SP_STATUSPOINT); - clif_updatestatus(sd,SP_BASELEVEL); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_NEXTBASEEXP); + clif->updatestatus(sd,SP_STATUSPOINT); + clif->updatestatus(sd,SP_BASELEVEL); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_NEXTBASEEXP); status_calc_pc(sd,0); status_percent_heal(&sd->bl,100,100); if((sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE) { - sc_start(&sd->bl,status_skill2sc(PR_KYRIE),100,1,skill_get_time(PR_KYRIE,1)); - sc_start(&sd->bl,status_skill2sc(PR_IMPOSITIO),100,1,skill_get_time(PR_IMPOSITIO,1)); - sc_start(&sd->bl,status_skill2sc(PR_MAGNIFICAT),100,1,skill_get_time(PR_MAGNIFICAT,1)); - sc_start(&sd->bl,status_skill2sc(PR_GLORIA),100,1,skill_get_time(PR_GLORIA,1)); - sc_start(&sd->bl,status_skill2sc(PR_SUFFRAGIUM),100,1,skill_get_time(PR_SUFFRAGIUM,1)); + sc_start(&sd->bl,status_skill2sc(PR_KYRIE),100,1,skill->get_time(PR_KYRIE,1)); + sc_start(&sd->bl,status_skill2sc(PR_IMPOSITIO),100,1,skill->get_time(PR_IMPOSITIO,1)); + sc_start(&sd->bl,status_skill2sc(PR_MAGNIFICAT),100,1,skill->get_time(PR_MAGNIFICAT,1)); + sc_start(&sd->bl,status_skill2sc(PR_GLORIA),100,1,skill->get_time(PR_GLORIA,1)); + sc_start(&sd->bl,status_skill2sc(PR_SUFFRAGIUM),100,1,skill->get_time(PR_SUFFRAGIUM,1)); if (sd->state.snovice_dead_flag) sd->state.snovice_dead_flag = 0; //Reenable steelbody resurrection on dead. } else if( (sd->class_&MAPID_BASEMASK) == MAPID_TAEKWON ) { sc_start(&sd->bl,status_skill2sc(AL_INCAGI),100,10,600000); sc_start(&sd->bl,status_skill2sc(AL_BLESSING),100,10,600000); } - clif_misceffect(&sd->bl,0); + clif->misceffect(&sd->bl,0); npc_script_event(sd, NPCE_BASELVUP); //LORDALFA - LVLUPEVENT if(sd->status.party_id) @@ -5616,14 +5700,14 @@ int pc_checkjoblevelup(struct map_session_data *sd) } while ((next=pc_nextjobexp(sd)) > 0 && sd->status.job_exp >= next); - clif_updatestatus(sd,SP_JOBLEVEL); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); - clif_updatestatus(sd,SP_SKILLPOINT); + clif->updatestatus(sd,SP_JOBLEVEL); + clif->updatestatus(sd,SP_JOBEXP); + clif->updatestatus(sd,SP_NEXTJOBEXP); + clif->updatestatus(sd,SP_SKILLPOINT); status_calc_pc(sd,0); - clif_misceffect(&sd->bl,1); + clif->misceffect(&sd->bl,1); if (pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd)) - clif_status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL. + clif->status_change(&sd->bl,SI_DEVIL, 1, 0, 0, 0, 1); //Permanent blind effect from SG_DEVIL. npc_script_event(sd, NPCE_JOBLVUP); return 1; @@ -5673,7 +5757,7 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int return 0; // no exp on pvp maps if(sd->status.guild_id>0) - base_exp-=guild_payexp(sd,base_exp); + base_exp-=guild->payexp(sd,base_exp); if(src) pc_calcexp(sd, &base_exp, &job_exp, src); @@ -5710,7 +5794,7 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int else sd->status.base_exp += base_exp; pc_checkbaselevelup(sd); - clif_updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_BASEEXP); } if (job_exp) { @@ -5720,18 +5804,18 @@ int pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned int else sd->status.job_exp += job_exp; pc_checkjoblevelup(sd); - clif_updatestatus(sd,SP_JOBEXP); + clif->updatestatus(sd,SP_JOBEXP); } if(base_exp) - clif_displayexp(sd, base_exp, SP_BASEEXP, quest); + clif->displayexp(sd, base_exp, SP_BASEEXP, quest); if(job_exp) - clif_displayexp(sd, job_exp, SP_JOBEXP, quest); + clif->displayexp(sd, job_exp, SP_JOBEXP, quest); if(sd->state.showexp) { char output[256]; sprintf(output, "Experience Gained Base:%u (%.2f%%) Job:%u (%.2f%%)",base_exp,nextbp*(float)100,job_exp,nextjp*(float)100); - clif_disp_onlyself(sd,output,strlen(output)); + clif->disp_onlyself(sd,output,strlen(output)); } return 1; @@ -5891,7 +5975,7 @@ int pc_statusup(struct map_session_data* sd, int type) 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); + clif->statusupack(sd,type,0,0); return 1; } @@ -5899,7 +5983,7 @@ int pc_statusup(struct map_session_data* sd, int type) max = pc_maxparameter(sd); if( pc_getstat(sd,type) >= max ) { - clif_statusupack(sd,type,0,0); + clif->statusupack(sd,type,0,0); return 1; } @@ -5911,15 +5995,15 @@ int pc_statusup(struct map_session_data* sd, int type) // 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 + clif->statusupack(sd,type,1,val); // required if( val > 255 ) - clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value + clif->updatestatus(sd,type); // send after the 'ack' to override the truncated value return 0; } @@ -5937,7 +6021,7 @@ int pc_statusup2(struct map_session_data* sd, int type, int val) if( type < SP_STR || type > SP_LUK ) { - clif_statusupack(sd,type,0,0); + clif->statusupack(sd,type,0,0); return 1; } @@ -5951,12 +6035,12 @@ int pc_statusup2(struct map_session_data* sd, int type, int val) // 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 stat value - clif_statusupack(sd,type,1,val); // required + clif->statusupack(sd,type,1,val); // required if( val > 255 ) - clif_updatestatus(sd,type); // send after the 'ack' to override the truncated value + clif->updatestatus(sd,type); // send after the 'ack' to override the truncated value return 0; } @@ -5965,45 +6049,43 @@ int pc_statusup2(struct map_session_data* sd, int type, int val) * Update skill_lv for player sd * Skill point allocation *------------------------------------------*/ -int pc_skillup(struct map_session_data *sd,uint16 skill_id) -{ +int pc_skillup(struct map_session_data *sd,uint16 skill_id) { + uint16 index = 0; nullpo_ret(sd); - if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL ) - { - guild_skillup(sd, skill_id); + if( skill_id >= GD_SKILLBASE && skill_id < GD_SKILLBASE+MAX_GUILDSKILL ) { + guild->skillup(sd, skill_id); return 0; } - if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd ) - { - merc_hom_skillup(sd->hd, skill_id); + if( skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL && sd->hd ) { + homun->skillup(sd->hd, skill_id); return 0; } - if(skill_id >= MAX_SKILL ) + if( !(index = skill->get_index(skill_id)) ) return 0; if( sd->status.skill_point > 0 && - sd->status.skill[skill_id].id && - sd->status.skill[skill_id].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] - sd->status.skill[skill_id].lv < skill_tree_get_max(skill_id, sd->status.class_) ) + sd->status.skill[index].id && + sd->status.skill[index].flag == SKILL_FLAG_PERMANENT && //Don't allow raising while you have granted skills. [Skotlex] + sd->status.skill[index].lv < skill->tree_get_max(skill_id, sd->status.class_) ) { - sd->status.skill[skill_id].lv++; + sd->status.skill[index].lv++; sd->status.skill_point--; - if( !skill_get_inf(skill_id) ) + if( !skill_db[index].inf ) status_calc_pc(sd,0); // Only recalculate for passive skills. else if( sd->status.skill_point == 0 && (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) pc_calc_skilltree(sd); // Required to grant all TK Ranger skills. else pc_check_skilltree(sd, skill_id); // Check if a new skill can Lvlup - clif_skillup(sd,skill_id); - clif_updatestatus(sd,SP_SKILLPOINT); + clif->skillup(sd,skill_id); + clif->updatestatus(sd,SP_SKILLPOINT); if( skill_id == GN_REMODELING_CART ) /* cart weight info was updated by status_calc_pc */ - clif_updatestatus(sd,SP_CARTINFO); + clif->updatestatus(sd,SP_CARTINFO); if (!pc_has_permission(sd, PC_PERM_ALL_SKILL)) // may skill everything at any time anyways, and this would cause a huge slowdown - clif_skillinfoblock(sd); + clif->skillinfoblock(sd); } return 0; @@ -6019,7 +6101,7 @@ int pc_allskillup(struct map_session_data *sd) nullpo_ret(sd); for(i=0;i<MAX_SKILL;i++){ - if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { + if (sd->status.skill[i].flag != SKILL_FLAG_PERMANENT && sd->status.skill[i].flag != SKILL_FLAG_PERM_GRANTED && sd->status.skill[i].flag != SKILL_FLAG_PLAGIARIZED) { sd->status.skill[i].lv = (sd->status.skill[i].flag == SKILL_FLAG_TEMPORARY) ? 0 : sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0; sd->status.skill[i].flag = SKILL_FLAG_PERMANENT; if (sd->status.skill[i].lv == 0) @@ -6027,25 +6109,25 @@ int pc_allskillup(struct map_session_data *sd) } } - if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) - { //Get ALL skills except npc/guild ones. [Skotlex] + if (pc_has_permission(sd, PC_PERM_ALL_SKILL)) { //Get ALL skills except npc/guild ones. [Skotlex] //and except SG_DEVIL [Komurka] and MO_TRIPLEATTACK and RG_SNATCHER [ultramage] for(i=0;i<MAX_SKILL;i++){ - switch( i ) { + switch( skill_db[i].nameid ) { case SG_DEVIL: case MO_TRIPLEATTACK: case RG_SNATCHER: continue; default: - if( !(skill_get_inf2(i)&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) ) - if ( ( sd->status.skill[i].lv = skill_get_max(i) ) )//Nonexistant skills should return a max of 0 anyway. - sd->status.skill[i].id = i; + if( !(skill_db[i].inf2&(INF2_NPC_SKILL|INF2_GUILD_SKILL)) ) + if ( ( sd->status.skill[i].lv = skill_db[i].max ) )//Nonexistant skills should return a max of 0 anyway. + sd->status.skill[i].id = skill_db[i].nameid; } } } else { int inf2; for(i=0;i < MAX_SKILL_TREE && (id=skill_tree[pc_class2idx(sd->status.class_)][i].id)>0;i++){ - inf2 = skill_get_inf2(id); + int idx = skill_tree[pc_class2idx(sd->status.class_)][i].idx; + inf2 = skill_db[idx].inf2; if ( (inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn) || (inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL)) || @@ -6053,14 +6135,14 @@ int pc_allskillup(struct map_session_data *sd) ) continue; //Cannot be learned normally. - sd->status.skill[id].id = id; - sd->status.skill[id].lv = skill_tree_get_max(id, sd->status.class_); // celest + sd->status.skill[idx].id = id; + sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest } } status_calc_pc(sd,0); //Required because if you could level up all skills previously, //the update will not be sent as only the lv variable changes. - clif_skillinfoblock(sd); + clif->skillinfoblock(sd); return 0; } @@ -6115,28 +6197,28 @@ int pc_resetlvl(struct map_session_data* sd,int type) sd->status.job_exp=0; } - clif_updatestatus(sd,SP_STATUSPOINT); - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); - clif_updatestatus(sd,SP_BASELEVEL); - clif_updatestatus(sd,SP_JOBLEVEL); - clif_updatestatus(sd,SP_STATUSPOINT); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTBASEEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); - clif_updatestatus(sd,SP_SKILLPOINT); - - clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris - clif_updatestatus(sd,SP_UAGI); - clif_updatestatus(sd,SP_UVIT); - clif_updatestatus(sd,SP_UINT); - clif_updatestatus(sd,SP_UDEX); - clif_updatestatus(sd,SP_ULUK); // End Addition + clif->updatestatus(sd,SP_STATUSPOINT); + clif->updatestatus(sd,SP_STR); + clif->updatestatus(sd,SP_AGI); + clif->updatestatus(sd,SP_VIT); + clif->updatestatus(sd,SP_INT); + clif->updatestatus(sd,SP_DEX); + clif->updatestatus(sd,SP_LUK); + clif->updatestatus(sd,SP_BASELEVEL); + clif->updatestatus(sd,SP_JOBLEVEL); + clif->updatestatus(sd,SP_STATUSPOINT); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_JOBEXP); + clif->updatestatus(sd,SP_NEXTBASEEXP); + clif->updatestatus(sd,SP_NEXTJOBEXP); + clif->updatestatus(sd,SP_SKILLPOINT); + + clif->updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris + clif->updatestatus(sd,SP_UAGI); + clif->updatestatus(sd,SP_UVIT); + clif->updatestatus(sd,SP_UINT); + clif->updatestatus(sd,SP_UDEX); + clif->updatestatus(sd,SP_ULUK); // End Addition for(i=0;i<EQI_MAX;i++) { // unequip items that can't be equipped by base 1 [Valaris] if(sd->equip_index[i] >= 0) @@ -6148,7 +6230,7 @@ int pc_resetlvl(struct map_session_data* sd,int type) party_send_levelup(sd); status_calc_pc(sd,0); - clif_skillinfoblock(sd); + clif->skillinfoblock(sd); return 0; } @@ -6190,21 +6272,21 @@ int pc_resetstate(struct map_session_data* sd) pc_setstat(sd, SP_DEX, 1); pc_setstat(sd, SP_LUK, 1); - clif_updatestatus(sd,SP_STR); - clif_updatestatus(sd,SP_AGI); - clif_updatestatus(sd,SP_VIT); - clif_updatestatus(sd,SP_INT); - clif_updatestatus(sd,SP_DEX); - clif_updatestatus(sd,SP_LUK); + clif->updatestatus(sd,SP_STR); + clif->updatestatus(sd,SP_AGI); + clif->updatestatus(sd,SP_VIT); + clif->updatestatus(sd,SP_INT); + clif->updatestatus(sd,SP_DEX); + clif->updatestatus(sd,SP_LUK); - clif_updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris - clif_updatestatus(sd,SP_UAGI); - clif_updatestatus(sd,SP_UVIT); - clif_updatestatus(sd,SP_UINT); - clif_updatestatus(sd,SP_UDEX); - clif_updatestatus(sd,SP_ULUK); // End Addition + clif->updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris + clif->updatestatus(sd,SP_UAGI); + clif->updatestatus(sd,SP_UVIT); + clif->updatestatus(sd,SP_UINT); + clif->updatestatus(sd,SP_UDEX); + clif->updatestatus(sd,SP_ULUK); // End Addition - clif_updatestatus(sd,SP_STATUSPOINT); + clif->updatestatus(sd,SP_STATUSPOINT); if( sd->mission_mobid ) { //bugreport:2200 sd->mission_mobid = 0; @@ -6239,10 +6321,10 @@ int pc_resetskill(struct map_session_data* sd, int flag) if( (sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON) ) return 0; - if( pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd) ) - clif_status_load(&sd->bl, SI_DEVIL, 0); //Remove perma blindness due to skill-reset. [Skotlex] + if( pc_checkskill(sd, SG_DEVIL) && !pc_nextjobexp(sd) ) //Remove perma blindness due to skill-reset. [Skotlex] + clif->sc_end(&sd->bl, sd->bl.id, SELF, SI_DEVIL); i = sd->sc.option; - if( i&OPTION_RIDING && pc_checkskill(sd, KN_RIDING) ) + if( i&OPTION_RIDING && (!pc_checkskill(sd, KN_RIDING) || (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) ) i &= ~OPTION_RIDING; if( i&OPTION_FALCON && pc_checkskill(sd, HT_FALCON) ) i &= ~OPTION_FALCON; @@ -6254,8 +6336,6 @@ int pc_resetskill(struct map_session_data* sd, int flag) i &= ~OPTION_WUGRIDER; if( i&OPTION_MADOGEAR && ( sd->class_&MAPID_THIRDMASK ) == MAPID_MECHANIC ) i &= ~OPTION_MADOGEAR; - if( i&OPTION_MOUNTING ) - i &= ~OPTION_MOUNTING; #ifndef NEW_CARTS if( i&OPTION_CART && pc_checkskill(sd, MC_PUSHCART) ) i &= ~OPTION_CART; @@ -6266,39 +6346,42 @@ int pc_resetskill(struct map_session_data* sd, int flag) if( i != sd->sc.option ) pc_setoption(sd, i); - if( merc_is_hom_active(sd->hd) && pc_checkskill(sd, AM_CALLHOMUN) ) - merc_hom_vaporize(sd, 0); + if( homun_alive(sd->hd) && pc_checkskill(sd, AM_CALLHOMUN) ) + homun->vaporize(sd, 0); } - for( i = 1; i < MAX_SKILL; i++ ) - { + for( i = 1; i < MAX_SKILL; i++ ) { + uint16 skill_id = 0; lv = sd->status.skill[i].lv; if (lv < 1) continue; - inf2 = skill_get_inf2(i); + inf2 = skill_db[i].inf2; if( inf2&(INF2_WEDDING_SKILL|INF2_SPIRIT_SKILL) ) //Avoid reseting wedding/linker skills. continue; - + + skill_id = skill_db[i].nameid; + // Don't reset trick dead if not a novice/baby - if( i == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) - { + if( skill_id == NV_TRICKDEAD && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) { sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; continue; } // do not reset basic skill - if( i == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) + if( skill_id == NV_BASIC && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE ) continue; + if( sd->status.skill[i].flag == SKILL_FLAG_PERM_GRANTED ) + continue; + if( flag&4 && !skill_ischangesex(i) ) continue; - if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn ) - { //Only handle quest skills in a special way when you can't learn them manually - if( battle_config.quest_skill_reset && !(flag&2) ) - { //Wipe them + if( inf2&INF2_QUEST_SKILL && !battle_config.quest_skill_learn ) { + //Only handle quest skills in a special way when you can't learn them manually + if( battle_config.quest_skill_reset && !(flag&2) ) { //Wipe them sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; } @@ -6307,11 +6390,10 @@ int pc_resetskill(struct map_session_data* sd, int flag) if( sd->status.skill[i].flag == SKILL_FLAG_PERMANENT ) skill_point += lv; else - if( sd->status.skill[i].flag >= SKILL_FLAG_REPLACED_LV_0 ) + if( sd->status.skill[i].flag == SKILL_FLAG_REPLACED_LV_0 ) skill_point += (sd->status.skill[i].flag - SKILL_FLAG_REPLACED_LV_0); - if( !(flag&2) ) - {// reset + if( !(flag&2) ) {// reset sd->status.skill[i].lv = 0; sd->status.skill[i].flag = 0; } @@ -6321,10 +6403,9 @@ int pc_resetskill(struct map_session_data* sd, int flag) sd->status.skill_point += skill_point; - if( flag&1 ) - { - clif_updatestatus(sd,SP_SKILLPOINT); - clif_skillinfoblock(sd); + if( flag&1 ) { + clif->updatestatus(sd,SP_SKILLPOINT); + clif->skillinfoblock(sd); status_calc_pc(sd,0); } @@ -6418,7 +6499,7 @@ void pc_respawn(struct map_session_data* sd, clr_type clrtype) pc_setstand(sd); pc_setrestartvalue(sd,3); if( pc_setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, clrtype) ) - clif_resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. + clif->resurrection(&sd->bl, 1); //If warping fails, send a normal stand up packet. } static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) @@ -6438,21 +6519,20 @@ static int pc_respawn_timer(int tid, unsigned int tick, int id, intptr_t data) *------------------------------------------*/ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int hp, unsigned int sp) { - if (sp) clif_updatestatus(sd,SP_SP); - if (hp) clif_updatestatus(sd,SP_HP); + if (sp) clif->updatestatus(sd,SP_SP); + if (hp) clif->updatestatus(sd,SP_HP); else return; if( !src || src == &sd->bl ) return; - if( pc_issit(sd) ) - { + if( pc_issit(sd) ) { pc_setstand(sd); - skill_sit(sd,0); + skill->sit(sd,0); } if( sd->progressbar.npc_id ) - clif_progressbar_abort(sd); + clif->progressbar_abort(sd); if( sd->status.pet_id > 0 && sd->pd && battle_config.pet_damage_support ) pet_target_check(sd,src,1); @@ -6485,7 +6565,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) pet_set_intimate(pd, pd->pet.intimate - pd->petDB->die); if( pd->pet.intimate < 0 ) pd->pet.intimate = 0; - clif_send_petdata(sd,sd->pd,1,pd->pet.intimate); + clif->send_petdata(sd,sd->pd,1,pd->pet.intimate); } if( sd->pd->target_id ) // Unlock all targets... pet_unlocktarget(sd->pd); @@ -6493,7 +6573,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if (sd->status.hom_id > 0){ if(battle_config.homunculus_auto_vapor && sd->hd && !sd->hd->sc.data[SC_LIGHT_OF_REGENE]) - merc_hom_vaporize(sd, 0); + homun->vaporize(sd, 0); } if( sd->md ) @@ -6523,7 +6603,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if (sd->npc_id) { if (sd->state.using_fake_npc) { - clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); + clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); sd->state.using_fake_npc = 0; } if (sd->state.menu_or_input) @@ -6540,7 +6620,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) /* e.g. not killed thru pc_damage */ if( pc_issit(sd) ) { - clif_status_load(&sd->bl,SI_SIT,0); + clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT); } pc_setdead(sd); @@ -6569,17 +6649,17 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) (unsigned int)md->level < pc_maxbaselv(sd) && !md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex] ) { // monster level up [Valaris] - clif_misceffect(&md->bl,0); + clif->misceffect(&md->bl,0); md->level++; status_calc_mob(md, 0); status_percent_heal(src,10,0); if( battle_config.show_mob_info&4 ) {// update name with new level - clif_charnameack(0, &md->bl); + clif->charnameack(0, &md->bl); } } - src = battle_get_master(src); // Maybe Player Summon + src = battle->get_master(src); // Maybe Player Summon } break; case BL_PET: //Pass on to master... @@ -6652,10 +6732,10 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) sd->state.snovice_dead_flag = 1; pc_setstand(sd); status_percent_heal(&sd->bl, 100, 100); - clif_resurrection(&sd->bl, 1); + clif->resurrection(&sd->bl, 1); if(battle_config.pc_invincible_time) pc_setinvincibletimer(sd, battle_config.pc_invincible_time); - sc_start(&sd->bl,status_skill2sc(MO_STEELBODY),100,1,skill_get_time(MO_STEELBODY,1)); + sc_start(&sd->bl,status_skill2sc(MO_STEELBODY),100,1,skill->get_time(MO_STEELBODY,1)); if(map_flag_gvg(sd->bl.m)) pc_respawn_timer(INVALID_TIMER, gettick(), sd->bl.id, 0); return 0; @@ -6682,7 +6762,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if (battle_config.pk_mode && src && src->type==BL_PC) base_penalty*=2; sd->status.base_exp -= min(sd->status.base_exp, base_penalty); - clif_updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_BASEEXP); } } if(battle_config.death_penalty_job > 0) @@ -6700,7 +6780,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if (battle_config.pk_mode && src && src->type==BL_PC) base_penalty*=2; sd->status.job_exp -= min(sd->status.job_exp, base_penalty); - clif_updatestatus(sd,SP_JOBEXP); + clif->updatestatus(sd,SP_JOBEXP); } } if(battle_config.zeny_penalty > 0 && !map[sd->bl.m].flag.nozenypenalty) @@ -6723,11 +6803,11 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) int eq_num=0,eq_n[MAX_INVENTORY]; memset(eq_n,0,sizeof(eq_n)); for(i=0;i<MAX_INVENTORY;i++){ - int k; if( (type == 1 && !sd->status.inventory[i].equip) || (type == 2 && sd->status.inventory[i].equip) || type == 3) { + int k; ARR_FIND( 0, MAX_INVENTORY, k, eq_n[k] <= 0 ); if( k < MAX_INVENTORY ) eq_n[k] = i; @@ -6802,18 +6882,18 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) } void pc_revive(struct map_session_data *sd,unsigned int hp, unsigned int sp) { - if(hp) clif_updatestatus(sd,SP_HP); - if(sp) clif_updatestatus(sd,SP_SP); + if(hp) clif->updatestatus(sd,SP_HP); + if(sp) clif->updatestatus(sd,SP_SP); pc_setstand(sd); if(battle_config.pc_invincible_time > 0) pc_setinvincibletimer(sd, battle_config.pc_invincible_time); if( sd->state.gmaster_flag ) { - guild_guildaura_refresh(sd,GD_LEADERSHIP,guild_checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); - guild_guildaura_refresh(sd,GD_GLORYWOUNDS,guild_checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); - guild_guildaura_refresh(sd,GD_SOULCOLD,guild_checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); - guild_guildaura_refresh(sd,GD_HAWKEYES,guild_checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); + guild->aura_refresh(sd,GD_LEADERSHIP,guild->checkskill(sd->state.gmaster_flag,GD_LEADERSHIP)); + guild->aura_refresh(sd,GD_GLORYWOUNDS,guild->checkskill(sd->state.gmaster_flag,GD_GLORYWOUNDS)); + guild->aura_refresh(sd,GD_SOULCOLD,guild->checkskill(sd->state.gmaster_flag,GD_SOULCOLD)); + guild->aura_refresh(sd,GD_HAWKEYES,guild->checkskill(sd->state.gmaster_flag,GD_HAWKEYES)); } } // script @@ -6828,39 +6908,141 @@ int pc_readparam(struct map_session_data* sd,int type) nullpo_ret(sd); switch(type) { - case SP_SKILLPOINT: val = sd->status.skill_point; break; - case SP_STATUSPOINT: val = sd->status.status_point; break; - case SP_ZENY: val = sd->status.zeny; break; - case SP_BASELEVEL: val = sd->status.base_level; break; - case SP_JOBLEVEL: val = sd->status.job_level; break; - case SP_CLASS: val = sd->status.class_; break; - case SP_BASEJOB: val = pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type. - case SP_UPPER: val = sd->class_&JOBL_UPPER?1:(sd->class_&JOBL_BABY?2:0); break; - case SP_BASECLASS: val = pc_mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex] - case SP_SEX: val = sd->status.sex; break; - case SP_WEIGHT: val = sd->weight; break; - case SP_MAXWEIGHT: val = sd->max_weight; break; - case SP_BASEEXP: val = sd->status.base_exp; break; - case SP_JOBEXP: val = sd->status.job_exp; break; - case SP_NEXTBASEEXP: val = pc_nextbaseexp(sd); break; - case SP_NEXTJOBEXP: val = pc_nextjobexp(sd); break; - case SP_HP: val = sd->battle_status.hp; break; - case SP_MAXHP: val = sd->battle_status.max_hp; break; - case SP_SP: val = sd->battle_status.sp; break; - case SP_MAXSP: val = sd->battle_status.max_sp; break; - case SP_STR: val = sd->status.str; break; - case SP_AGI: val = sd->status.agi; break; - case SP_VIT: val = sd->status.vit; break; - case SP_INT: val = sd->status.int_; break; - case SP_DEX: val = sd->status.dex; break; - case SP_LUK: val = sd->status.luk; break; - case SP_KARMA: val = sd->status.karma; break; - case SP_MANNER: val = sd->status.manner; break; - case SP_FAME: val = sd->status.fame; break; - case SP_KILLERRID: val = sd->killerrid; break; - case SP_KILLEDRID: val = sd->killedrid; break; - case SP_CRITICAL: val = sd->battle_status.cri/10; break; - case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break; + case SP_SKILLPOINT: val = sd->status.skill_point; break; + case SP_STATUSPOINT: val = sd->status.status_point; break; + case SP_ZENY: val = sd->status.zeny; break; + case SP_BASELEVEL: val = sd->status.base_level; break; + case SP_JOBLEVEL: val = sd->status.job_level; break; + case SP_CLASS: val = sd->status.class_; break; + case SP_BASEJOB: val = pc_mapid2jobid(sd->class_&MAPID_UPPERMASK, sd->status.sex); break; //Base job, extracting upper type. + case SP_UPPER: val = sd->class_&JOBL_UPPER?1:(sd->class_&JOBL_BABY?2:0); break; + case SP_BASECLASS: val = pc_mapid2jobid(sd->class_&MAPID_BASEMASK, sd->status.sex); break; //Extract base class tree. [Skotlex] + case SP_SEX: val = sd->status.sex; break; + case SP_WEIGHT: val = sd->weight; break; + case SP_MAXWEIGHT: val = sd->max_weight; break; + case SP_BASEEXP: val = sd->status.base_exp; break; + case SP_JOBEXP: val = sd->status.job_exp; break; + case SP_NEXTBASEEXP: val = pc_nextbaseexp(sd); break; + case SP_NEXTJOBEXP: val = pc_nextjobexp(sd); break; + case SP_HP: val = sd->battle_status.hp; break; + case SP_MAXHP: val = sd->battle_status.max_hp; break; + case SP_SP: val = sd->battle_status.sp; break; + case SP_MAXSP: val = sd->battle_status.max_sp; break; + case SP_STR: val = sd->status.str; break; + case SP_AGI: val = sd->status.agi; break; + case SP_VIT: val = sd->status.vit; break; + case SP_INT: val = sd->status.int_; break; + case SP_DEX: val = sd->status.dex; break; + case SP_LUK: val = sd->status.luk; break; + case SP_KARMA: val = sd->status.karma; break; + case SP_MANNER: val = sd->status.manner; break; + case SP_FAME: val = sd->status.fame; break; + case SP_KILLERRID: val = sd->killerrid; break; + case SP_KILLEDRID: val = sd->killedrid; break; + case SP_SLOTCHANGE: val = sd->status.slotchange; break; + case SP_CHARRENAME: val = sd->status.rename; break; + case SP_CRITICAL: val = sd->battle_status.cri/10; break; + case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break; + case SP_BASE_ATK: val = sd->battle_status.batk; break; + case SP_DEF1: val = sd->battle_status.def; break; + case SP_DEF2: val = sd->battle_status.def2; break; + case SP_MDEF1: val = sd->battle_status.mdef; break; + case SP_MDEF2: val = sd->battle_status.mdef2; break; + case SP_HIT: val = sd->battle_status.hit; break; + case SP_FLEE1: val = sd->battle_status.flee; break; + case SP_FLEE2: val = sd->battle_status.flee2; break; + case SP_DEFELE: val = sd->battle_status.def_ele; break; +#ifndef RENEWAL_CAST + case SP_VARCASTRATE: +#endif + case SP_CASTRATE: + val = sd->castrate+=val; + break; + case SP_MAXHPRATE: val = sd->hprate; break; + case SP_MAXSPRATE: val = sd->sprate; break; + case SP_SPRATE: val = sd->dsprate; break; + case SP_SPEED_RATE: val = sd->bonus.speed_rate; break; + case SP_SPEED_ADDRATE: val = sd->bonus.speed_add_rate; break; + case SP_ASPD_RATE: +#ifndef RENEWAL_ASPD + val = sd->battle_status.aspd_rate; +#else + val = sd->battle_status.aspd_rate2; +#endif + break; + case SP_HP_RECOV_RATE: val = sd->hprecov_rate; break; + case SP_SP_RECOV_RATE: val = sd->sprecov_rate; break; + case SP_CRITICAL_DEF: val = sd->bonus.critical_def; break; + case SP_NEAR_ATK_DEF: val = sd->bonus.near_attack_def_rate; break; + case SP_LONG_ATK_DEF: val = sd->bonus.long_attack_def_rate; break; + case SP_DOUBLE_RATE: val = sd->bonus.double_rate; break; + case SP_DOUBLE_ADD_RATE: val = sd->bonus.double_add_rate; break; + case SP_MATK_RATE: val = sd->matk_rate; break; + case SP_ATK_RATE: val = sd->bonus.atk_rate; break; + case SP_MAGIC_ATK_DEF: val = sd->bonus.magic_def_rate; break; + case SP_MISC_ATK_DEF: val = sd->bonus.misc_def_rate; break; + case SP_PERFECT_HIT_RATE:val = sd->bonus.perfect_hit; break; + case SP_PERFECT_HIT_ADD_RATE: val = sd->bonus.perfect_hit_add; break; + case SP_CRITICAL_RATE: val = sd->critical_rate; break; + case SP_HIT_RATE: val = sd->hit_rate; break; + case SP_FLEE_RATE: val = sd->flee_rate; break; + case SP_FLEE2_RATE: val = sd->flee2_rate; break; + case SP_DEF_RATE: val = sd->def_rate; break; + case SP_DEF2_RATE: val = sd->def2_rate; break; + case SP_MDEF_RATE: val = sd->mdef_rate; break; + case SP_MDEF2_RATE: val = sd->mdef2_rate; break; + case SP_RESTART_FULL_RECOVER: val = sd->special_state.restart_full_recover?1:0; break; + case SP_NO_CASTCANCEL: val = sd->special_state.no_castcancel?1:0; break; + case SP_NO_CASTCANCEL2: val = sd->special_state.no_castcancel2?1:0; break; + case SP_NO_SIZEFIX: val = sd->special_state.no_sizefix?1:0; break; + case SP_NO_MAGIC_DAMAGE: val = sd->special_state.no_magic_damage; break; + case SP_NO_WEAPON_DAMAGE:val = sd->special_state.no_weapon_damage; break; + case SP_NO_MISC_DAMAGE: val = sd->special_state.no_misc_damage; break; + case SP_NO_GEMSTONE: val = sd->special_state.no_gemstone?1:0; break; + case SP_INTRAVISION: val = sd->special_state.intravision?1:0; break; + case SP_NO_KNOCKBACK: val = sd->special_state.no_knockback?1:0; break; + case SP_SPLASH_RANGE: val = sd->bonus.splash_range; break; + case SP_SPLASH_ADD_RANGE:val = sd->bonus.splash_add_range; break; + case SP_SHORT_WEAPON_DAMAGE_RETURN: val = sd->bonus.short_weapon_damage_return; break; + case SP_LONG_WEAPON_DAMAGE_RETURN: val = sd->bonus.long_weapon_damage_return; break; + case SP_MAGIC_DAMAGE_RETURN: val = sd->bonus.magic_damage_return; break; + case SP_PERFECT_HIDE: val = sd->special_state.perfect_hiding?1:0; break; + case SP_UNBREAKABLE: val = sd->bonus.unbreakable; break; + case SP_UNBREAKABLE_WEAPON: val = (sd->bonus.unbreakable_equip&EQP_WEAPON)?1:0; break; + case SP_UNBREAKABLE_ARMOR: val = (sd->bonus.unbreakable_equip&EQP_ARMOR)?1:0; break; + case SP_UNBREAKABLE_HELM: val = (sd->bonus.unbreakable_equip&EQP_HELM)?1:0; break; + case SP_UNBREAKABLE_SHIELD: val = (sd->bonus.unbreakable_equip&EQP_SHIELD)?1:0; break; + case SP_UNBREAKABLE_GARMENT: val = (sd->bonus.unbreakable_equip&EQP_GARMENT)?1:0; break; + case SP_UNBREAKABLE_SHOES: val = (sd->bonus.unbreakable_equip&EQP_SHOES)?1:0; break; + case SP_CLASSCHANGE: val = sd->bonus.classchange; break; + case SP_LONG_ATK_RATE: val = sd->bonus.long_attack_atk_rate; break; + case SP_BREAK_WEAPON_RATE: val = sd->bonus.break_weapon_rate; break; + case SP_BREAK_ARMOR_RATE: val = sd->bonus.break_armor_rate; break; + case SP_ADD_STEAL_RATE: val = sd->bonus.add_steal_rate; break; + case SP_DELAYRATE: val = sd->delayrate; break; + case SP_CRIT_ATK_RATE: val = sd->bonus.crit_atk_rate; break; + case SP_UNSTRIPABLE_WEAPON: val = (sd->bonus.unstripable_equip&EQP_WEAPON)?1:0; break; + case SP_UNSTRIPABLE: + case SP_UNSTRIPABLE_ARMOR: + val = (sd->bonus.unstripable_equip&EQP_ARMOR)?1:0; + break; + case SP_UNSTRIPABLE_HELM: val = (sd->bonus.unstripable_equip&EQP_HELM)?1:0; break; + case SP_UNSTRIPABLE_SHIELD: val = (sd->bonus.unstripable_equip&EQP_SHIELD)?1:0; break; + case SP_SP_GAIN_VALUE: val = sd->bonus.sp_gain_value; break; + case SP_HP_GAIN_VALUE: val = sd->bonus.hp_gain_value; break; + case SP_MAGIC_SP_GAIN_VALUE: val = sd->bonus.magic_sp_gain_value; break; + case SP_MAGIC_HP_GAIN_VALUE: val = sd->bonus.magic_hp_gain_value; break; + case SP_ADD_HEAL_RATE: val = sd->bonus.add_heal_rate; break; + case SP_ADD_HEAL2_RATE: val = sd->bonus.add_heal2_rate; break; + case SP_ADD_ITEM_HEAL_RATE: val = sd->bonus.itemhealrate2; break; + case SP_EMATK: val = sd->bonus.ematk; break; + case SP_FIXCASTRATE: val = sd->bonus.fixcastrate; break; + case SP_ADD_FIXEDCAST: val = sd->bonus.add_fixcast; break; +#ifdef RENEWAL_CAST + case SP_VARCASTRATE: val = sd->bonus.varcastrate; break; + case SP_ADD_VARIABLECAST:val = sd->bonus.add_varcast; break; +#endif + } return val; @@ -6887,10 +7069,10 @@ int pc_setparam(struct map_session_data *sd,int type,int val) } sd->status.base_level = (unsigned int)val; sd->status.base_exp = 0; - // clif_updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom - clif_updatestatus(sd, SP_NEXTBASEEXP); - clif_updatestatus(sd, SP_STATUSPOINT); - clif_updatestatus(sd, SP_BASEEXP); + // clif->updatestatus(sd, SP_BASELEVEL); // Gets updated at the bottom + clif->updatestatus(sd, SP_NEXTBASEEXP); + clif->updatestatus(sd, SP_STATUSPOINT); + clif->updatestatus(sd, SP_BASEEXP); status_calc_pc(sd, 0); if(sd->status.party_id) { @@ -6901,13 +7083,13 @@ int pc_setparam(struct map_session_data *sd,int type,int val) if ((unsigned int)val >= sd->status.job_level) { if ((unsigned int)val > pc_maxjoblv(sd)) val = pc_maxjoblv(sd); sd->status.skill_point += val - sd->status.job_level; - clif_updatestatus(sd, SP_SKILLPOINT); + clif->updatestatus(sd, SP_SKILLPOINT); } sd->status.job_level = (unsigned int)val; sd->status.job_exp = 0; - // clif_updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom - clif_updatestatus(sd, SP_NEXTJOBEXP); - clif_updatestatus(sd, SP_JOBEXP); + // clif->updatestatus(sd, SP_JOBLEVEL); // Gets updated at the bottom + clif->updatestatus(sd, SP_NEXTJOBEXP); + clif->updatestatus(sd, SP_JOBEXP); status_calc_pc(sd, 0); break; case SP_SKILLPOINT: @@ -6919,7 +7101,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val) case SP_ZENY: if( val < 0 ) return 0;// can't set negative zeny - log_zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY))); + logs->zeny(sd, LOG_TYPE_SCRIPT, sd, -(sd->status.zeny - cap_value(val, 0, MAX_ZENY))); sd->status.zeny = cap_value(val, 0, MAX_ZENY); break; case SP_BASEEXP: @@ -6952,7 +7134,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val) if( sd->battle_status.max_hp < sd->battle_status.hp ) { sd->battle_status.hp = sd->battle_status.max_hp; - clif_updatestatus(sd, SP_HP); + clif->updatestatus(sd, SP_HP); } break; case SP_SP: @@ -6964,7 +7146,7 @@ int pc_setparam(struct map_session_data *sd,int type,int val) if( sd->battle_status.max_sp < sd->battle_status.sp ) { sd->battle_status.sp = sd->battle_status.max_sp; - clif_updatestatus(sd, SP_SP); + clif->updatestatus(sd, SP_SP); } break; case SP_STR: @@ -7000,30 +7182,36 @@ int pc_setparam(struct map_session_data *sd,int type,int val) case SP_KILLEDRID: sd->killedrid = val; return 1; + case SP_SLOTCHANGE: + sd->status.slotchange = val; + return 1; + case SP_CHARRENAME: + sd->status.rename = val; + return 1; default: ShowError("pc_setparam: Attempted to set unknown parameter '%d'.\n", type); return 0; } - clif_updatestatus(sd,type); + clif->updatestatus(sd,type); return 1; } /*========================================== - * HP/SP Healing. If flag is passed, the heal type is through clif_heal, otherwise update status. + * HP/SP Healing. If flag is passed, the heal type is through clif->heal, otherwise update status. *------------------------------------------*/ void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int type) { if (type) { if (hp) - clif_heal(sd->fd,SP_HP,hp); + clif->heal(sd->fd,SP_HP,hp); if (sp) - clif_heal(sd->fd,SP_SP,sp); + clif->heal(sd->fd,SP_SP,sp); } else { if(hp) - clif_updatestatus(sd,SP_HP); + clif->updatestatus(sd,SP_HP); if(sp) - clif_updatestatus(sd,SP_SP); + clif->updatestatus(sd,SP_SP); } return; } @@ -7035,9 +7223,10 @@ void pc_heal(struct map_session_data *sd,unsigned int hp,unsigned int sp, int ty *------------------------------------------*/ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp) { - int i, bonus; + int bonus; if(hp) { + int i; bonus = 100 + (sd->battle_status.vit<<1) + pc_checkskill(sd,SM_RECOVERY)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5; @@ -7155,7 +7344,7 @@ static int jobchange_killclone(struct block_list *bl, va_list ap) int pc_jobchange(struct map_session_data *sd,int job, int upper) { int i, fame_flag=0; - int b_class; + int b_class, idx = 0; nullpo_ret(sd); @@ -7195,11 +7384,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) } if(sd->cloneskill_id) { - if( sd->status.skill[sd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED ) { - sd->status.skill[sd->cloneskill_id].id = 0; - sd->status.skill[sd->cloneskill_id].lv = 0; - sd->status.skill[sd->cloneskill_id].flag = 0; - clif_deleteskill(sd,sd->cloneskill_id); + idx = skill->get_index(sd->cloneskill_id); + if( sd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED ) { + sd->status.skill[idx].id = 0; + sd->status.skill[idx].lv = 0; + sd->status.skill[idx].flag = 0; + clif->deleteskill(sd,sd->cloneskill_id); } sd->cloneskill_id = 0; pc_setglobalreg(sd, "CLONE_SKILL", 0); @@ -7207,11 +7397,12 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) } if(sd->reproduceskill_id) { - if( sd->status.skill[sd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) { - sd->status.skill[sd->reproduceskill_id].id = 0; - sd->status.skill[sd->reproduceskill_id].lv = 0; - sd->status.skill[sd->reproduceskill_id].flag = 0; - clif_deleteskill(sd,sd->reproduceskill_id); + idx = skill->get_index(sd->reproduceskill_id); + if( sd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED ) { + sd->status.skill[idx].id = 0; + sd->status.skill[idx].lv = 0; + sd->status.skill[idx].flag = 0; + clif->deleteskill(sd,sd->reproduceskill_id); } sd->reproduceskill_id = 0; pc_setglobalreg(sd, "REPRODUCE_SKILL",0); @@ -7229,6 +7420,11 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) } } + if( (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && (b_class&MAPID_UPPERMASK) != MAPID_STAR_GLADIATOR) { + /* going off star glad lineage, reset feel to not store no-longer-used vars in the database */ + pc_resetfeel(sd); + } + sd->status.class_ = job; fame_flag = pc_famerank(sd->status.char_id,sd->class_&MAPID_UPPERMASK); sd->class_ = (unsigned short)b_class; @@ -7239,15 +7435,15 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) sd->status.base_level = pc_maxbaselv(sd); sd->status.base_exp=0; pc_resetstate(sd); - clif_updatestatus(sd,SP_STATUSPOINT); - clif_updatestatus(sd,SP_BASELEVEL); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_NEXTBASEEXP); + clif->updatestatus(sd,SP_STATUSPOINT); + clif->updatestatus(sd,SP_BASELEVEL); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_NEXTBASEEXP); } - clif_updatestatus(sd,SP_JOBLEVEL); - clif_updatestatus(sd,SP_JOBEXP); - clif_updatestatus(sd,SP_NEXTJOBEXP); + clif->updatestatus(sd,SP_JOBLEVEL); + clif->updatestatus(sd,SP_JOBEXP); + clif->updatestatus(sd,SP_NEXTJOBEXP); for(i=0;i<EQI_MAX;i++) { if(sd->equip_index[i] >= 0) @@ -7257,22 +7453,22 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) //Change look, if disguised, you need to undisguise //to correctly calculate new job sprite without - if (sd->disguise) - pc_disguise(sd, 0); + if (sd->disguise != -1) + pc_disguise(sd, -1); status_set_viewdata(&sd->bl, job); - clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris] + clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_); // move sprite update to prevent client crashes with incompatible equipment [Valaris] if(sd->vd.cloth_color) - clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); //Update skill tree. pc_calc_skilltree(sd); - clif_skillinfoblock(sd); + clif->skillinfoblock(sd); if (sd->ed) elemental_delete(sd->ed, 0); if (sd->state.vending) - vending_closevending(sd); + vending->close(sd); map_foreachinmap(jobchange_killclone, sd->bl.m, BL_MOB, sd->bl.id); @@ -7300,11 +7496,11 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper) if(i != sd->sc.option) pc_setoption(sd, i); - if(merc_is_hom_active(sd->hd) && !pc_checkskill(sd, AM_CALLHOMUN)) - merc_hom_vaporize(sd, 0); + if(homun_alive(sd->hd) && !pc_checkskill(sd, AM_CALLHOMUN)) + homun->vaporize(sd, 0); if(sd->status.manner < 0) - clif_changestatus(sd,SP_MANNER,sd->status.manner); + clif->changestatus(sd,SP_MANNER,sd->status.manner); status_calc_pc(sd,0); pc_checkallowskill(sd); @@ -7336,12 +7532,12 @@ int pc_equiplookall(struct map_session_data *sd) { nullpo_ret(sd); - clif_changelook(&sd->bl,LOOK_WEAPON,0); - clif_changelook(&sd->bl,LOOK_SHOES,0); - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); - clif_changelook(&sd->bl, LOOK_ROBE, sd->status.robe); + clif->changelook(&sd->bl,LOOK_WEAPON,0); + clif->changelook(&sd->bl,LOOK_SHOES,0); + clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + clif->changelook(&sd->bl,LOOK_ROBE, sd->status.robe); return 0; } @@ -7354,55 +7550,56 @@ int pc_changelook(struct map_session_data *sd,int type,int val) nullpo_ret(sd); switch(type){ - case LOOK_HAIR: //Use the battle_config limits! [Skotlex] - val = cap_value(val, MIN_HAIR_STYLE, MAX_HAIR_STYLE); - - if (sd->status.hair != val) - { - sd->status.hair=val; - if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, - GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair)); - } - break; - case LOOK_WEAPON: - sd->status.weapon=val; - break; - case LOOK_HEAD_BOTTOM: - sd->status.head_bottom=val; - break; - case LOOK_HEAD_TOP: - sd->status.head_top=val; - break; - case LOOK_HEAD_MID: - sd->status.head_mid=val; - break; - case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex] - val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR); - - if (sd->status.hair_color != val) - { - sd->status.hair_color=val; - if (sd->status.guild_id) //Update Guild Window. [Skotlex] - intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, - GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color)); - } - break; - case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex] - val = cap_value(val, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); + case LOOK_BASE: + sd->vd.class_ = val; + break; + case LOOK_HAIR: //Use the battle_config limits! [Skotlex] + val = cap_value(val, MIN_HAIR_STYLE, MAX_HAIR_STYLE); + + if (sd->status.hair != val) { + sd->status.hair=val; + if (sd->status.guild_id) //Update Guild Window. [Skotlex] + intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, + GMI_HAIR,&sd->status.hair,sizeof(sd->status.hair)); + } + break; + case LOOK_WEAPON: + sd->status.weapon=val; + break; + case LOOK_HEAD_BOTTOM: + sd->status.head_bottom=val; + break; + case LOOK_HEAD_TOP: + sd->status.head_top=val; + break; + case LOOK_HEAD_MID: + sd->status.head_mid=val; + break; + case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex] + val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR); + + if (sd->status.hair_color != val) { + sd->status.hair_color=val; + if (sd->status.guild_id) //Update Guild Window. [Skotlex] + intif_guild_change_memberinfo(sd->status.guild_id,sd->status.account_id,sd->status.char_id, + GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color)); + } + break; + case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex] + val = cap_value(val, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); - sd->status.clothes_color=val; - break; - case LOOK_SHIELD: - sd->status.shield=val; - break; - case LOOK_SHOES: - break; - case LOOK_ROBE: - sd->status.robe = val; - break; + sd->status.clothes_color=val; + break; + case LOOK_SHIELD: + sd->status.shield=val; + break; + case LOOK_SHOES: + break; + case LOOK_ROBE: + sd->status.robe = val; + break; } - clif_changelook(&sd->bl,type,val); + clif->changelook(&sd->bl,type,val); return 0; } @@ -7417,52 +7614,42 @@ int pc_setoption(struct map_session_data *sd,int type) //Option has to be changed client-side before the class sprite or it won't always work (eg: Wedding sprite) [Skotlex] sd->sc.option=type; - clif_changeoption(&sd->bl); + clif->changeoption(&sd->bl); - if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) ) - { // Mounting - clif_status_load(&sd->bl,SI_RIDING,1); + if( (type&OPTION_RIDING && !(p_type&OPTION_RIDING)) || (type&OPTION_DRAGON && !(p_type&OPTION_DRAGON) && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) ) { + // Mounting + clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_RIDING, 0, 0, 0); status_calc_pc(sd,0); - } - else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON && pc_checkskill(sd,RK_DRAGONTRAINING) > 0) ) - { // Dismount - clif_status_load(&sd->bl,SI_RIDING,0); + } else if( (!(type&OPTION_RIDING) && p_type&OPTION_RIDING) || (!(type&OPTION_DRAGON) && p_type&OPTION_DRAGON) ) { + // Dismount + clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_RIDING); status_calc_pc(sd,0); } #ifndef NEW_CARTS if( type&OPTION_CART && !( p_type&OPTION_CART ) ) { //Cart On - clif_cartlist(sd); - clif_updatestatus(sd, SP_CARTINFO); + clif->cartlist(sd); + clif->updatestatus(sd, SP_CARTINFO); if(pc_checkskill(sd, MC_PUSHCART) < 10) status_calc_pc(sd,0); //Apply speed penalty. } else if( !( type&OPTION_CART ) && p_type&OPTION_CART ){ //Cart Off - clif_clearcart(sd->fd); + clif->clearcart(sd->fd); if(pc_checkskill(sd, MC_PUSHCART) < 10) status_calc_pc(sd,0); //Remove speed penalty. } #endif - if (type&OPTION_MOUNTING && !(p_type&OPTION_MOUNTING) ) { - clif_status_load_notick(&sd->bl,SI_ALL_RIDING,2,1,0,0); - status_calc_pc(sd,0); - } else if (!(type&OPTION_MOUNTING) && p_type&OPTION_MOUNTING) { - clif_status_load_notick(&sd->bl,SI_ALL_RIDING,0,0,0,0); - status_calc_pc(sd,0); - } - - if (type&OPTION_FALCON && !(p_type&OPTION_FALCON)) //Falcon ON - clif_status_load(&sd->bl,SI_FALCON,1); + clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_FALCON, 0, 0, 0); else if (!(type&OPTION_FALCON) && p_type&OPTION_FALCON) //Falcon OFF - clif_status_load(&sd->bl,SI_FALCON,0); + clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_FALCON); if( (sd->class_&MAPID_THIRDMASK) == MAPID_RANGER ) { if( type&OPTION_WUGRIDER && !(p_type&OPTION_WUGRIDER) ) { // Mounting - clif_status_load(&sd->bl,SI_WUGRIDER,1); + clif->sc_load(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER, 0, 0, 0); status_calc_pc(sd,0); } else if( !(type&OPTION_WUGRIDER) && p_type&OPTION_WUGRIDER ) { // Dismount - clif_status_load(&sd->bl,SI_WUGRIDER,0); + clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_WUGRIDER); status_calc_pc(sd,0); } } @@ -7490,23 +7677,8 @@ int pc_setoption(struct map_session_data *sd,int type) new_look = JOB_STAR_GLADIATOR2; else if (!(type&OPTION_FLYING) && p_type&OPTION_FLYING) new_look = -1; - - if (type&OPTION_WEDDING && !(p_type&OPTION_WEDDING)) - new_look = JOB_WEDDING; - else if (!(type&OPTION_WEDDING) && p_type&OPTION_WEDDING) - new_look = -1; - - if (type&OPTION_XMAS && !(p_type&OPTION_XMAS)) - new_look = JOB_XMAS; - else if (!(type&OPTION_XMAS) && p_type&OPTION_XMAS) - new_look = -1; - - if (type&OPTION_SUMMER && !(p_type&OPTION_SUMMER)) - new_look = JOB_SUMMER; - else if (!(type&OPTION_SUMMER) && p_type&OPTION_SUMMER) - new_look = -1; - - if (sd->disguise || !new_look) + + if (sd->disguise != -1 || !new_look) return 0; //Disguises break sprite changes if (new_look < 0) { //Restore normal look. @@ -7515,10 +7687,10 @@ int pc_setoption(struct map_session_data *sd,int type) } pc_stop_attack(sd); //Stop attacking on new view change (to prevent wedding/santa attacks. - clif_changelook(&sd->bl,LOOK_BASE,new_look); + clif->changelook(&sd->bl,LOOK_BASE,new_look); if (sd->vd.cloth_color) - clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); - clif_skillinfoblock(sd); // Skill list needs to be updated after base change. + clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + clif->skillinfoblock(sd); // Skill list needs to be updated after base change. return 0; } @@ -7549,14 +7721,15 @@ int pc_setcart(struct map_session_data *sd,int type) { if( !sd->sc.data[SC_PUSH_CART] ) return 0; status_change_end(&sd->bl,SC_PUSH_CART,INVALID_TIMER); - clif_clearcart(sd->fd); + clif->clearcart(sd->fd); + clif->updatestatus(sd, SP_CARTINFO); break; default:/* everything else is an allowed ID so we can move on */ if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */ - clif_cartlist(sd); - clif_updatestatus(sd, SP_CARTINFO); + clif->cartlist(sd); + clif->updatestatus(sd, SP_CARTINFO); sc_start(&sd->bl, SC_PUSH_CART, 100, type, 0); - clif_status_load_notick(&sd->bl, SI_ON_PUSH_CART, 2 , type, 0, 0); + clif->sc_load(&sd->bl, sd->bl.id, AREA, SI_ON_PUSH_CART, type, 0, 0); if( sd->sc.data[SC_PUSH_CART] )/* forcefully update */ sd->sc.data[SC_PUSH_CART]->val1 = type; break; @@ -8195,6 +8368,10 @@ int pc_removecombo(struct map_session_data *sd, struct item_data *data ) { cursor++; } + + /* check if combo requirements still fit */ + if( pc_checkcombo( sd, data ) ) + continue; /* it's empty, we can clear all the memory */ if( (sd->combos.count = cursor) == 0 ) { @@ -8238,19 +8415,19 @@ int pc_load_combo(struct map_session_data *sd) { *------------------------------------------*/ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) { - int i,pos,flag=0; + int i,pos,flag=0,iflag; struct item_data *id; nullpo_ret(sd); if( n < 0 || n >= MAX_INVENTORY ) { - clif_equipitemack(sd,0,0,0); + clif->equipitemack(sd,0,0,0); return 0; } if( DIFF_TICK(sd->canequip_tick,gettick()) > 0 ) { - clif_equipitemack(sd,n,0,0); + clif->equipitemack(sd,n,0,0); return 0; } @@ -8261,13 +8438,13 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos); if(!pc_isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris] // FIXME: pc_isequip: equip level failure uses 2 instead of 0 - clif_equipitemack(sd,n,0,0); // fail + clif->equipitemack(sd,n,0,0); // fail return 0; } if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST]) { - clif_equipitemack(sd,n,0,0); // fail + clif->equipitemack(sd,n,0,0); // fail return 0; } @@ -8303,11 +8480,11 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) } if(pos==EQP_AMMO){ - clif_arrowequip(sd,n); - clif_arrow_fail(sd,3); + clif->arrowequip(sd,n); + clif->arrow_fail(sd,3); } else - clif_equipitemack(sd,n,pos,1); + clif->equipitemack(sd,n,pos,1); sd->status.inventory[n].equip=pos; @@ -8317,7 +8494,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) else sd->weapontype1 = 0; pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); } if(pos & EQP_HAND_L) { if(id) { @@ -8334,7 +8511,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) else sd->status.shield = sd->weapontype2 = 0; pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); + clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); } //Added check to prevent sending the same look on multiple slots -> //causes client to redraw item on top of itself. (suggested by Lupus) @@ -8343,62 +8520,69 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) sd->status.head_bottom = id->look; else sd->status.head_bottom = 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); } if(pos & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) { if(id) sd->status.head_top = id->look; else sd->status.head_top = 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); } if(pos & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) { if(id && !(pos&EQP_HEAD_TOP)) sd->status.head_mid = id->look; else sd->status.head_mid = 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); } if(pos & EQP_COSTUME_HEAD_TOP) { if(id){ sd->status.head_top = id->look; } else sd->status.head_top = 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); } if(pos & EQP_COSTUME_HEAD_MID) { if(id && !(pos&EQP_HEAD_TOP)){ sd->status.head_mid = id->look; } else sd->status.head_mid = 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); } if(pos & EQP_COSTUME_HEAD_LOW) { if(id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))){ sd->status.head_bottom = id->look; } else sd->status.head_bottom = 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); } + if(pos & EQP_SHOES) - clif_changelook(&sd->bl,LOOK_SHOES,0); - if( pos&EQP_GARMENT ) - { + clif->changelook(&sd->bl,LOOK_SHOES,0); + if( pos&EQP_GARMENT && pc_checkequip(sd,EQP_COSTUME_GARMENT) == -1 ) { + sd->status.robe = id ? id->look : 0; + clif->changelook(&sd->bl, LOOK_ROBE, sd->status.robe); + } + + if(pos & EQP_COSTUME_GARMENT) { sd->status.robe = id ? id->look : 0; - clif_changelook(&sd->bl, LOOK_ROBE, sd->status.robe); + clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe); } + pc_checkallowskill(sd); //Check if status changes should be halted. + iflag = sd->npc_item_flag; /* check for combos (MUST be before status_calc_pc) */ if ( id ) { - struct item_data *data; if( id->combos_count ) pc_checkcombo(sd,id); if(itemdb_isspecial(sd->status.inventory[n].card[0])) ; //No cards else { for( i = 0; i < id->slot; i++ ) { + struct item_data *data; if (!sd->status.inventory[n].card[i]) continue; if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { @@ -8411,17 +8595,17 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) status_calc_pc(sd,0); if (flag) //Update skill data - clif_skillinfoblock(sd); + clif->skillinfoblock(sd); //OnEquip script [Skotlex] if (id) { - struct item_data *data; if (id->equip_script) run_script(id->equip_script,0,sd->bl.id,fake_nd->bl.id); if(itemdb_isspecial(sd->status.inventory[n].card[0])) ; //No cards else { for( i = 0; i < id->slot; i++ ) { + struct item_data *data; if (!sd->status.inventory[n].card[i]) continue; if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { @@ -8431,6 +8615,8 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) } } } + sd->npc_item_flag = iflag; + return 0; } @@ -8442,25 +8628,25 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos) * 2 - force unequip *------------------------------------------*/ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { - int i; + int i,iflag; bool status_cacl = false; nullpo_ret(sd); if( n < 0 || n >= MAX_INVENTORY ) { - clif_unequipitemack(sd,0,0,0); + clif->unequipitemack(sd,0,0,0); return 0; } // if player is berserk then cannot unequip if (!(flag & 2) && sd->sc.count && (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_SATURDAYNIGHTFEVER] || sd->sc.data[SC__BLOODYLUST])) { - clif_unequipitemack(sd,n,0,0); + clif->unequipitemack(sd,n,0,0); return 0; } if( !(flag&2) && sd->sc.count && sd->sc.data[SC_KYOUGAKU] ) { - clif_unequipitemack(sd,n,0,0); + clif->unequipitemack(sd,n,0,0); return 0; } @@ -8468,7 +8654,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { ShowInfo("unequip %d %x:%x\n",n,pc_equippoint(sd,n),sd->status.inventory[n].equip); if(!sd->status.inventory[n].equip){ //Nothing to unequip - clif_unequipitemack(sd,n,0,0); + clif->unequipitemack(sd,n,0,0); return 0; } for(i=0;i<EQI_MAX;i++) { @@ -8480,56 +8666,61 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { sd->weapontype1 = 0; sd->status.weapon = sd->weapontype2; pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); if( !battle_config.dancing_weaponswitch_fix ) status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing. } if(sd->status.inventory[n].equip & EQP_HAND_L) { sd->status.shield = sd->weapontype2 = 0; pc_calcweapontype(sd); - clif_changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); + clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield); } if(sd->status.inventory[n].equip & EQP_HEAD_LOW && pc_checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1 ) { sd->status.head_bottom = 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); } if(sd->status.inventory[n].equip & EQP_HEAD_TOP && pc_checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1 ) { sd->status.head_top = 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); } if(sd->status.inventory[n].equip & EQP_HEAD_MID && pc_checkequip(sd,EQP_COSTUME_HEAD_MID) == -1 ) { sd->status.head_mid = 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); } if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_TOP) { sd->status.head_top = ( pc_checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_TOP)]->look : 0; - clif_changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); + clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top); } if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_MID) { sd->status.head_mid = ( pc_checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_MID)]->look : 0; - clif_changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); + clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid); } if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_LOW) { sd->status.head_bottom = ( pc_checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_HEAD_LOW)]->look : 0; - clif_changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); + clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom); } if(sd->status.inventory[n].equip & EQP_SHOES) - clif_changelook(&sd->bl,LOOK_SHOES,0); - if( sd->status.inventory[n].equip&EQP_GARMENT ) - { + clif->changelook(&sd->bl,LOOK_SHOES,0); + + if( sd->status.inventory[n].equip&EQP_GARMENT && pc_checkequip(sd,EQP_COSTUME_GARMENT) == -1 ) { sd->status.robe = 0; - clif_changelook(&sd->bl, LOOK_ROBE, 0); + clif->changelook(&sd->bl, LOOK_ROBE, 0); } - clif_unequipitemack(sd,n,sd->status.inventory[n].equip,1); + if(sd->status.inventory[n].equip & EQP_COSTUME_GARMENT) { + sd->status.robe = ( pc_checkequip(sd,EQP_GARMENT) >= 0 ) ? sd->inventory_data[pc_checkequip(sd,EQP_GARMENT)]->look : 0; + clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe); + } + + clif->unequipitemack(sd,n,sd->status.inventory[n].equip,1); if((sd->status.inventory[n].equip & EQP_ARMS) && sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!) - skill_enchant_elemental_end(&sd->bl,-1); + skill->enchant_elemental_end(&sd->bl,-1); if(sd->status.inventory[n].equip & EQP_ARMOR) { // On Armor Change... @@ -8541,11 +8732,10 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish] sd->status.inventory[n].equip=0; + iflag = sd->npc_item_flag; /* check for combos (MUST be before status_calc_pc) */ if ( sd->inventory_data[n] ) { - struct item_data *data; - if( sd->inventory_data[n]->combos_count ) { if( pc_removecombo(sd,sd->inventory_data[n]) ) status_cacl = true; @@ -8553,6 +8743,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { ; //No cards else { for( i = 0; i < sd->inventory_data[n]->slot; i++ ) { + struct item_data *data; if (!sd->status.inventory[n].card[i]) continue; if ( ( data = itemdb_exists(sd->status.inventory[n].card[i]) ) != NULL ) { @@ -8570,18 +8761,18 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { status_calc_pc(sd,0); } - if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle_check_undead(sd->battle_status.race,sd->battle_status.def_ele)) + if(sd->sc.data[SC_SIGNUMCRUCIS] && !battle->check_undead(sd->battle_status.race,sd->battle_status.def_ele)) status_change_end(&sd->bl, SC_SIGNUMCRUCIS, INVALID_TIMER); //OnUnEquip script [Skotlex] if (sd->inventory_data[n]) { - struct item_data *data; if (sd->inventory_data[n]->unequip_script) run_script(sd->inventory_data[n]->unequip_script,0,sd->bl.id,fake_nd->bl.id); if(itemdb_isspecial(sd->status.inventory[n].card[0])) ; //No cards else { for( i = 0; i < sd->inventory_data[n]->slot; i++ ) { + struct item_data *data; if (!sd->status.inventory[n].card[i]) continue; @@ -8593,6 +8784,7 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) { } } } + sd->npc_item_flag = iflag; return 0; } @@ -8604,41 +8796,33 @@ 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; - struct item_data *it=NULL; nullpo_ret(sd); if( sd->state.vending ) //Avoid reorganizing items when we are vending, as that leads to exploits (pointed out by End of Exam) return 0; - if( battle_config.item_check ) - {// check for invalid(ated) items - for( i = 0; i < MAX_INVENTORY; i++ ) - { + if( battle_config.item_check ) { // check for invalid(ated) items + for( i = 0; i < MAX_INVENTORY; i++ ) { id = sd->status.inventory[i].nameid; - if( id && !itemdb_available(id) ) - { + if( id && !itemdb_available(id) ) { ShowWarning("Removed invalid/disabled item id %d from inventory (amount=%d, char_id=%d).\n", id, sd->status.inventory[i].amount, sd->status.char_id); pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_OTHER); } } - for( i = 0; i < MAX_CART; i++ ) - { + for( i = 0; i < MAX_CART; i++ ) { id = sd->status.cart[i].nameid; - if( id && !itemdb_available(id) ) - { + if( id && !itemdb_available(id) ) { ShowWarning("Removed invalid/disabled item id %d from cart (amount=%d, char_id=%d).\n", id, sd->status.cart[i].amount, sd->status.char_id); pc_cart_delitem(sd, i, sd->status.cart[i].amount, 0, LOG_TYPE_OTHER); } } } - for( i = 0; i < MAX_INVENTORY; i++) - { - it = sd->inventory_data[i]; + for( i = 0; i < MAX_INVENTORY; i++) { if( sd->status.inventory[i].nameid == 0 ) continue; @@ -8646,31 +8830,15 @@ int pc_checkitem(struct map_session_data *sd) if( !sd->status.inventory[i].equip ) continue; - if( sd->status.inventory[i].equip&~pc_equippoint(sd,i) ) - { + if( sd->status.inventory[i].equip&~pc_equippoint(sd,i) ) { pc_unequipitem(sd, i, 2); calc_flag = 1; continue; } - if( it ) - { // check for forbiden items. - int flag = - (map[sd->bl.m].flag.restricted?(8*map[sd->bl.m].zone):0) - | (!map_flag_vs(sd->bl.m)?1:0) - | (map[sd->bl.m].flag.pvp?2:0) - | (map_flag_gvg(sd->bl.m)?4:0) - | (map[sd->bl.m].flag.battleground?8:0); - if( flag && (it->flag.no_equip&flag || !pc_isAllowedCardOn(sd,it->slot,i,flag)) ) - { - pc_unequipitem(sd, i, 2); - calc_flag = 1; - } - } } - if( calc_flag && sd->state.active ) - { + if( calc_flag && sd->state.active ) { pc_checkallowskill(sd); status_calc_pc(sd,0); } @@ -8683,7 +8851,7 @@ int pc_checkitem(struct map_session_data *sd) *------------------------------------------*/ int pc_calc_pvprank_sub(struct block_list *bl,va_list ap) { - struct map_session_data *sd1,*sd2=NULL; + struct map_session_data *sd1,*sd2; sd1=(struct map_session_data *)bl; sd2=va_arg(ap,struct map_session_data *); @@ -8710,7 +8878,7 @@ int pc_calc_pvprank(struct map_session_data *sd) sd->pvp_rank=1; map_foreachinmap(pc_calc_pvprank_sub,sd->bl.m,BL_PC,sd); if(old!=sd->pvp_rank || sd->pvp_lastusers!=m->users_pvp) - clif_pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0); + clif->pvpset(sd,sd->pvp_rank,sd->pvp_lastusers=m->users_pvp,0); return sd->pvp_rank; } /*========================================== @@ -8718,7 +8886,7 @@ int pc_calc_pvprank(struct map_session_data *sd) *------------------------------------------*/ int pc_calc_pvprank_timer(int tid, unsigned int tick, int id, intptr_t data) { - struct map_session_data *sd=NULL; + struct map_session_data *sd; sd=map_id2sd(id); if(sd==NULL) @@ -8803,8 +8971,8 @@ int pc_divorce(struct map_session_data *sd) pc_delitem(p_sd, i, 1, 0, 0, LOG_TYPE_OTHER); } - clif_divorced(sd, p_sd->status.name); - clif_divorced(p_sd, sd->status.name); + clif->divorced(sd, p_sd->status.name); + clif->divorced(p_sd, sd->status.name); return 0; } @@ -8950,7 +9118,7 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) save_flag = 1; //Noone was saved, so save first found char. iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if(sd->bl.id == last_save_id && save_flag != 1) { save_flag = 1; @@ -8967,7 +9135,7 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) chrif_save(sd,0); break; } - mapit_free(iter); + mapit->free(iter); interval = autosave_interval/(map_usercount()+1); if(interval < minsave_interval) @@ -8979,9 +9147,8 @@ int pc_autosave(int tid, unsigned int tick, int id, intptr_t data) static int pc_daynight_timer_sub(struct map_session_data *sd,va_list ap) { - if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled) - { //Night/day state does not match. - clif_status_load(&sd->bl, SI_NIGHT, night_flag); //New night effect by dynamix [Skotlex] + if (sd->state.night != night_flag && map[sd->bl.m].flag.nightenabled) { //Night/day state does not match. + clif->status_change(&sd->bl, SI_NIGHT, night_flag, 0, 0, 0, 0); //New night effect by dynamix [Skotlex] sd->state.night = night_flag; return 1; } @@ -9033,7 +9200,7 @@ void pc_setstand(struct map_session_data *sd){ nullpo_retv(sd); status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER); - clif_status_load(&sd->bl,SI_SIT,0); + clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT); //Reset sitting tick. sd->ssregen.tick.hp = sd->ssregen.tick.sp = 0; sd->state.dead_sit = sd->vd.dead_sit = 0; @@ -9079,22 +9246,10 @@ bool pc_isautolooting(struct map_session_data *sd, int nameid) /** * Checks if player can use @/#command * @param sd Player map session data - * @param command Command name without @/# and params - * @param type is it atcommand or charcommand + * @param command Command name with @/# and without params */ -bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type) -{ - return pc_group_can_use_command(pc_get_group_id(sd), command, type); -} - -/** - * Checks if commands used by a player should be logged - * according to their group setting. - * @param sd Player map session data - */ -bool pc_should_log_commands(struct map_session_data *sd) -{ - return pc_group_should_log_commands(pc_get_group_id(sd)); +bool pc_can_use_command(struct map_session_data *sd, const char *command) { + return atcommand->can_use(sd,command); } static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data) @@ -9126,7 +9281,7 @@ static int pc_talisman_timer(int tid, unsigned int tick, int id, intptr_t data) memmove(sd->talisman_timer[type]+i, sd->talisman_timer[type]+i+1, (sd->talisman[type]-i)*sizeof(int)); sd->talisman_timer[type][sd->talisman[type]] = INVALID_TIMER; - clif_talisman(sd, type); + clif->talisman(sd, type); return 0; } @@ -9159,7 +9314,7 @@ int pc_add_talisman(struct map_session_data *sd,int interval,int max,int type) sd->talisman_timer[type][i] = tid; sd->talisman[type]++; - clif_talisman(sd, type); + clif->talisman(sd, type); return 0; } @@ -9193,7 +9348,7 @@ int pc_del_talisman(struct map_session_data *sd,int count,int type) sd->talisman_timer[type][i] = INVALID_TIMER; } - clif_talisman(sd, type); + clif->talisman(sd, type); return 0; } #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) @@ -9319,24 +9474,22 @@ static bool pc_readdb_skilltree(char* fields[], int columns, int current) //This is to avoid adding two lines for the same skill. [Skotlex] ARR_FIND( 0, MAX_SKILL_TREE, skill_idx, skill_tree[idx][skill_idx].id == 0 || skill_tree[idx][skill_idx].id == skill_id ); - if( skill_idx == MAX_SKILL_TREE ) - { + if( skill_idx == MAX_SKILL_TREE ) { ShowWarning("pc_readdb_skilltree: Unable to load skill %hu into job %d's tree. Maximum number of skills per class has been reached.\n", skill_id, class_); return false; - } - else if(skill_tree[idx][skill_idx].id) - { + } else if(skill_tree[idx][skill_idx].id) { ShowNotice("pc_readdb_skilltree: Overwriting skill %hu for job class %d.\n", skill_id, class_); } skill_tree[idx][skill_idx].id = skill_id; + skill_tree[idx][skill_idx].idx = skill->get_index(skill_id); skill_tree[idx][skill_idx].max = skill_lv; skill_tree[idx][skill_idx].joblv = joblv; - for(i = 0; i < MAX_PC_SKILL_REQUIRE; i++) - { - skill_tree[idx][skill_idx].need[i].id = atoi(fields[i*2+offset]); - skill_tree[idx][skill_idx].need[i].lv = atoi(fields[i*2+offset+1]); + for(i = 0; i < MAX_PC_SKILL_REQUIRE; i++) { + skill_tree[idx][skill_idx].need[i].id = atoi(fields[i*2+offset]); + skill_tree[idx][skill_idx].need[i].idx = skill->get_index(atoi(fields[i*2+offset])); + skill_tree[idx][skill_idx].need[i].lv = atoi(fields[i*2+offset+1]); } return true; } @@ -9354,7 +9507,7 @@ static bool pc_readdb_levelpenalty(char* fields[], int columns, int current) return false; } - if( race < 0 && race > RC_MAX ){ + if( race < 0 || race > RC_MAX ){ ShowWarning("pc_readdb_levelpenalty: Invalid race %d specified.\n", race); return false; } @@ -9378,7 +9531,8 @@ static bool pc_readdb_levelpenalty(char* fields[], int columns, int current) *------------------------------------------*/ int pc_readdb(void) { - int i,j,k,tmp=0; + int i,j,k; + unsigned int count = 0; FILE *fp; char line[24000],*p; @@ -9422,7 +9576,7 @@ int pc_readdb(void) ShowWarning("pc_readdb: Specified max level %u for job %d is beyond server's limit (%u).\n ", maxlv, job_id, MAX_LEVEL); maxlv = MAX_LEVEL; } - + count++; job = jobs[0] = pc_class2idx(job_id); //We send one less and then one more because the last entry in the exp array should hold 0. max_level[job][type] = pc_split_atoui(split[3], exp_table[job][type],',',maxlv-1)+1; @@ -9465,17 +9619,17 @@ int pc_readdb(void) if (!max_level[j][1]) ShowWarning("Class %s (%d) does not has a job exp table.\n", job_name(i), i); } - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","exp.txt"); - + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,db_path,"exp.txt"); + count = 0; // Reset and read skilltree memset(skill_tree,0,sizeof(skill_tree)); - sv_readdb(db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree); + sv->readdb(db_path, DBPATH"skill_tree.txt", ',', 3+MAX_PC_SKILL_REQUIRE*2, 4+MAX_PC_SKILL_REQUIRE*2, -1, &pc_readdb_skilltree); #if defined(RENEWAL_DROP) || defined(RENEWAL_EXP) - sv_readdb(db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty); + sv->readdb(db_path, "re/level_penalty.txt", ',', 4, 4, -1, &pc_readdb_levelpenalty); for( k=1; k < 3; k++ ){ // fill in the blanks for( j = 0; j < RC_MAX; j++ ){ - tmp = 0; + int tmp = 0; for( i = 0; i < MAX_LEVEL*2; i++ ){ if( i == MAX_LEVEL+1 ) tmp = level_penalty[k][j][0];// reset @@ -9517,7 +9671,7 @@ int pc_readdb(void) lv=atoi(split[0]); n=atoi(split[1]); - + count++; for(i=0;i<n && i<ELE_MAX;){ if( !fgets(line, sizeof(line), fp) ) break; @@ -9538,8 +9692,8 @@ int pc_readdb(void) } } fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","attr_fix.txt"); - + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,db_path,"attr_fix.txt"); + count = 0; // reset then read statspoint memset(statp,0,sizeof(statp)); i=1; @@ -9559,12 +9713,13 @@ int pc_readdb(void) stat=0; if (i > MAX_LEVEL) break; + count++; statp[i]=stat; i++; } fclose(fp); - ShowStatus("Done reading '"CL_WHITE"%s"CL_RESET"'.\n","statpoint.txt"); + ShowStatus("Done reading '"CL_WHITE"%lu"CL_RESET"' entries in '"CL_WHITE"%s/"DBPATH"%s"CL_RESET"'.\n",count,db_path,"statpoint.txt"); } // generate the remaining parts of the db if necessary k = battle_config.use_statpoint_table; //save setting @@ -9678,6 +9833,8 @@ void do_final_pc(void) { db_destroy(itemcd_db); do_final_pc_groups(); + + ers_destroy(pc_sc_display_ers); return; } @@ -9715,6 +9872,8 @@ int do_init_pc(void) { } do_init_pc_groups(); + + pc_sc_display_ers = ers_new(sizeof(struct sc_display_entry), "pc.c:pc_sc_display_ers", ERS_OPT_NONE); return 0; } diff --git a/src/map/pc.h b/src/map/pc.h index 3027c5f10..014f93d99 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -1,10 +1,12 @@ -// 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 _PC_H_ #define _PC_H_ #include "../common/mmo.h" // JOB_*, MAX_FAME_LIST, struct fame_list, struct mmo_charstatus +#include "../common/ers.h" #include "../common/timer.h" // INVALID_TIMER #include "atcommand.h" // AtCommandType #include "battle.h" // battle_config @@ -24,6 +26,27 @@ #define MAX_PC_SKILL_REQUIRE 5 #define MAX_PC_FEELHATE 3 +//Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index +//where the arrows are equipped) +enum equip_index { + EQI_ACC_L = 0, + EQI_ACC_R, + EQI_SHOES, + EQI_GARMENT, + EQI_HEAD_LOW, + EQI_HEAD_MID, + EQI_HEAD_TOP, + EQI_ARMOR, + EQI_HAND_L, + EQI_HAND_R, + EQI_COSTUME_TOP, + EQI_COSTUME_MID, + EQI_COSTUME_LOW, + EQI_COSTUME_GARMENT, + EQI_AMMO, + EQI_MAX +}; + struct weapon_data { int atkmods[3]; // all the variables except atkmods get zero'ed in each call of status_calc_pc @@ -87,6 +110,12 @@ struct s_autobonus { unsigned short pos; }; +enum npc_timeout_type { + NPCT_INPUT = 0, + NPCT_MENU = 1, + NPCT_WAIT = 2, +}; + struct map_session_data { struct block_list bl; struct unit_data ud; @@ -115,7 +144,6 @@ struct map_session_data { unsigned int showdelay :1; unsigned int showexp :1; unsigned int showzeny :1; - unsigned int mainchat :1; //[LuzZza] unsigned int noask :1; // [LuzZza] unsigned int trading :1; //[Skotlex] is 1 only after a trade has started. unsigned int deal_locked :2; //1: Clicked on OK. 2: Clicked on TRADE @@ -144,6 +172,7 @@ struct map_session_data { struct guild *gmaster_flag; unsigned int prevend : 1;//used to flag wheather you've spent 40sp to open the vending or not. unsigned int warping : 1;//states whether you're in the middle of a warp processing + unsigned int permanent_speed : 1; // When 1, speed cannot be changed through status_calc_pc(). } state; struct { unsigned char no_weapon_damage, no_magic_damage, no_misc_damage; @@ -161,13 +190,13 @@ struct map_session_data { unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex] int group_id, group_pos, group_level; unsigned int permissions;/* group permissions */ - - int packet_ver; // 5: old, 6: 7july04, 7: 13july04, 8: 26july04, 9: 9aug04/16aug04/17aug04, 10: 6sept04, 11: 21sept04, 12: 18oct04, 13: 25oct04 ... 18 + bool group_log_command; + struct mmo_charstatus status; struct registry save_reg; struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups) - short equip_index[14]; + short equip_index[EQI_MAX]; unsigned int weight,max_weight; int cart_weight,cart_num,cart_weight_max; int fd; @@ -262,7 +291,7 @@ struct map_session_data { struct { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills. unsigned short id; short val; - } skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS], skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS]; + } skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[5], skillheal2[5], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS], skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS], skillfixcastrate[MAX_PC_BONUS]; struct { short value; int rate; @@ -319,6 +348,7 @@ struct map_session_data { unsigned short unbreakable_equip; //100% break resistance on certain equipment unsigned short unstripable_equip; int fixcastrate,varcastrate; + int add_fixcast,add_varcast; int ematk; // matk bonus from equipment // int eatk; // atk bonus from equipment } bonus; @@ -336,7 +366,7 @@ struct map_session_data { short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo] short spiritball, spiritball_old; - int spirit_timer[MAX_SKILL_LEVEL]; + int spirit_timer[MAX_SPIRITBALL]; short talisman[ELE_POISON+1]; // There are actually 5 talisman Fire, Ice, Wind, Earth & Poison maybe because its color violet. int talisman_timer[ELE_POISON+1][10]; @@ -363,15 +393,15 @@ struct map_session_data { bool party_joining; // whether the char is accepting party invitation int party_invite, party_invite_account; // for handling party invitation (holds party id and account id) int adopt_invite; // Adoption - + struct guild *guild;/* [Ind/Hercules] speed everything up */ int guild_invite,guild_invite_account; int guild_emblem_id,guild_alliance,guild_alliance_account; short guild_x,guild_y; // For guildmate position display. [Skotlex] should be short [zzo] int guildspy; // [Syrus22] int partyspy; // [Syrus22] - int vended_id; - int vender_id; + unsigned int vended_id; + unsigned int vender_id; int vend_num; char message[MESSAGE_SIZE]; struct s_vending vending[MAX_VENDING]; @@ -445,7 +475,7 @@ struct map_session_data { /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT /** * ID of the timer * @info @@ -459,6 +489,8 @@ struct map_session_data { * - It is updated on every NPC iteration as mentioned above **/ unsigned int npc_idle_tick; + /* */ + enum npc_timeout_type npc_idle_type; #endif struct { @@ -473,13 +505,28 @@ struct map_session_data { int friend_req; int shadowform_id; - + + /* [Ind/Hercules] */ + struct hChSysCh **channels; + unsigned char channel_count; + struct hChSysCh *gcbind; + bool stealth; + unsigned char fontcolor; + unsigned int fontcolor_tid; + unsigned int hchsysch_tick; + + /* [Ind/Hercules] */ + struct sc_display_entry **sc_display; + unsigned char sc_display_count; + // temporary debugging of bug #3504 const char* delunit_prevfile; int delunit_prevline; }; +struct eri *pc_sc_display_ers; + //Update this max as necessary. 55 is the value needed for Super Baby currently //Raised to 84 since Expanded Super Novice needs it. #define MAX_SKILL_TREE 84 @@ -535,20 +582,21 @@ enum ammo_type { //Equip position constants enum equip_pos { - EQP_HEAD_LOW = 0x0001, - EQP_HEAD_MID = 0x0200, //512 - EQP_HEAD_TOP = 0x0100, //256 - EQP_HAND_R = 0x0002, - EQP_HAND_L = 0x0020, //32 - EQP_ARMOR = 0x0010, //16 - EQP_SHOES = 0x0040, //64 - EQP_GARMENT = 0x0004, - EQP_ACC_L = 0x0008, - EQP_ACC_R = 0x0080, //128 - EQP_COSTUME_HEAD_TOP = 0x0400, - EQP_COSTUME_HEAD_MID = 0x0800, - EQP_COSTUME_HEAD_LOW = 0x1000, - EQP_AMMO = 0x8000, //32768 + EQP_HEAD_LOW = 0x0001, + EQP_HEAD_MID = 0x0200, //512 + EQP_HEAD_TOP = 0x0100, //256 + EQP_HAND_R = 0x0002, //2 + EQP_HAND_L = 0x0020, //32 + EQP_ARMOR = 0x0010, //16 + EQP_SHOES = 0x0040, //64 + EQP_GARMENT = 0x0004, //4 + EQP_ACC_L = 0x0008, //8 + EQP_ACC_R = 0x0080, //128 + EQP_COSTUME_HEAD_TOP = 0x0400, //1024 + EQP_COSTUME_HEAD_MID = 0x0800, //2048 + EQP_COSTUME_HEAD_LOW = 0x1000, //4096 + EQP_COSTUME_GARMENT = 0x2000, //8192 + EQP_AMMO = 0x8000, //32768 }; #define EQP_WEAPON EQP_HAND_R @@ -556,7 +604,7 @@ enum equip_pos { #define EQP_ARMS (EQP_HAND_R|EQP_HAND_L) #define EQP_HELM (EQP_HEAD_LOW|EQP_HEAD_MID|EQP_HEAD_TOP) #define EQP_ACC (EQP_ACC_L|EQP_ACC_R) -#define EQP_COSTUME (EQP_COSTUME_HEAD_TOP|EQP_COSTUME_HEAD_MID|EQP_COSTUME_HEAD_LOW) +#define EQP_COSTUME (EQP_COSTUME_HEAD_TOP|EQP_COSTUME_HEAD_MID|EQP_COSTUME_HEAD_LOW|EQP_COSTUME_GARMENT) /// Equip positions that use a visible sprite #if PACKETVER < 20110111 @@ -565,33 +613,17 @@ enum equip_pos { #define EQP_VISIBLE (EQP_HELM|EQP_GARMENT|EQP_COSTUME) #endif -//Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index -//where the arrows are equipped) -enum equip_index { - EQI_ACC_L = 0, - EQI_ACC_R, - EQI_SHOES, - EQI_GARMENT, - EQI_HEAD_LOW, - EQI_HEAD_MID, - EQI_HEAD_TOP, - EQI_ARMOR, - EQI_HAND_L, - EQI_HAND_R, - EQI_COSTUME_TOP, - EQI_COSTUME_MID, - EQI_COSTUME_LOW, - EQI_AMMO, - EQI_MAX -}; - #define pc_setdead(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 1 ) #define pc_setsit(sd) ( (sd)->state.dead_sit = (sd)->vd.dead_sit = 2 ) #define pc_isdead(sd) ( (sd)->state.dead_sit == 1 ) #define pc_issit(sd) ( (sd)->vd.dead_sit == 2 ) #define pc_isidle(sd) ( (sd)->chatID || (sd)->state.vending || (sd)->state.buyingstore || DIFF_TICK(last_tick, (sd)->idletime) >= battle_config.idle_no_share ) #define pc_istrading(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->state.trading ) -#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag ) +#define pc_cant_act(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || (sd)->chatID || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend ) + +/* equals pc_cant_act except it doesn't check for chat rooms */ +#define pc_cant_act2(sd) ( (sd)->npc_id || (sd)->state.vending || (sd)->state.buyingstore || ((sd)->sc.opt1 && (sd)->sc.opt1 != OPT1_BURNING) || (sd)->state.trading || (sd)->state.storage_flag || (sd)->state.prevend ) + #define pc_setdir(sd,b,h) ( (sd)->ud.dir = (b) ,(sd)->head_dir = (h) ) #define pc_setchatid(sd,n) ( (sd)->chatID = n ) #define pc_ishiding(sd) ( (sd)->sc.option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) ) @@ -672,13 +704,13 @@ enum equip_index { int pc_class2idx(int class_); int pc_get_group_level(struct map_session_data *sd); -int pc_get_group_id(struct map_session_data *sd); +#define pc_get_group_id(sd) ( (sd)->group_id ) int pc_getrefinebonus(int lv,int type); bool pc_can_give_items(struct map_session_data *sd); -bool pc_can_use_command(struct map_session_data *sd, const char *command, AtCommandType type); +bool pc_can_use_command(struct map_session_data *sd, const char *command); #define pc_has_permission(sd, permission) ( ((sd)->permissions&permission) != 0 ) -bool pc_should_log_commands(struct map_session_data *sd); +#define pc_should_log_commands(sd) ( (sd)->group_log_command != false ) int pc_setrestartvalue(struct map_session_data *sd,int type); int pc_makesavestatus(struct map_session_data *); @@ -693,6 +725,7 @@ int pc_equippoint(struct map_session_data *sd,int n); int pc_setinventorydata(struct map_session_data *sd); int pc_checkskill(struct map_session_data *sd,uint16 skill_id); +int pc_checkskill2(struct map_session_data *sd,uint16 index); int pc_checkallowskill(struct map_session_data *sd); int pc_checkequip(struct map_session_data *sd,int pos); @@ -855,10 +888,12 @@ const char * job_name(int class_); struct skill_tree_entry { short id; + unsigned short idx; unsigned char max; unsigned char joblv; struct { short id; + unsigned short idx; unsigned char lv; } need[MAX_PC_SKILL_REQUIRE]; }; // Celest diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c index 3111e2788..1a83c8b63 100644 --- a/src/map/pc_groups.c +++ b/src/map/pc_groups.c @@ -1,5 +1,6 @@ -// 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 #include "../common/conf.h" #include "../common/db.h" @@ -13,28 +14,26 @@ #include "pc_groups.h" #include "pc.h" // e_pc_permission - typedef struct GroupSettings GroupSettings; // Cached config settings/pointers for quick lookup struct GroupSettings { unsigned int id; // groups.[].id int level; // groups.[].level - const char *name; // groups.[].name - config_setting_t *commands; // groups.[].commands + char name[60]; // copy of groups.[].name unsigned int e_permissions; // packed groups.[].permissions bool log_commands; // groups.[].log_commands - /// Following are used only during config reading + int group_pos;/* pos on load [Ind] */ + /// Following are used/avaialble only during config reading + config_setting_t *commands; // groups.[].commands config_setting_t *permissions; // groups.[].permissions config_setting_t *inherit; // groups.[].inherit bool inheritance_done; // have all inheritance rules been evaluated? config_setting_t *root; // groups.[] - int group_pos;/* pos on load */ }; int pc_group_max; /* known number of groups */ -static config_t pc_group_config; static DBMap* pc_group_db; // id -> GroupSettings static DBMap* pc_groupname_db; // name -> GroupSettings @@ -60,8 +59,8 @@ static inline GroupSettings* name2group(const char* group_name) * Loads group configuration from config file into memory. * @private */ -static void read_config(void) -{ +static void read_config(void) { + config_t pc_group_config; config_setting_t *groups = NULL; const char *config_filename = "conf/groups.conf"; // FIXME hardcoded name int group_count = 0; @@ -126,7 +125,7 @@ static void read_config(void) CREATE(group_settings, GroupSettings, 1); group_settings->id = id; group_settings->level = level; - group_settings->name = groupname; + safestrncpy(group_settings->name, groupname, 60); group_settings->log_commands = (bool)log_commands; group_settings->inherit = config_setting_get_member(group, "inherit"); group_settings->commands = config_setting_get_member(group, "commands"); @@ -155,7 +154,7 @@ static void read_config(void) for (i = 0; i < count; ++i) { config_setting_t *command = config_setting_get_elem(commands, i); const char *name = config_setting_name(command); - if (!atcommand_exists(name)) { + if (!atcommand->exists(name)) { ShowConfigWarning(command, "pc_groups:read_config: non-existent command name '%s', removing...", name); config_setting_remove(commands, name); --i; @@ -278,26 +277,21 @@ static void read_config(void) if( ( pc_group_max = group_count ) ) { DBIterator *iter = db_iterator(pc_group_db); GroupSettings *group_settings = NULL; - int* group_ids = aMalloc( pc_group_max * sizeof(int) ); + unsigned int* group_ids = aMalloc( pc_group_max * sizeof(unsigned int) ); int i = 0; for (group_settings = dbi_first(iter); dbi_exists(iter); group_settings = dbi_next(iter)) { group_ids[i++] = group_settings->id; } - atcommand_db_load_groups(group_ids); - - aFree(group_ids); + if( atcommand->group_ids ) + aFree(atcommand->group_ids); + atcommand->group_ids = group_ids; + atcommand->load_groups(); + dbi_destroy(iter); } -} - -/** - * Removes group configuration from memory. - * @private - */ -static void destroy_config(void) -{ + config_destroy(&pc_group_config); } @@ -312,13 +306,12 @@ static void destroy_config(void) static inline int AtCommandType2idx(AtCommandType type) { return (type-1); } /** - * Checks if player group can use @/#command + * Checks if player group can use @/#command, used only during parse (only available during parse) * @param group_id ID of the group * @param command Command name without @/# and params * @param type enum AtCommanndType { COMMAND_ATCOMMAND = 1, COMMAND_CHARCOMMAND = 2 } */ -bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type) -{ +bool pc_group_can_use_command(int group_id, const char *command, AtCommandType type) { int result = 0; config_setting_t *commands = NULL; GroupSettings *group = NULL; @@ -357,6 +350,7 @@ void pc_group_pc_load(struct map_session_data * sd) { sd->permissions = group->e_permissions; sd->group_pos = group->group_pos; sd->group_level = group->level; + sd->group_log_command = group->log_commands; } /** * Checks if player group has a permission @@ -442,7 +436,6 @@ void do_final_pc_groups(void) db_destroy(pc_group_db); if (pc_groupname_db != NULL ) db_destroy(pc_groupname_db); - destroy_config(); } /** @@ -452,17 +445,17 @@ void do_final_pc_groups(void) */ void pc_groups_reload(void) { struct map_session_data* sd = NULL; - struct s_mapiterator* iter = NULL; + struct s_mapiterator* iter; do_final_pc_groups(); do_init_pc_groups(); /* refresh online users permissions */ iter = mapit_getallusers(); - for (sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter)) { + for (sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter)) { pc_group_pc_load(sd); } - mapit_free(iter); + mapit->free(iter); } diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h index 65c48935a..26cd8f39f 100644 --- a/src/map/pc_groups.h +++ b/src/map/pc_groups.h @@ -1,5 +1,6 @@ -// 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 _PC_GROUPS_H_ #define _PC_GROUPS_H_ @@ -43,6 +44,7 @@ enum e_pc_permission { PC_PERM_DISABLE_PVM = 0x040000, PC_PERM_DISABLE_PVP = 0x080000, PC_PERM_DISABLE_CMD_DEAD = 0x100000, + PC_PERM_HCHSYS_ADMIN = 0x200000, }; static const struct { @@ -70,6 +72,7 @@ static const struct { { "disable_pvm", PC_PERM_DISABLE_PVM }, { "disable_pvp", PC_PERM_DISABLE_PVP }, { "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD }, + { "hchsys_admin", PC_PERM_HCHSYS_ADMIN }, }; #endif // _PC_GROUPS_H_ diff --git a/src/map/pet.c b/src/map/pet.c index 5c7f15151..c85092a01 100644 --- a/src/map/pet.c +++ b/src/map/pet.c @@ -1,5 +1,6 @@ -// 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 #include "../common/db.h" #include "../common/timer.h" @@ -75,6 +76,7 @@ int pet_create_egg(struct map_session_data *sd, int item_id) { int pet_id = search_petDB_index(item_id, PET_EGG); if (pet_id < 0) return 0; //No pet egg here. + if (!pc_inventoryblank(sd)) return 0; // Inventory full sd->catch_target_class = pet_db[pet_id].class_; intif_create_pet(sd->status.account_id, sd->status.char_id, (short)pet_db[pet_id].class_, @@ -100,8 +102,6 @@ int pet_unlocktarget(struct pet_data *pd) *------------------------------------------*/ int pet_attackskill(struct pet_data *pd, int target_id) { - struct block_list *bl; - if (!battle_config.pet_status_support || !pd->a_skill || (battle_config.pet_equip_required && !pd->pet.equip)) return 0; @@ -112,13 +112,14 @@ int pet_attackskill(struct pet_data *pd, int target_id) if (rnd()%100 < (pd->a_skill->rate +pd->pet.intimate*pd->a_skill->bonusrate/1000)) { //Skotlex: Use pet's skill int inf; + struct block_list *bl; bl=map_id2bl(target_id); if(bl == NULL || pd->bl.m != bl->m || bl->prev == NULL || status_isdead(bl) || !check_distance_bl(&pd->bl, bl, pd->db->range3)) return 0; - inf = skill_get_inf(pd->a_skill->id); + inf = skill->get_inf(pd->a_skill->id); if (inf & INF_GROUND_SKILL) unit_skilluse_pos(&pd->bl, bl->x, bl->y, pd->a_skill->id, pd->a_skill->lv); else //Offensive self skill? Could be stuff like GX. @@ -226,9 +227,9 @@ static int pet_hungry(int tid, unsigned int tick, int id, intptr_t data) pd->status.speed = pd->db->status.speed; } status_calc_pet(pd, 0); - clif_send_petdata(sd,pd,1,pd->pet.intimate); + clif->send_petdata(sd,pd,1,pd->pet.intimate); } - clif_send_petdata(sd,pd,2,pd->pet.hungry); + clif->send_petdata(sd,pd,2,pd->pet.hungry); if(battle_config.pet_hungry_delay_rate != 100) interval = (pd->petDB->hungry_delay*battle_config.pet_hungry_delay_rate)/100; @@ -285,7 +286,7 @@ static int pet_performance(struct map_session_data *sd, struct pet_data *pd) val = 1; pet_stop_walking(pd,2000<<8); - clif_pet_performance(pd, rnd()%val + 1); + clif->send_petdata(NULL, pd, 4, rnd()%val + 1); pet_lootitem_drop(pd,NULL); return 1; } @@ -304,7 +305,7 @@ static int pet_return_egg(struct map_session_data *sd, struct pet_data *pd) tmp_item.card[2] = GetWord(pd->pet.pet_id,1); tmp_item.card[3] = pd->pet.rename_flag; if((flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } pd->pet.incuvate = 1; @@ -411,11 +412,11 @@ int pet_birth_process(struct map_session_data *sd, struct s_pet *pet) if(sd->bl.prev != NULL) { map_addblock(&sd->pd->bl); - clif_spawn(&sd->pd->bl); - clif_send_petdata(sd,sd->pd, 0,0); - clif_send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style); - clif_pet_equip_area(sd->pd); - clif_send_petstatus(sd); + clif->spawn(&sd->pd->bl); + clif->send_petdata(sd,sd->pd, 0,0); + clif->send_petdata(sd,sd->pd, 5,battle_config.pet_hair_style); + clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); + clif->send_petstatus(sd); } Assert((sd->status.pet_id == 0 || sd->pd == 0) || sd->pd->msd == sd); @@ -452,11 +453,11 @@ int pet_recv_petdata(int account_id,struct s_pet *p,int flag) pet_data_init(sd,p); if(sd->pd && sd->bl.prev != NULL) { map_addblock(&sd->pd->bl); - clif_spawn(&sd->pd->bl); - clif_send_petdata(sd,sd->pd,0,0); - clif_send_petdata(sd,sd->pd,5,battle_config.pet_hair_style); - clif_pet_equip_area(sd->pd); - clif_send_petstatus(sd); + clif->spawn(&sd->pd->bl); + clif->send_petdata(sd,sd->pd,0,0); + clif->send_petdata(sd,sd->pd,5,battle_config.pet_hair_style); + clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); + clif->send_petstatus(sd); } } @@ -483,7 +484,7 @@ int pet_catch_process1(struct map_session_data *sd,int target_class) nullpo_ret(sd); sd->catch_target_class = target_class; - clif_catch_process(sd); + clif->catch_process(sd); return 0; } @@ -498,7 +499,7 @@ int pet_catch_process2(struct map_session_data* sd, int target_id) md = (struct mob_data*)map_id2bl(target_id); if(!md || md->bl.type != BL_MOB || md->bl.prev == NULL) { // Invalid inputs/state, abort capture. - clif_pet_roulette(sd,0); + clif->pet_roulette(sd,0); sd->catch_target_class = -1; sd->itemid = sd->itemindex = -1; return 1; @@ -511,8 +512,8 @@ int pet_catch_process2(struct map_session_data* sd, int target_id) if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS)) sd->catch_target_class = md->class_; if(i < 0 || sd->catch_target_class != md->class_) { - clif_emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them. - clif_pet_roulette(sd,0); + clif->emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them. + clif->pet_roulette(sd,0); sd->catch_target_class = -1; return 1; } @@ -527,13 +528,13 @@ int pet_catch_process2(struct map_session_data* sd, int target_id) { unit_remove_map(&md->bl,CLR_OUTSIGHT); status_kill(&md->bl); - clif_pet_roulette(sd,1); + clif->pet_roulette(sd,1); intif_create_pet(sd->status.account_id,sd->status.char_id,pet_db[i].class_,mob_db(pet_db[i].class_)->lv, pet_db[i].EggID,0,pet_db[i].intimate,100,0,1,pet_db[i].jname); } else { - clif_pet_roulette(sd,0); + clif->pet_roulette(sd,0); sd->catch_target_class = -1; } @@ -569,7 +570,7 @@ int pet_get_egg(int account_id,int pet_id,int flag) tmp_item.card[2] = GetWord(pet_id,1); tmp_item.card[3] = 0; //New pets are not named. if((ret = pc_additem(sd,&tmp_item,1,LOG_TYPE_PICKDROP_PLAYER))) { - clif_additem(sd,0,0,ret); + clif->additem(sd,0,0,ret); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } @@ -582,6 +583,7 @@ static int pet_ai_sub_hard_lootsearch(struct block_list *bl,va_list ap); int pet_menu(struct map_session_data *sd,int menunum) { + struct item_data *egg_id; nullpo_ret(sd); if (sd->pd == NULL) return 1; @@ -589,10 +591,18 @@ int pet_menu(struct map_session_data *sd,int menunum) //You lost the pet already. if(!sd->status.pet_id || sd->pd->pet.intimate <= 0 || sd->pd->pet.incuvate) return 1; + + egg_id = itemdb_exists(sd->pd->petDB->EggID); + if (egg_id) { + if ((egg_id->flag.trade_restriction&0x01) && !pc_inventoryblank(sd)) { + clif->message(sd->fd, msg_txt(451)); // You can't return your pet because your inventory is full. + return 1; + } + } switch(menunum) { case 0: - clif_send_petstatus(sd); + clif->send_petstatus(sd); break; case 1: pet_food(sd, sd->pd); @@ -636,15 +646,15 @@ int pet_change_name_ack(struct map_session_data *sd, char* name, int flag) normalize_name(name," ");//bugreport:3032 if ( !flag || !strlen(name) ) { - clif_displaymessage(sd->fd, msg_txt(280)); // You cannot use this name for your pet. - clif_send_petstatus(sd); //Send status so client knows oet name change got rejected. + clif->message(sd->fd, msg_txt(280)); // You cannot use this name for your pet. + clif->send_petstatus(sd); //Send status so client knows oet name change got rejected. return 0; } memcpy(pd->pet.name, name, NAME_LENGTH); - clif_charnameack (0,&pd->bl); + clif->charnameack (0,&pd->bl); pd->pet.rename_flag = 1; - clif_pet_equip_area(pd); - clif_send_petstatus(sd); + clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); + clif->send_petstatus(sd); return 1; } @@ -660,14 +670,14 @@ int pet_equipitem(struct map_session_data *sd,int index) nameid = sd->status.inventory[index].nameid; if(pd->petDB->AcceID == 0 || nameid != pd->petDB->AcceID || pd->pet.equip != 0) { - clif_equipitemack(sd,0,0,0); + clif->equipitemack(sd,0,0,0); return 1; } pc_delitem(sd,index,1,0,0,LOG_TYPE_OTHER); pd->pet.equip = nameid; status_set_viewdata(&pd->bl, pd->pet.class_); //Updates view_data. - clif_pet_equip_area(pd); + clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); if (battle_config.pet_equip_required) { //Skotlex: start support timers if need unsigned int tick = gettick(); @@ -696,12 +706,12 @@ static int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) nameid = pd->pet.equip; pd->pet.equip = 0; status_set_viewdata(&pd->bl, pd->pet.class_); - clif_pet_equip_area(pd); + clif->send_petdata(NULL, sd->pd, 3, sd->pd->vd.head_bottom); memset(&tmp_item,0,sizeof(tmp_item)); tmp_item.nameid = nameid; tmp_item.identify = 1; if((flag = pc_additem(sd,&tmp_item,1,LOG_TYPE_OTHER))) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&tmp_item,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } if( battle_config.pet_equip_required ) @@ -736,7 +746,7 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd) k=pd->petDB->FoodID; i=pc_search_inventory(sd,k); if(i < 0) { - clif_pet_food(sd,k,0); + clif->pet_food(sd,k,0); return 1; } pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME); @@ -770,22 +780,21 @@ static int pet_food(struct map_session_data *sd, struct pet_data *pd) if( pd->pet.hungry > 100 ) pd->pet.hungry = 100; - clif_send_petdata(sd,pd,2,pd->pet.hungry); - clif_send_petdata(sd,pd,1,pd->pet.intimate); - clif_pet_food(sd,pd->petDB->FoodID,1); + clif->send_petdata(sd,pd,2,pd->pet.hungry); + clif->send_petdata(sd,pd,1,pd->pet.intimate); + clif->pet_food(sd,pd->petDB->FoodID,1); return 0; } static int pet_randomwalk(struct pet_data *pd,unsigned int tick) { - const int retrycount=20; - nullpo_ret(pd); Assert((pd->msd == 0) || (pd->msd->pd == pd)); if(DIFF_TICK(pd->next_walktime,tick) < 0 && unit_can_move(&pd->bl)) { + const int retrycount=20; int i,x,y,c,d=12-pd->move_fail_count; if(d<5) d=5; for(i=0;i<retrycount;i++){ @@ -876,7 +885,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns } } - if(!target && pd->loot && pd->loot->count < pd->loot->max && DIFF_TICK(tick,pd->ud.canact_tick)>0) { + if(!target && pd->loot && pd->msd && pc_has_permission(pd->msd, PC_PERM_TRADE) && pd->loot->count < pd->loot->max && DIFF_TICK(tick,pd->ud.canact_tick)>0) { //Use half the pet's range of sight. map_foreachinrange(pet_ai_sub_hard_lootsearch,&pd->bl, pd->db->range2/2, BL_ITEM,pd,&target); @@ -903,7 +912,7 @@ static int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, uns if (target->type != BL_ITEM) { //enemy targetted - if(!battle_check_range(&pd->bl,target,pd->status.rhw.range)) + if(!battle->check_range(&pd->bl,target,pd->status.rhw.range)) { //Chase if(!unit_walktobl(&pd->bl, target, pd->status.rhw.range, 2)) pet_unlocktarget(pd); //Unreachable target. @@ -1013,7 +1022,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd) it = &pd->loot->item[i]; if(sd){ if((flag = pc_additem(sd,it,it->amount,LOG_TYPE_PICKDROP_PLAYER))){ - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); ditem = ers_alloc(item_drop_ers, struct item_drop); memcpy(&ditem->item_data, it, sizeof(struct item)); ditem->next = dlist->item; @@ -1103,9 +1112,9 @@ int pet_recovery_timer(int tid, unsigned int tick, int id, intptr_t data) if(sd->sc.data[pd->recovery->type]) { //Display a heal animation? //Detoxify is chosen for now. - clif_skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1); + clif->skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1); status_change_end(&sd->bl, pd->recovery->type, INVALID_TIMER); - clif_emotion(&pd->bl, E_OK); + clif->emotion(&pd->bl, E_OK); } pd->recovery->timer = INVALID_TIMER; @@ -1142,7 +1151,7 @@ int pet_heal_timer(int tid, unsigned int tick, int id, intptr_t data) } pet_stop_attack(pd); pet_stop_walking(pd,1); - clif_skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1); + clif->skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1); status_heal(&sd->bl, pd->s_skill->lv,0, 0); pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0); return 0; @@ -1187,7 +1196,7 @@ int pet_skill_support_timer(int tid, unsigned int tick, int id, intptr_t data) pet_stop_attack(pd); pet_stop_walking(pd,1); pd->s_skill->timer=add_timer(tick+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0); - if (skill_get_inf(pd->s_skill->id) & INF_GROUND_SKILL) + if (skill->get_inf(pd->s_skill->id) & INF_GROUND_SKILL) unit_skilluse_pos(&pd->bl, sd->bl.x, sd->bl.y, pd->s_skill->id, pd->s_skill->lv); else unit_skilluse_id(&pd->bl, sd->bl.id, pd->s_skill->id, pd->s_skill->lv); diff --git a/src/map/quest.c b/src/map/quest.c index c7ca06514..3ef162aaa 100644 --- a/src/map/quest.c +++ b/src/map/quest.c @@ -53,8 +53,8 @@ int quest_pc_login(TBL_PC * sd) if(sd->avail_quests == 0) return 1; - clif_quest_send_list(sd); - clif_quest_send_mission(sd); + clif->quest_send_list(sd); + clif->quest_send_mission(sd); return 0; } @@ -97,7 +97,7 @@ int quest_add(TBL_PC * sd, int quest_id) sd->avail_quests++; sd->save_quest = true; - clif_quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); + clif->quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); if( save_settings&64 ) chrif_save(sd,0); @@ -144,8 +144,8 @@ int quest_change(TBL_PC * sd, int qid1, int qid2) sd->quest_index[i] = j; sd->save_quest = true; - clif_quest_delete(sd, qid1); - clif_quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); + clif->quest_delete(sd, qid1); + clif->quest_add(sd, &sd->quest_log[i], sd->quest_index[i]); if( save_settings&64 ) chrif_save(sd,0); @@ -176,7 +176,7 @@ int quest_delete(TBL_PC * sd, int quest_id) sd->quest_index[sd->num_quests] = 0; sd->save_quest = true; - clif_quest_delete(sd, quest_id); + clif->quest_delete(sd, quest_id); if( save_settings&64 ) chrif_save(sd,0); @@ -217,7 +217,7 @@ void quest_update_objective(TBL_PC * sd, int mob) { if( quest_db[sd->quest_index[i]].mob[j] == mob && sd->quest_log[i].count[j] < quest_db[sd->quest_index[i]].count[j] ) { sd->quest_log[i].count[j]++; sd->save_quest = true; - clif_quest_update_objective(sd,&sd->quest_log[i],sd->quest_index[i]); + clif->quest_update_objective(sd,&sd->quest_log[i],sd->quest_index[i]); } } } @@ -236,7 +236,7 @@ int quest_update_status(TBL_PC * sd, int quest_id, quest_state status) { sd->save_quest = true; if( status < Q_COMPLETE ) { - clif_quest_update_status(sd, quest_id, (bool)status); + clif->quest_update_status(sd, quest_id, (bool)status); return 0; } @@ -247,7 +247,7 @@ int quest_update_status(TBL_PC * sd, int quest_id, quest_state status) { memcpy(&sd->quest_log[sd->avail_quests], &tmp_quest,sizeof(struct quest)); } - clif_quest_delete(sd, quest_id); + clif->quest_delete(sd, quest_id); if( save_settings&64 ) chrif_save(sd,0); diff --git a/src/map/script.c b/src/map/script.c index 4099820f1..41f8e7472 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -1,5 +1,6 @@ -// 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 //#define DEBUG_DISP //#define DEBUG_DISASM @@ -49,6 +50,7 @@ #include "script.h" #include "quest.h" #include "elemental.h" +#include "../config/core.h" #include <stdio.h> #include <stdlib.h> @@ -61,110 +63,6 @@ #include <setjmp.h> #include <errno.h> -#ifdef BETA_THREAD_TEST - #include "../common/atomic.h" - #include "../common/spinlock.h" - #include "../common/thread.h" - #include "../common/mutex.h" -#endif - - -/////////////////////////////////////////////////////////////////////////////// -//## TODO possible enhancements: [FlavioJS] -// - 'callfunc' supporting labels in the current npc "::LabelName" -// - 'callfunc' supporting labels in other npcs "NpcName::LabelName" -// - 'function FuncName;' function declarations reverting to global functions -// if local label isn't found -// - join callfunc and callsub's functionality -// - remove dynamic allocation in add_word() -// - remove GETVALUE / SETVALUE -// - clean up the set_reg / set_val / setd_sub mess -// - detect invalid label references at parse-time - -// -// struct script_state* st; -// - -/// Returns the script_data at the target index -#define script_getdata(st,i) ( &((st)->stack->stack_data[(st)->start + (i)]) ) -/// Returns if the stack contains data at the target index -#define script_hasdata(st,i) ( (st)->end > (st)->start + (i) ) -/// Returns the index of the last data in the stack -#define script_lastdata(st) ( (st)->end - (st)->start - 1 ) -/// Pushes an int into the stack -#define script_pushint(st,val) push_val((st)->stack, C_INT, (val)) -/// Pushes a string into the stack (script engine frees it automatically) -#define script_pushstr(st,val) push_str((st)->stack, C_STR, (val)) -/// Pushes a copy of a string into the stack -#define script_pushstrcopy(st,val) push_str((st)->stack, C_STR, aStrdup(val)) -/// Pushes a constant string into the stack (must never change or be freed) -#define script_pushconststr(st,val) push_str((st)->stack, C_CONSTSTR, (val)) -/// Pushes a nil into the stack -#define script_pushnil(st) push_val((st)->stack, C_NOP, 0) -/// Pushes a copy of the data in the target index -#define script_pushcopy(st,i) push_copy((st)->stack, (st)->start + (i)) - -#define script_isstring(st,i) data_isstring(script_getdata(st,i)) -#define script_isint(st,i) data_isint(script_getdata(st,i)) - -#define script_getnum(st,val) conv_num(st, script_getdata(st,val)) -#define script_getstr(st,val) conv_str(st, script_getdata(st,val)) -#define script_getref(st,val) ( script_getdata(st,val)->ref ) - -// Note: "top" functions/defines use indexes relative to the top of the stack -// -1 is the index of the data at the top - -/// Returns the script_data at the target index relative to the top of the stack -#define script_getdatatop(st,i) ( &((st)->stack->stack_data[(st)->stack->sp + (i)]) ) -/// Pushes a copy of the data in the target index relative to the top of the stack -#define script_pushcopytop(st,i) push_copy((st)->stack, (st)->stack->sp + (i)) -/// Removes the range of values [start,end[ relative to the top of the stack -#define script_removetop(st,start,end) ( pop_stack((st), ((st)->stack->sp + (start)), (st)->stack->sp + (end)) ) - -// -// struct script_data* data; -// - -/// Returns if the script data is a string -#define data_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR ) -/// Returns if the script data is an int -#define data_isint(data) ( (data)->type == C_INT ) -/// Returns if the script data is a reference -#define data_isreference(data) ( (data)->type == C_NAME ) -/// Returns if the script data is a label -#define data_islabel(data) ( (data)->type == C_POS ) -/// Returns if the script data is an internal script function label -#define data_isfunclabel(data) ( (data)->type == C_USERFUNC_POS ) - -/// Returns if this is a reference to a constant -#define reference_toconstant(data) ( str_data[reference_getid(data)].type == C_INT ) -/// Returns if this a reference to a param -#define reference_toparam(data) ( str_data[reference_getid(data)].type == C_PARAM ) -/// Returns if this a reference to a variable -//##TODO confirm it's C_NAME [FlavioJS] -#define reference_tovariable(data) ( str_data[reference_getid(data)].type == C_NAME ) -/// Returns the unique id of the reference (id and index) -#define reference_getuid(data) ( (data)->u.num ) -/// Returns the id of the reference -#define reference_getid(data) ( (int32)(reference_getuid(data) & 0x00ffffff) ) -/// Returns the array index of the reference -#define reference_getindex(data) ( (int32)(((uint32)(reference_getuid(data) & 0xff000000)) >> 24) ) -/// Returns the name of the reference -#define reference_getname(data) ( str_buf + str_data[reference_getid(data)].str ) -/// Returns the linked list of uid-value pairs of the reference (can be NULL) -#define reference_getref(data) ( (data)->ref ) -/// Returns the value of the constant -#define reference_getconstant(data) ( str_data[reference_getid(data)].val ) -/// Returns the type of param -#define reference_getparamtype(data) ( str_data[reference_getid(data)].val ) - -/// Composes the uid of a reference from the id and the index -#define reference_uid(id,idx) ( (int32)((((uint32)(id)) & 0x00ffffff) | (((uint32)(idx)) << 24)) ) - -#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.' && (prefix) != '\'') -#define not_array_variable(prefix) ( (prefix) != '$' && (prefix) != '@' && (prefix) != '.' && (prefix) != '\'' ) -#define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' ) - #define FETCH(n, t) \ if( script_hasdata(st,n) ) \ (t)=script_getnum(st,n); @@ -198,7 +96,7 @@ static struct str_data_struct { int str; int backpatch; int label; - int (*func)(struct script_state *st); + bool (*func)(struct script_state *st); int val; int next; } *str_data = NULL; @@ -303,40 +201,8 @@ int potion_target=0; c_op get_com(unsigned char *script,int *pos); int get_num(unsigned char *script,int *pos); -typedef struct script_function { - int (*func)(struct script_state *st); - const char *name; - const char *arg; -} script_function; - -extern script_function buildin_func[]; - static struct linkdb_node* sleep_db;// int oid -> struct script_state* -#ifdef BETA_THREAD_TEST -/** - * MySQL Query Slave - **/ -static SPIN_LOCK queryThreadLock; -static rAthread queryThread = NULL; -static ramutex queryThreadMutex = NULL; -static racond queryThreadCond = NULL; -static volatile int32 queryThreadTerminate = 0; - -struct queryThreadEntry { - bool ok; - bool type; /* main db or log db? */ - struct script_state *st; -}; - -/* Ladies and Gentleman the Manager! */ -struct { - struct queryThreadEntry **entry;/* array of structs */ - int count; - int timer;/* used to receive processed entries */ -} queryThreadData; -#endif - /*========================================== * (Only those needed) local declaration prototype *------------------------------------------*/ @@ -364,13 +230,8 @@ enum { MF_FOG, MF_SAKURA, MF_LEAVES, - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //MF_RAIN, //20 - // 21 free - MF_NOGO = 22, - MF_CLOUDS, + /* 21 - 22 free */ + MF_CLOUDS = 23, MF_CLOUDS2, MF_FIREWORKS, MF_GVG_CASTLE, @@ -383,7 +244,7 @@ enum { MF_NORETURN, MF_NOWARPTO, MF_NIGHTMAREDROP, - MF_RESTRICTED, + MF_ZONE, MF_NOCOMMAND, MF_NODROP, MF_JEXP, @@ -506,20 +367,19 @@ static void script_reportsrc(struct script_state *st) if( bl == NULL ) return; - switch( bl->type ) - { - case BL_NPC: - if( bl->m >= 0 ) - ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y); - else - ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name); - break; - default: - if( bl->m >= 0 ) - ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y); - else - ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl)); - break; + switch( bl->type ) { + case BL_NPC: + if( bl->m >= 0 ) + ShowDebug("Source (NPC): %s at %s (%d,%d)\n", ((struct npc_data *)bl)->name, map[bl->m].name, bl->x, bl->y); + else + ShowDebug("Source (NPC): %s (invisible/not on a map)\n", ((struct npc_data *)bl)->name); + break; + default: + if( bl->m >= 0 ) + ShowDebug("Source (Non-NPC type %d): name %s at %s (%d,%d)\n", bl->type, status_get_name(bl), map[bl->m].name, bl->x, bl->y); + else + ShowDebug("Source (Non-NPC type %d): name %s (invisible/not on a map)\n", bl->type, status_get_name(bl)); + break; } } @@ -528,54 +388,43 @@ static void script_reportdata(struct script_data* data) { if( data == NULL ) return; - switch( data->type ) - { - case C_NOP:// no value - ShowDebug("Data: nothing (nil)\n"); - break; - case C_INT:// number - ShowDebug("Data: number value=%d\n", data->u.num); - break; - case C_STR: - case C_CONSTSTR:// string - if( data->u.str ) - { - ShowDebug("Data: string value=\"%s\"\n", data->u.str); - } - else - { - ShowDebug("Data: string value=NULL\n"); - } - break; - case C_NAME:// reference - if( reference_tovariable(data) ) - {// variable - const char* name = reference_getname(data); - if( not_array_variable(*name) ) - ShowDebug("Data: variable name='%s'\n", name); - else - ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data)); - } - else if( reference_toconstant(data) ) - {// constant - ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data)); - } - else if( reference_toparam(data) ) - {// param - ShowDebug("Data: param name='%s' type=%d\n", reference_getname(data), reference_getparamtype(data)); - } - else - {// ??? - ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script_op2name(data->type)); - ShowDebug("Please report this!!! - str_data.type=%s\n", script_op2name(str_data[reference_getid(data)].type)); - } - break; - case C_POS:// label - ShowDebug("Data: label pos=%d\n", data->u.num); - break; - default: - ShowDebug("Data: %s\n", script_op2name(data->type)); - break; + switch( data->type ) { + case C_NOP:// no value + ShowDebug("Data: nothing (nil)\n"); + break; + case C_INT:// number + ShowDebug("Data: number value=%d\n", data->u.num); + break; + case C_STR: + case C_CONSTSTR:// string + if( data->u.str ) { + ShowDebug("Data: string value=\"%s\"\n", data->u.str); + } else { + ShowDebug("Data: string value=NULL\n"); + } + break; + case C_NAME:// reference + if( reference_tovariable(data) ) {// variable + const char* name = reference_getname(data); + if( not_array_variable(*name) ) + ShowDebug("Data: variable name='%s'\n", name); + else + ShowDebug("Data: variable name='%s' index=%d\n", name, reference_getindex(data)); + } else if( reference_toconstant(data) ) {// constant + ShowDebug("Data: constant name='%s' value=%d\n", reference_getname(data), reference_getconstant(data)); + } else if( reference_toparam(data) ) {// param + ShowDebug("Data: param name='%s' type=%d\n", reference_getname(data), reference_getparamtype(data)); + } else {// ??? + ShowDebug("Data: reference name='%s' type=%s\n", reference_getname(data), script_op2name(data->type)); + ShowDebug("Please report this!!! - str_data.type=%s\n", script_op2name(str_data[reference_getid(data)].type)); + } + break; + case C_POS:// label + ShowDebug("Data: label pos=%d\n", data->u.num); + break; + default: + ShowDebug("Data: %s\n", script_op2name(data->type)); + break; } } @@ -807,33 +656,33 @@ static void add_scriptl(int l) int backpatch = str_data[l].backpatch; switch(str_data[l].type){ - case C_POS: - case C_USERFUNC_POS: - add_scriptc(C_POS); - add_scriptb(str_data[l].label); - add_scriptb(str_data[l].label>>8); - add_scriptb(str_data[l].label>>16); - break; - case C_NOP: - case C_USERFUNC: - // Embedded data backpatch there is a possibility of label - add_scriptc(C_NAME); - str_data[l].backpatch = script_pos; - add_scriptb(backpatch); - add_scriptb(backpatch>>8); - add_scriptb(backpatch>>16); - break; - case C_INT: - add_scripti(abs(str_data[l].val)); - if( str_data[l].val < 0 ) //Notice that this is negative, from jA (Rayce) - add_scriptc(C_NEG); - break; - default: // assume C_NAME - add_scriptc(C_NAME); - add_scriptb(l); - add_scriptb(l>>8); - add_scriptb(l>>16); - break; + case C_POS: + case C_USERFUNC_POS: + add_scriptc(C_POS); + add_scriptb(str_data[l].label); + add_scriptb(str_data[l].label>>8); + add_scriptb(str_data[l].label>>16); + break; + case C_NOP: + case C_USERFUNC: + // Embedded data backpatch there is a possibility of label + add_scriptc(C_NAME); + str_data[l].backpatch = script_pos; + add_scriptb(backpatch); + add_scriptb(backpatch>>8); + add_scriptb(backpatch>>16); + break; + case C_INT: + add_scripti(abs(str_data[l].val)); + if( str_data[l].val < 0 ) //Notice that this is negative, from jA (Rayce) + add_scriptc(C_NEG); + break; + default: // assume C_NAME + add_scriptc(C_NAME); + add_scriptb(l); + add_scriptb(l>>8); + add_scriptb(l>>16); + break; } } @@ -961,8 +810,8 @@ int add_word(const char* p) static const char* parse_callfunc(const char* p, int require_paren, int is_custom) { - const char* p2; - const char* arg=NULL; + const char *p2; + char *arg = NULL; int func; func = add_word(p); @@ -970,13 +819,13 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) // buildin function add_scriptl(func); add_scriptc(C_ARG); - arg = buildin_func[str_data[func].val].arg; + arg = script->buildin[str_data[func].val]; } else if( str_data[func].type == C_USERFUNC || str_data[func].type == C_USERFUNC_POS ){ // script defined function add_scriptl(buildin_callsub_ref); add_scriptc(C_ARG); add_scriptl(func); - arg = buildin_func[str_data[buildin_callsub_ref].val].arg; + arg = script->buildin[str_data[buildin_callsub_ref].val]; if( *arg == 0 ) disp_error_message("parse_callfunc: callsub has no arguments, please review it's definition",p); if( *arg != '*' ) @@ -994,7 +843,7 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) add_scriptc(C_STR); while( *name ) add_scriptb(*name ++); add_scriptb(0); - arg = buildin_func[str_data[buildin_callfunc_ref].val].arg; + arg = script->buildin[str_data[buildin_callfunc_ref].val]; if( *arg != '*' ) ++ arg; } #endif @@ -1016,8 +865,7 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) {// <func name> syntax.curly[syntax.curly_count].flag = ARGLIST_NO_PAREN; */ - } else - {// <func name> <arg list> + } else {// <func name> <arg list> if( require_paren ){ if( *p != '(' ) disp_error_message("need '('",p); @@ -1043,7 +891,7 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom) } --syntax.curly_count; } - if( *arg && *arg != '?' && *arg != '*' ) + if( arg && *arg && *arg != '?' && *arg != '*' ) disp_error_message2("parse_callfunc: not enough arguments, expected ','", p, script_config.warn_func_mismatch_paramnum); if( syntax.curly[syntax.curly_count].type != TYPE_ARGLIST ) disp_error_message("parse_callfunc: DEBUG last curly is not an argument list",p); @@ -1247,18 +1095,16 @@ const char* parse_simpleexpr(const char *p) add_scriptc(C_STR); p++; while( *p && *p != '"' ){ - if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) - { + if( (unsigned char)p[-1] <= 0x7e && *p == '\\' ) { char buf[8]; - size_t len = skip_escaped_c(p) - p; - size_t n = sv_unescape_c(buf, p, len); + size_t len = sv->skip_escaped_c(p) - p; + size_t n = sv->unescape_c(buf, p, len); if( n != 1 ) ShowDebug("parse_simpleexpr: unexpected length %d after unescape (\"%.*s\" -> %.*s)\n", (int)n, (int)len, p, (int)n, buf); p += len; add_scriptb(*buf); continue; - } - else if( *p == '\n' ) + } else if( *p == '\n' ) disp_error_message("parse_simpleexpr: unexpected newline @ string",p); add_scriptb(*p++); } @@ -1609,9 +1455,9 @@ const char* parse_syntax(const char* p) set_label(l,script_pos,p); } // check duplication of case label [Rayce] - if(linkdb_search(&syntax.curly[pos].case_label, (void*)__64BPRTSIZE(v)) != NULL) + if(linkdb_search(&syntax.curly[pos].case_label, (void*)__64BPTRSIZE(v)) != NULL) disp_error_message("parse_syntax: dup 'case'",p); - linkdb_insert(&syntax.curly[pos].case_label, (void*)__64BPRTSIZE(v), (void*)1); + linkdb_insert(&syntax.curly[pos].case_label, (void*)__64BPTRSIZE(v), (void*)1); sprintf(label,"set $@__SW%x_VAL,0;",syntax.curly[pos].index); syntax.curly[syntax.curly_count++].type = TYPE_NULL; @@ -2121,45 +1967,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag) } } -/*========================================== - * Added built-in functions - *------------------------------------------*/ -static void add_buildin_func(void) -{ - int i,n; - const char* p; - for( i = 0; buildin_func[i].func; i++ ) - { - // arg must follow the pattern: (v|s|i|r|l)*\?*\*? - // 'v' - value (either string or int or reference) - // 's' - string - // 'i' - int - // 'r' - reference (of a variable) - // 'l' - label - // '?' - one optional parameter - // '*' - unknown number of optional parameters - p = buildin_func[i].arg; - while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p; - while( *p == '?' ) ++p; - if( *p == '*' ) ++p; - if( *p != 0){ - ShowWarning("add_buildin_func: ignoring function \"%s\" with invalid arg \"%s\".\n", buildin_func[i].name, buildin_func[i].arg); - } else if( *skip_word(buildin_func[i].name) != 0 ){ - ShowWarning("add_buildin_func: ignoring function with invalid name \"%s\" (must be a word).\n", buildin_func[i].name); - } else { - n = add_str(buildin_func[i].name); - str_data[n].type = C_FUNC; - str_data[n].val = i; - str_data[n].func = buildin_func[i].func; - - if (!strcmp(buildin_func[i].name, "set")) buildin_set_ref = n; - else if (!strcmp(buildin_func[i].name, "callsub")) buildin_callsub_ref = n; - else if (!strcmp(buildin_func[i].name, "callfunc")) buildin_callfunc_ref = n; - else if( !strcmp(buildin_func[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n; - } - } -} - /// Retrieves the value of a constant. bool script_get_constant(const char* name, int* value) { @@ -2231,16 +2038,16 @@ static const char* script_print_line(StringBuf* buf, const char* p, const char* int i; if( p == NULL || !p[0] ) return NULL; if( line < 0 ) - StringBuf_Printf(buf, "*% 5d : ", -line); + StrBuf->Printf(buf, "*% 5d : ", -line); else - StringBuf_Printf(buf, " % 5d : ", line); + StrBuf->Printf(buf, " % 5d : ", line); for(i=0;p[i] && p[i] != '\n';i++){ if(p + i != mark) - StringBuf_Printf(buf, "%c", p[i]); + StrBuf->Printf(buf, "%c", p[i]); else - StringBuf_Printf(buf, "\'%c\'", p[i]); + StrBuf->Printf(buf, "\'%c\'", p[i]); } - StringBuf_AppendStr(buf, "\n"); + StrBuf->AppendStr(buf, "\n"); return p+i+(p[i] == '\n' ? 1 : 0); } @@ -2265,10 +2072,10 @@ void script_error(const char* src, const char* file, int start_line, const char* p=lineend+1; } - StringBuf_Init(&buf); - StringBuf_AppendStr(&buf, "\a\n"); - StringBuf_Printf(&buf, "script error on %s line %d\n", file, line); - StringBuf_Printf(&buf, " %s\n", error_msg); + StrBuf->Init(&buf); + StrBuf->AppendStr(&buf, "\a\n"); + StrBuf->Printf(&buf, "script error on %s line %d\n", file, line); + StrBuf->Printf(&buf, " %s\n", error_msg); for(j = 0; j < 5; j++ ) { script_print_line(&buf, linestart[j], NULL, line + j - 5); } @@ -2276,8 +2083,8 @@ void script_error(const char* src, const char* file, int start_line, const char* for(j = 0; j < 5; j++) { p = script_print_line(&buf, p, NULL, line + j + 1 ); } - ShowError("%s", StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); + ShowError("%s", StrBuf->Value(&buf)); + StrBuf->Destroy(&buf); } /*========================================== @@ -2288,7 +2095,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o const char *p,*tmpp; int i; struct script_code* code = NULL; - static int first=1; char end; bool unresolved_names = false; @@ -2296,11 +2102,6 @@ struct script_code* parse_script(const char *src,const char *file,int line,int o return NULL;// empty script memset(&syntax,0,sizeof(syntax)); - if(first){ - add_buildin_func(); - read_constdb(); - first=0; - } script_buf=(unsigned char *)aMalloc(SCRIPT_BLOCK_SIZE*sizeof(unsigned char)); script_pos=0; @@ -2649,7 +2450,7 @@ void* get_val2(struct script_state* st, int uid, struct DBMap** ref) push_val2(st->stack, C_NAME, uid, ref); data = script_getdatatop(st, -1); get_val(st, data); - return (data->type == C_INT ? (void*)__64BPRTSIZE(data->u.num) : (void*)__64BPRTSIZE(data->u.str)); + return (data->type == C_INT ? (void*)__64BPTRSIZE(data->u.num) : (void*)__64BPTRSIZE(data->u.str)); } /*========================================== @@ -2694,7 +2495,7 @@ static int set_reg(struct script_state* st, TBL_PC* sd, int num, const char* nam } else {// integer variable - int val = (int)__64BPRTSIZE(value); + int val = (int)__64BPTRSIZE(value); if(str_data[num&0x00ffffff].type == C_PARAM) { if( pc_setparam(sd, str_data[num&0x00ffffff].val, val) == 0 ) @@ -2788,8 +2589,7 @@ const char* conv_str(struct script_state* st, struct script_data* data) } /// Converts the data to an int -int conv_num(struct script_state* st, struct script_data* data) -{ +int conv_num(struct script_state* st, struct script_data* data) { char* p; long num; @@ -3016,6 +2816,7 @@ struct script_state* script_alloc_state(struct script_code* script, int pos, int st->rid = rid; st->oid = oid; st->sleep.timer = INVALID_TIMER; + st->npc_item_flag = battle_config.item_enabled_npc; return st; } @@ -3248,11 +3049,11 @@ void op_2(struct script_state *st, int op) case C_ADD: if( data_isint(left) && data_isstring(right) ) {// convert int-string to string-string - conv_str(st, left); + script->conv_str(st, left); } else if( data_isstring(left) && data_isint(right) ) {// convert string-int to string-string - conv_str(st, right); + script->conv_str(st, right); } break; } @@ -3339,26 +3140,20 @@ static void script_check_buildin_argtype(struct script_state* st, int func) { char type; int idx, invalid = 0; - script_function* sf = &buildin_func[str_data[func].val]; + char* sf = script->buildin[str_data[func].val]; - for( idx = 2; script_hasdata(st, idx); idx++ ) - { + for( idx = 2; script_hasdata(st, idx); idx++ ) { struct script_data* data = script_getdata(st, idx); - type = sf->arg[idx-2]; - - if( type == '?' || type == '*' ) - {// optional argument or unknown number of optional parameters ( no types are after this ) + type = sf[idx-2]; + + if( type == '?' || type == '*' ) {// optional argument or unknown number of optional parameters ( no types are after this ) break; - } - else if( type == 0 ) - {// more arguments than necessary ( should not happen, as it is checked before ) + } else if( type == 0 ) {// more arguments than necessary ( should not happen, as it is checked before ) ShowWarning("Found more arguments than necessary. unexpected arg type %s\n",script_op2name(data->type)); invalid++; break; - } - else - { + } else { const char* name = NULL; if( data_isreference(data) ) @@ -3366,8 +3161,7 @@ static void script_check_buildin_argtype(struct script_state* st, int func) name = reference_getname(data); } - switch( type ) - { + switch( type ) { case 'v': if( !data_isstring(data) && !data_isint(data) && !data_isreference(data) ) {// variant @@ -3412,8 +3206,7 @@ static void script_check_buildin_argtype(struct script_state* st, int func) } } - if(invalid) - { + if(invalid) { ShowDebug("Function: %s\n", get_str(func)); script_reportsrc(st); } @@ -3460,7 +3253,7 @@ int run_func(struct script_state *st) } if(str_data[func].func){ - if (str_data[func].func(st)) //Report error + if (!(str_data[func].func(st))) //Report error script_reportsrc(st); } else { ShowError("script:run_func: '%s' (id=%d type=%s) has no C function. please report this!!!\n", get_str(func), func, script_op2name(str_data[func].type)); @@ -3527,7 +3320,7 @@ void script_stop_sleeptimers(int id) struct script_state* st; for(;;) { - st = (struct script_state*)linkdb_erase(&sleep_db,(void*)__64BPRTSIZE(id)); + st = (struct script_state*)linkdb_erase(&sleep_db,(void*)__64BPTRSIZE(id)); if( st == NULL ) break; // no more sleep timers script_free_state(st); @@ -3569,7 +3362,7 @@ int run_script_timer(int tid, unsigned int tick, int id, intptr_t data) st->state = END; } while( node && st->sleep.timer != INVALID_TIMER ) { - if( (int)__64BPRTSIZE(node->key) == st->oid && ((struct script_state *)node->data)->sleep.timer == st->sleep.timer ) { + if( (int)__64BPTRSIZE(node->key) == st->oid && ((struct script_state *)node->data)->sleep.timer == st->sleep.timer ) { script_erase_sleepdb(node); st->sleep.timer = INVALID_TIMER; break; @@ -3590,30 +3383,26 @@ static void script_detach_state(struct script_state* st, bool dequeue_event) { struct map_session_data* sd; - if(st->rid && (sd = map_id2sd(st->rid))!=NULL) - { + if(st->rid && (sd = map_id2sd(st->rid))!=NULL) { sd->st = st->bk_st; sd->npc_id = st->bk_npcid; - /** - * For the Secure NPC Timeout option (check config/Secure.h) [RR] - **/ - #if SECURE_NPCTIMEOUT - /** - * We're done with this NPC session, so we cancel the timer (if existent) and move on - **/ - if( sd->npc_idle_timer != INVALID_TIMER ) { - delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer); - sd->npc_idle_timer = INVALID_TIMER; - } - #endif - if(st->bk_st) - { + if(st->bk_st) { //Remove tag for removal. st->bk_st = NULL; st->bk_npcid = 0; - } - else if(dequeue_event) - { + } else if(dequeue_event) { + /** + * For the Secure NPC Timeout option (check config/Secure.h) [RR] + **/ +#ifdef SECURE_NPCTIMEOUT + /** + * We're done with this NPC session, so we cancel the timer (if existent) and move on + **/ + if( sd->npc_idle_timer != INVALID_TIMER ) { + delete_timer(sd->npc_idle_timer,npc_rr_secure_timeout_timer); + sd->npc_idle_timer = INVALID_TIMER; + } +#endif npc_event_dequeue(sd); } } @@ -3647,10 +3436,11 @@ static void script_attach_state(struct script_state* st) } sd->st = st; sd->npc_id = st->oid; + sd->npc_item_flag = st->npc_item_flag; // load default. /** * For the Secure NPC Timeout option (check config/Secure.h) [RR] **/ -#if SECURE_NPCTIMEOUT +#ifdef SECURE_NPCTIMEOUT if( sd->npc_idle_timer == INVALID_TIMER ) sd->npc_idle_timer = add_timer(gettick() + (SECURE_NPCTIMEOUT_INTERVAL*1000),npc_rr_secure_timeout_timer,sd->bl.id,0); sd->npc_idle_tick = gettick(); @@ -3778,7 +3568,7 @@ void run_script_main(struct script_state *st) st->sleep.charid = sd?sd->status.char_id:0; st->sleep.timer = add_timer(gettick()+st->sleep.tick, run_script_timer, st->sleep.charid, (intptr_t)st); - linkdb_insert(&sleep_db, (void*)__64BPRTSIZE(st->oid), st); + linkdb_insert(&sleep_db, (void*)__64BPTRSIZE(st->oid), st); } else if(st->state != END && st->rid){ //Resume later (st is already attached to player). @@ -3798,7 +3588,7 @@ void run_script_main(struct script_state *st) if ((sd = map_id2sd(st->rid))!=NULL) { //Restore previous stack and save char. if(sd->state.using_fake_npc){ - clif_clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); + clif->clearunit_single(sd->npc_id, CLR_OUTSIGHT, sd->fd); sd->state.using_fake_npc = 0; } //Restore previous script if any. @@ -3868,7 +3658,7 @@ int script_config_read(char *cfgName) */ static int db_script_free_code_sub(DBKey key, DBData *data, va_list ap) { - struct script_code *code = db_data2ptr(data); + struct script_code *code = DB->data2ptr(data); if (code) script_free_code(code); return 0; @@ -3922,7 +3712,7 @@ void script_cleararray_pc(struct map_session_data* sd, const char* varname, void { for( idx = 0; idx < SCRIPT_MAX_ARRAYSIZE; idx++ ) { - pc_setreg(sd, reference_uid(key, idx), (int)__64BPRTSIZE(value)); + pc_setreg(sd, reference_uid(key, idx), (int)__64BPTRSIZE(value)); } } } @@ -3954,7 +3744,7 @@ void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 } else { - pc_setreg(sd, reference_uid(key, idx), (int)__64BPRTSIZE(value)); + pc_setreg(sd, reference_uid(key, idx), (int)__64BPTRSIZE(value)); } if( refcache ) @@ -3962,179 +3752,10 @@ void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 refcache[0] = key; } } -#ifdef BETA_THREAD_TEST -int buildin_query_sql_sub(struct script_state* st, Sql* handle); - -/* used to receive items the queryThread has already processed */ -int queryThread_timer(int tid, unsigned int tick, int id, intptr_t data) { - int i, cursor = 0; - bool allOk = true; - - EnterSpinLock(&queryThreadLock); - - for( i = 0; i < queryThreadData.count; i++ ) { - struct queryThreadEntry *entry = queryThreadData.entry[i]; - - if( !entry->ok ) { - allOk = false; - continue; - } - - run_script_main(entry->st); - - entry->st = NULL;/* empty entries */ - aFree(entry); - queryThreadData.entry[i] = NULL; - } - - - if( allOk ) { - /* cancel the repeating timer -- it'll re-create itself when necessary, dont need to remain looping */ - delete_timer(queryThreadData.timer, queryThread_timer); - queryThreadData.timer = INVALID_TIMER; - } - - /* now lets clear the mess. */ - for( i = 0; i < queryThreadData.count; i++ ) { - struct queryThreadEntry *entry = queryThreadData.entry[i]; - if( entry == NULL ) - continue;/* entry on hold */ - - /* move */ - memmove(&queryThreadData.entry[cursor], &queryThreadData.entry[i], sizeof(struct queryThreadEntry*)); - - cursor++; - } - - queryThreadData.count = cursor; - - LeaveSpinLock(&queryThreadLock); - - return 0; -} - -void queryThread_add(struct script_state *st, bool type) { - int idx = 0; - struct queryThreadEntry* entry = NULL; - - EnterSpinLock(&queryThreadLock); - - if( queryThreadData.count++ != 0 ) - RECREATE(queryThreadData.entry, struct queryThreadEntry* , queryThreadData.count); - - idx = queryThreadData.count-1; - - CREATE(queryThreadData.entry[idx],struct queryThreadEntry,1); - - entry = queryThreadData.entry[idx]; - - entry->st = st; - entry->ok = false; - entry->type = type; - if( queryThreadData.timer == INVALID_TIMER ) { /* start the receiver timer */ - queryThreadData.timer = add_timer_interval(gettick() + 100, queryThread_timer, 0, 0, 100); - } - - LeaveSpinLock(&queryThreadLock); - - /* unlock the queryThread */ - racond_signal(queryThreadCond); -} -/* adds a new log to the queue */ -void queryThread_log(char * entry, int length) { - int idx = logThreadData.count; - - EnterSpinLock(&queryThreadLock); - - if( logThreadData.count++ != 0 ) - RECREATE(logThreadData.entry, char* , logThreadData.count); - - CREATE(logThreadData.entry[idx], char, length + 1 ); - safestrncpy(logThreadData.entry[idx], entry, length + 1 ); - - LeaveSpinLock(&queryThreadLock); - - /* unlock the queryThread */ - racond_signal(queryThreadCond); -} - -/* queryThread_main */ -static void *queryThread_main(void *x) { - Sql *queryThread_handle = Sql_Malloc(); - int i; - - if ( SQL_ERROR == Sql_Connect(queryThread_handle, map_server_id, map_server_pw, map_server_ip, map_server_port, map_server_db) ) - exit(EXIT_FAILURE); - - if( strlen(default_codepage) > 0 ) - if ( SQL_ERROR == Sql_SetEncoding(queryThread_handle, default_codepage) ) - Sql_ShowDebug(queryThread_handle); - - if( log_config.sql_logs ) { - logmysql_handle = Sql_Malloc(); - - if ( SQL_ERROR == Sql_Connect(logmysql_handle, log_db_id, log_db_pw, log_db_ip, log_db_port, log_db_db) ) - exit(EXIT_FAILURE); - - if( strlen(default_codepage) > 0 ) - if ( SQL_ERROR == Sql_SetEncoding(logmysql_handle, default_codepage) ) - Sql_ShowDebug(logmysql_handle); - } - - while( 1 ) { - - if(queryThreadTerminate > 0) - break; - - EnterSpinLock(&queryThreadLock); - - /* mess with queryThreadData within the lock */ - for( i = 0; i < queryThreadData.count; i++ ) { - struct queryThreadEntry *entry = queryThreadData.entry[i]; - - if( entry->ok ) - continue; - else if ( !entry->st || !entry->st->stack ) { - entry->ok = true;/* dispose */ - continue; - } - - buildin_query_sql_sub(entry->st, entry->type ? logmysql_handle : queryThread_handle); - - entry->ok = true;/* we're done with this */ - } - - /* also check for any logs in need to be sent */ - if( log_config.sql_logs ) { - for( i = 0; i < logThreadData.count; i++ ) { - if( SQL_ERROR == Sql_Query(logmysql_handle, logThreadData.entry[i]) ) - Sql_ShowDebug(logmysql_handle); - aFree(logThreadData.entry[i]); - } - logThreadData.count = 0; - } - - LeaveSpinLock(&queryThreadLock); - - ramutex_lock( queryThreadMutex ); - racond_wait( queryThreadCond, queryThreadMutex, -1 ); - ramutex_unlock( queryThreadMutex ); - - } - - Sql_Free(queryThread_handle); - - if( log_config.sql_logs ) { - Sql_Free(logmysql_handle); - } - - return NULL; -} -#endif /*========================================== * Destructor *------------------------------------------*/ -int do_final_script() { +void do_final_script(void) { int i; #ifdef DEBUG_HASH if (battle_config.etc_log) @@ -4211,107 +3832,49 @@ int do_final_script() { if (str_buf) aFree(str_buf); - for( i = 0; i < atcmd_binding_count; i++ ) { - aFree(atcmd_binding[i]); + for( i = 0; i < atcommand->binding_count; i++ ) { + aFree(atcommand->binding[i]); } - if( atcmd_binding_count != 0 ) - aFree(atcmd_binding); -#ifdef BETA_THREAD_TEST - /* QueryThread */ - InterlockedIncrement(&queryThreadTerminate); - racond_signal(queryThreadCond); - rathread_wait(queryThread, NULL); - - // Destroy cond var and mutex. - racond_destroy( queryThreadCond ); - ramutex_destroy( queryThreadMutex ); - - /* Clear missing vars */ - for( i = 0; i < queryThreadData.count; i++ ) { - aFree(queryThreadData.entry[i]); - } - - aFree(queryThreadData.entry); - - for( i = 0; i < logThreadData.count; i++ ) { - aFree(logThreadData.entry[i]); + if( atcommand->binding_count != 0 ) + aFree(atcommand->binding); + + for( i = 0; i < script->buildin_count; i++) { + if( script->buildin[i] ) { + aFree(script->buildin[i]); + script->buildin[i] = NULL; + } } + + aFree(script->buildin); - aFree(logThreadData.entry); -#endif - - return 0; } /*========================================== * Initialization *------------------------------------------*/ -int do_init_script() { - userfunc_db=strdb_alloc(DB_OPT_DUP_KEY,0); - scriptlabel_db=strdb_alloc(DB_OPT_DUP_KEY,50); +void do_init_script(void) { + userfunc_db = strdb_alloc(DB_OPT_DUP_KEY,0); + scriptlabel_db = strdb_alloc(DB_OPT_DUP_KEY,50); autobonus_db = strdb_alloc(DB_OPT_DUP_KEY,0); - + script->parse_builtin(); + read_constdb(); mapreg_init(); -#ifdef BETA_THREAD_TEST - CREATE(queryThreadData.entry, struct queryThreadEntry*, 1); - queryThreadData.count = 0; - CREATE(logThreadData.entry, char *, 1); - logThreadData.count = 0; - /* QueryThread Start */ - - InitializeSpinLock(&queryThreadLock); - - queryThreadData.timer = INVALID_TIMER; - queryThreadTerminate = 0; - queryThreadMutex = ramutex_create(); - queryThreadCond = racond_create(); - - queryThread = rathread_create(queryThread_main, NULL); - - if(queryThread == NULL){ - ShowFatalError("do_init_script: cannot spawn Query Thread.\n"); - exit(EXIT_FAILURE); - } - - add_timer_func_list(queryThread_timer, "queryThread_timer"); -#endif - return 0; } int script_reload() { int i; -#ifdef BETA_THREAD_TEST - /* we're reloading so any queries undergoing should be...exterminated. */ - EnterSpinLock(&queryThreadLock); - - for( i = 0; i < queryThreadData.count; i++ ) { - aFree(queryThreadData.entry[i]); - } - queryThreadData.count = 0; - - if( queryThreadData.timer != INVALID_TIMER ) { - delete_timer(queryThreadData.timer, queryThread_timer); - queryThreadData.timer = INVALID_TIMER; - } - - LeaveSpinLock(&queryThreadLock); -#endif - - userfunc_db->clear(userfunc_db, db_script_free_code_sub); db_clear(scriptlabel_db); - // @commands (script based) - // Clear bindings - for( i = 0; i < atcmd_binding_count; i++ ) { - aFree(atcmd_binding[i]); + for( i = 0; i < atcommand->binding_count; i++ ) { + aFree(atcommand->binding[i]); } - if( atcmd_binding_count != 0 ) - aFree(atcmd_binding); + if( atcommand->binding_count != 0 ) + aFree(atcommand->binding); - atcmd_binding_count = 0; + atcommand->binding_count = 0; if(sleep_db) { struct linkdb_node *n = (struct linkdb_node *)sleep_db; @@ -4332,7 +3895,6 @@ int script_reload() { #define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args } #define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args } -#define BUILDIN_FUNC(x) int buildin_ ## x (struct script_state* st) ///////////////////////////////////////////////////////////////////// // NPC interaction @@ -4342,79 +3904,81 @@ int script_reload() { /// If a dialog doesn't exist yet, one is created. /// /// mes "<message>"; -BUILDIN_FUNC(mes) +BUILDIN(mes) { TBL_PC* sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if( !script_hasdata(st, 3) ) {// only a single line detected in the script - clif_scriptmes(sd, st->oid, script_getstr(st, 2)); + clif->scriptmes(sd, st->oid, script_getstr(st, 2)); } else {// parse multiple lines as they exist int i; - + for( i = 2; script_hasdata(st, i); i++ ) { // send the message to the client - clif_scriptmes(sd, st->oid, script_getstr(st, i)); + clif->scriptmes(sd, st->oid, script_getstr(st, i)); } } - - return 0; + + return true; } /// Displays the button 'next' in the npc dialog. /// The dialog text is cleared and the script continues when the button is pressed. /// /// next; -BUILDIN_FUNC(next) +BUILDIN(next) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; +#ifdef SECURE_NPCTIMEOUT + sd->npc_idle_type = NPCT_WAIT; +#endif st->state = STOP; - clif_scriptnext(sd, st->oid); - return 0; + clif->scriptnext(sd, st->oid); + return true; } /// Ends the script and displays the button 'close' on the npc dialog. /// The dialog is closed when the button is pressed. /// /// close; -BUILDIN_FUNC(close) +BUILDIN(close) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - - st->state = END; - clif_scriptclose(sd, st->oid); - return 0; + return true; + + st->state = CLOSE; + clif->scriptclose(sd, st->oid); + return true; } /// Displays the button 'close' on the npc dialog. /// The dialog is closed and the script continues when the button is pressed. /// /// close2; -BUILDIN_FUNC(close2) +BUILDIN(close2) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + st->state = STOP; - clif_scriptclose(sd, st->oid); - return 0; + clif->scriptclose(sd, st->oid); + return true; } /// Counts the number of valid and total number of options in 'str' @@ -4424,11 +3988,11 @@ static int menu_countoptions(const char* str, int max_count, int* total) { int count = 0; int bogus_total; - + if( total == NULL ) total = &bogus_total; ++(*total); - + // initial empty options while( *str == ':' ) { @@ -4469,74 +4033,78 @@ static int menu_countoptions(const char* str, int max_count, int* total) /// NOTE: the client closes the npc dialog when cancel is pressed /// /// menu "<option_text>",<target_label>{,"<option_text>",<target_label>,...}; -BUILDIN_FUNC(menu) +BUILDIN(menu) { int i; const char* text; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + +#ifdef SECURE_NPCTIMEOUT + sd->npc_idle_type = NPCT_MENU; +#endif + // TODO detect multiple scripts waiting for input at the same time, and what to do when that happens if( sd->state.menu_or_input == 0 ) { struct StringBuf buf; struct script_data* data; - + if( script_lastdata(st) % 2 == 0 ) {// argument count is not even (1st argument is at index 2) ShowError("script:menu: illegal number of arguments (%d).\n", (script_lastdata(st) - 1)); st->state = END; - return 1; + return false; } - - StringBuf_Init(&buf); + + StrBuf->Init(&buf); sd->npc_menu = 0; for( i = 2; i < script_lastdata(st); i += 2 ) { // menu options text = script_getstr(st, i); - + // target label data = script_getdata(st, i+1); if( !data_islabel(data) ) {// not a label - StringBuf_Destroy(&buf); + StrBuf->Destroy(&buf); ShowError("script:menu: argument #%d (from 1) is not a label or label not found.\n", i); script_reportdata(data); st->state = END; - return 1; + return false; } - + // append option(s) if( text[0] == '\0' ) continue;// empty string, ignore if( sd->npc_menu > 0 ) - StringBuf_AppendStr(&buf, ":"); - StringBuf_AppendStr(&buf, text); + StrBuf->AppendStr(&buf, ":"); + StrBuf->AppendStr(&buf, text); sd->npc_menu += menu_countoptions(text, 0, NULL); } st->state = RERUNLINE; sd->state.menu_or_input = 1; - + /** * menus beyond this length crash the client (see bugreport:6402) **/ - if( StringBuf_Length(&buf) >= 2047 ) { + if( StrBuf->Length(&buf) >= 2047 ) { struct npc_data * nd = map_id2nd(st->oid); char* menu; CREATE(menu, char, 2048); - safestrncpy(menu, StringBuf_Value(&buf), 2047); - ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); - clif_scriptmenu(sd, st->oid, menu); + safestrncpy(menu, StrBuf->Value(&buf), 2047); + ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf)); + clif->scriptmenu(sd, st->oid, menu); aFree(menu); } else - clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); - - StringBuf_Destroy(&buf); - + clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf)); + + StrBuf->Destroy(&buf); + if( sd->npc_menu >= 0xff ) {// client supports only up to 254 entries; 0 is not used and 255 is reserved for cancel; excess entries are displayed but cause 'uint8' overflow ShowWarning("buildin_menu: Too many options specified (current=%d, max=254).\n", sd->npc_menu); @@ -4551,15 +4119,15 @@ BUILDIN_FUNC(menu) else {// goto target label int menu = 0; - + sd->state.menu_or_input = 0; if( sd->npc_menu <= 0 ) { ShowDebug("script:menu: unexpected selection (%d)\n", sd->npc_menu); st->state = END; - return 1; + return false; } - + // get target label for( i = 2; i < script_lastdata(st); i += 2 ) { @@ -4572,20 +4140,20 @@ BUILDIN_FUNC(menu) {// Invalid selection ShowDebug("script:menu: selection is out of range (%d pairs are missing?) - please report this\n", sd->npc_menu); st->state = END; - return 1; + return false; } if( !data_islabel(script_getdata(st, i + 1)) ) {// TODO remove this temporary crash-prevention code (fallback for multiple scripts requesting user input) ShowError("script:menu: unexpected data in label argument\n"); script_reportdata(script_getdata(st, i + 1)); st->state = END; - return 1; + return false; } pc_setreg(sd, add_str("@menu"), menu); st->pos = script_getnum(st, i + 1); st->state = GOTO; } - return 0; + return true; } /// Displays a menu with options and returns the selected option. @@ -4594,49 +4162,53 @@ BUILDIN_FUNC(menu) /// select(<option_text>{,<option_text>,...}) -> <selected_option> /// /// @see menu -BUILDIN_FUNC(select) +BUILDIN(select) { int i; const char* text; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + +#ifdef SECURE_NPCTIMEOUT + sd->npc_idle_type = NPCT_MENU; +#endif + if( sd->state.menu_or_input == 0 ) { struct StringBuf buf; - - StringBuf_Init(&buf); + + StrBuf->Init(&buf); sd->npc_menu = 0; for( i = 2; i <= script_lastdata(st); ++i ) { text = script_getstr(st, i); - + if( sd->npc_menu > 0 ) - StringBuf_AppendStr(&buf, ":"); - - StringBuf_AppendStr(&buf, text); + StrBuf->AppendStr(&buf, ":"); + + StrBuf->AppendStr(&buf, text); sd->npc_menu += menu_countoptions(text, 0, NULL); } - + st->state = RERUNLINE; sd->state.menu_or_input = 1; - + /** * menus beyond this length crash the client (see bugreport:6402) **/ - if( StringBuf_Length(&buf) >= 2047 ) { + if( StrBuf->Length(&buf) >= 2047 ) { struct npc_data * nd = map_id2nd(st->oid); char* menu; CREATE(menu, char, 2048); - safestrncpy(menu, StringBuf_Value(&buf), 2047); - ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); - clif_scriptmenu(sd, st->oid, menu); + safestrncpy(menu, StrBuf->Value(&buf), 2047); + ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf)); + clif->scriptmenu(sd, st->oid, menu); aFree(menu); } else - clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); - + clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf)); + StrBuf->Destroy(&buf); + if( sd->npc_menu >= 0xff ) { ShowWarning("buildin_select: Too many options specified (current=%d, max=254).\n", sd->npc_menu); script_reportsrc(st); @@ -4646,7 +4218,7 @@ BUILDIN_FUNC(select) st->state = END; } else {// return selected option int menu = 0; - + sd->state.menu_or_input = 0; for( i = 2; i <= script_lastdata(st); ++i ) { text = script_getstr(st, i); @@ -4658,7 +4230,7 @@ BUILDIN_FUNC(select) script_pushint(st, menu); st->state = RUN; } - return 0; + return true; } /// Displays a menu with options and returns the selected option. @@ -4669,49 +4241,53 @@ BUILDIN_FUNC(select) /// prompt(<option_text>{,<option_text>,...}) -> <selected_option> /// /// @see menu -BUILDIN_FUNC(prompt) +BUILDIN(prompt) { int i; const char *text; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + +#ifdef SECURE_NPCTIMEOUT + sd->npc_idle_type = NPCT_MENU; +#endif + if( sd->state.menu_or_input == 0 ) { struct StringBuf buf; - - StringBuf_Init(&buf); + + StrBuf->Init(&buf); sd->npc_menu = 0; for( i = 2; i <= script_lastdata(st); ++i ) { text = script_getstr(st, i); if( sd->npc_menu > 0 ) - StringBuf_AppendStr(&buf, ":"); - StringBuf_AppendStr(&buf, text); + StrBuf->AppendStr(&buf, ":"); + StrBuf->AppendStr(&buf, text); sd->npc_menu += menu_countoptions(text, 0, NULL); } - + st->state = RERUNLINE; sd->state.menu_or_input = 1; - + /** * menus beyond this length crash the client (see bugreport:6402) **/ - if( StringBuf_Length(&buf) >= 2047 ) { + if( StrBuf->Length(&buf) >= 2047 ) { struct npc_data * nd = map_id2nd(st->oid); char* menu; CREATE(menu, char, 2048); - safestrncpy(menu, StringBuf_Value(&buf), 2047); - ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StringBuf_Length(&buf)); - clif_scriptmenu(sd, st->oid, menu); + safestrncpy(menu, StrBuf->Value(&buf), 2047); + ShowWarning("NPC Menu too long! (source:%s / length:%d)\n",nd?nd->name:"Unknown",StrBuf->Length(&buf)); + clif->scriptmenu(sd, st->oid, menu); aFree(menu); } else - clif_scriptmenu(sd, st->oid, StringBuf_Value(&buf)); - StringBuf_Destroy(&buf); - + clif->scriptmenu(sd, st->oid, StrBuf->Value(&buf)); + StrBuf->Destroy(&buf); + if( sd->npc_menu >= 0xff ) { ShowWarning("buildin_prompt: Too many options specified (current=%d, max=254).\n", sd->npc_menu); @@ -4728,7 +4304,7 @@ BUILDIN_FUNC(prompt) else {// return selected option int menu = 0; - + sd->state.menu_or_input = 0; for( i = 2; i <= script_lastdata(st); ++i ) { @@ -4741,7 +4317,7 @@ BUILDIN_FUNC(prompt) script_pushint(st, menu); st->state = RUN; } - return 0; + return true; } ///////////////////////////////////////////////////////////////////// @@ -4751,40 +4327,40 @@ BUILDIN_FUNC(prompt) /// Jumps to the target script label. /// /// goto <label>; -BUILDIN_FUNC(goto) +BUILDIN(goto) { if( !data_islabel(script_getdata(st,2)) ) { ShowError("script:goto: not a label\n"); script_reportdata(script_getdata(st,2)); st->state = END; - return 1; + return false; } - + st->pos = script_getnum(st,2); st->state = GOTO; - return 0; + return true; } /*========================================== * user-defined function call *------------------------------------------*/ -BUILDIN_FUNC(callfunc) +BUILDIN(callfunc) { int i, j; struct script_retinfo* ri; struct script_code* scr; const char* str = script_getstr(st,2); DBMap **ref = NULL; - + scr = (struct script_code*)strdb_get(userfunc_db, str); if( !scr ) { ShowError("script:callfunc: function not found! [%s]\n", str); st->state = END; - return 1; + return false; } - + for( i = st->start+3, j = 0; i < st->end; i++, j++ ) { struct script_data* data = push_copy(st->stack,i); @@ -4792,15 +4368,13 @@ BUILDIN_FUNC(callfunc) { const char* name = reference_getname(data); if( name[0] == '.' ) { - if ( !ref ) { - ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1); - ref[0] = (name[1] == '@' ? st->stack->var_function : st->script->script_vars); - } + ref = (struct DBMap**)aCalloc(sizeof(struct DBMap*), 1); + ref[0] = (name[1] == '@' ? st->stack->var_function : st->script->script_vars); data->ref = ref; } } } - + CREATE(ri, struct script_retinfo, 1); ri->script = st->script;// script code ri->var_function = st->stack->var_function;// scope variables @@ -4808,33 +4382,33 @@ BUILDIN_FUNC(callfunc) ri->nargs = j;// argument count ri->defsp = st->stack->defsp;// default stack pointer push_retinfo(st->stack, ri, ref); - + st->pos = 0; st->script = scr; st->stack->defsp = st->stack->sp; st->state = GOTO; st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); - - return 0; + + return true; } /*========================================== * subroutine call *------------------------------------------*/ -BUILDIN_FUNC(callsub) +BUILDIN(callsub) { int i,j; struct script_retinfo* ri; int pos = script_getnum(st,2); DBMap **ref = NULL; - + if( !data_islabel(script_getdata(st,2)) && !data_isfunclabel(script_getdata(st,2)) ) { ShowError("script:callsub: argument is not a label\n"); script_reportdata(script_getdata(st,2)); st->state = END; - return 1; + return false; } - + for( i = st->start+3, j = 0; i < st->end; i++, j++ ) { struct script_data* data = push_copy(st->stack,i); @@ -4850,7 +4424,7 @@ BUILDIN_FUNC(callsub) } } } - + CREATE(ri, struct script_retinfo, 1); ri->script = st->script;// script code ri->var_function = st->stack->var_function;// scope variables @@ -4858,34 +4432,34 @@ BUILDIN_FUNC(callsub) ri->nargs = j;// argument count ri->defsp = st->stack->defsp;// default stack pointer push_retinfo(st->stack, ri, ref); - + st->pos = pos; st->stack->defsp = st->stack->sp; st->state = GOTO; st->stack->var_function = idb_alloc(DB_OPT_RELEASE_DATA); - - return 0; + + return true; } /// Retrieves an argument provided to callfunc/callsub. /// If the argument doesn't exist /// /// getarg(<index>{,<default_value>}) -> <value> -BUILDIN_FUNC(getarg) +BUILDIN(getarg) { struct script_retinfo* ri; int idx; - + if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO ) { ShowError("script:getarg: no callfunc or callsub!\n"); st->state = END; - return 1; + return false; } ri = st->stack->stack_data[st->stack->defsp - 1].u.ri; - + idx = script_getnum(st,2); - + if( idx >= 0 && idx < ri->nargs ) push_copy(st->stack, st->stack->defsp - 1 - ri->nargs + idx); else if( script_hasdata(st,3) ) @@ -4894,10 +4468,10 @@ BUILDIN_FUNC(getarg) { ShowError("script:getarg: index (idx=%d) out of range (nargs=%d) and no default value found\n", idx, ri->nargs); st->state = END; - return 1; + return false; } - - return 0; + + return true; } /// Returns from the current function, optionaly returning a value from the functions. @@ -4905,7 +4479,7 @@ BUILDIN_FUNC(getarg) /// /// return; /// return <value>; -BUILDIN_FUNC(return) +BUILDIN(return) { if( script_hasdata(st,2) ) {// return value @@ -4931,7 +4505,7 @@ BUILDIN_FUNC(return) script_pushnil(st); } st->state = RETFUNC; - return 0; + return true; } /// Returns a random number from 0 to <range>-1. @@ -4939,12 +4513,12 @@ BUILDIN_FUNC(return) /// If <min> is greater than <max>, their numbers are switched. /// rand(<range>) -> <int> /// rand(<min>,<max>) -> <int> -BUILDIN_FUNC(rand) +BUILDIN(rand) { int range; int min; int max; - + if( script_hasdata(st,3) ) {// min,max min = script_getnum(st,2); @@ -4962,41 +4536,41 @@ BUILDIN_FUNC(rand) script_pushint(st, min); else script_pushint(st, rnd()%range + min); - - return 0; + + return true; } /*========================================== * Warp sd to str,x,y or Random or SavePoint/Save *------------------------------------------*/ -BUILDIN_FUNC(warp) +BUILDIN(warp) { int ret; int x,y; const char* str; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + str = script_getstr(st,2); x = script_getnum(st,3); y = script_getnum(st,4); - + if(strcmp(str,"Random")==0) ret = pc_randomwarp(sd,CLR_TELEPORT); else if(strcmp(str,"SavePoint")==0 || strcmp(str,"Save")==0) ret = pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); else ret = pc_setpos(sd,mapindex_name2id(str),x,y,CLR_OUTSIGHT); - + if( ret ) { ShowError("buildin_warp: moving player '%s' to \"%s\",%d,%d failed.\n", sd->status.name, str, x, y); script_reportsrc(st); } - - return 0; + + return true; } /*========================================== * Warp a specified area @@ -5005,42 +4579,42 @@ static int buildin_areawarp_sub(struct block_list *bl,va_list ap) { int x2,y2,x3,y3; unsigned int index; - + index = va_arg(ap,unsigned int); x2 = va_arg(ap,int); y2 = va_arg(ap,int); x3 = va_arg(ap,int); y3 = va_arg(ap,int); - + if(index == 0) pc_randomwarp((TBL_PC *)bl,CLR_TELEPORT); else if(x3 && y3) { int max, tx, ty, j = 0; - + // choose a suitable max number of attempts if( (max = (y3-y2+1)*(x3-x2+1)*3) > 1000 ) max = 1000; - + // find a suitable map cell do { tx = rnd()%(x3-x2+1)+x2; ty = rnd()%(y3-y2+1)+y2; j++; } while( map_getcell(index,tx,ty,CELL_CHKNOPASS) && j < max ); - + pc_setpos((TBL_PC *)bl,index,tx,ty,CLR_OUTSIGHT); } else pc_setpos((TBL_PC *)bl,index,x2,y2,CLR_OUTSIGHT); return 0; } -BUILDIN_FUNC(areawarp) +BUILDIN(areawarp) { int16 m, x0,y0,x1,y1, x2,y2,x3=0,y3=0; unsigned int index; const char *str; const char *mapname; - + mapname = script_getstr(st,2); x0 = script_getnum(st,3); y0 = script_getnum(st,4); @@ -5049,7 +4623,7 @@ BUILDIN_FUNC(areawarp) str = script_getstr(st,7); x2 = script_getnum(st,8); y2 = script_getnum(st,9); - + if( script_hasdata(st,10) && script_hasdata(st,11) ) { // Warp area to area if( (x3 = script_getnum(st,10)) < 0 || (y3 = script_getnum(st,11)) < 0 ){ x3 = 0; @@ -5060,17 +4634,17 @@ BUILDIN_FUNC(areawarp) if( y3 < y2 ) swap(y3,y2); } } - + if( (m = map_mapname2mapid(mapname)) < 0 ) - return 0; - + return true; + if( strcmp(str,"Random") == 0 ) index = 0; else if( !(index=mapindex_name2id(str)) ) - return 0; - + return true; + map_foreachinarea(buildin_areawarp_sub, m,x0,y0,x1,y1, BL_PC, index,x2,y2,x3,y3); - return 0; + return true; } /*========================================== @@ -5084,12 +4658,12 @@ static int buildin_areapercentheal_sub(struct block_list *bl,va_list ap) pc_percentheal((TBL_PC *)bl,hp,sp); return 0; } -BUILDIN_FUNC(areapercentheal) +BUILDIN(areapercentheal) { int hp,sp,m; const char *mapname; int x0,y0,x1,y1; - + mapname=script_getstr(st,2); x0=script_getnum(st,3); y0=script_getnum(st,4); @@ -5097,12 +4671,12 @@ BUILDIN_FUNC(areapercentheal) y1=script_getnum(st,6); hp=script_getnum(st,7); sp=script_getnum(st,8); - + if( (m=map_mapname2mapid(mapname))< 0) - return 0; - + return true; + map_foreachinarea(buildin_areapercentheal_sub,m,x0,y0,x1,y1,BL_PC,hp,sp); - return 0; + return true; } /*========================================== @@ -5111,37 +4685,37 @@ BUILDIN_FUNC(areapercentheal) * another player npc-session. * Using: warpchar "mapname",x,y,Char_ID; *------------------------------------------*/ -BUILDIN_FUNC(warpchar) +BUILDIN(warpchar) { int x,y,a; const char *str; TBL_PC *sd; - + str=script_getstr(st,2); x=script_getnum(st,3); y=script_getnum(st,4); a=script_getnum(st,5); - + sd = map_charid2sd(a); if( sd == NULL ) - return 0; - + return true; + if(strcmp(str, "Random") == 0) pc_randomwarp(sd, CLR_TELEPORT); else - if(strcmp(str, "SavePoint") == 0) - pc_setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); - else - pc_setpos(sd, mapindex_name2id(str), x, y, CLR_TELEPORT); - - return 0; + if(strcmp(str, "SavePoint") == 0) + pc_setpos(sd, sd->status.save_point.map,sd->status.save_point.x, sd->status.save_point.y, CLR_TELEPORT); + else + pc_setpos(sd, mapindex_name2id(str), x, y, CLR_TELEPORT); + + return true; } /*========================================== * Warpparty - [Fredzilla] [Paradox924X] * Syntax: warpparty "to_mapname",x,y,Party_ID,{"from_mapname"}; * If 'from_mapname' is specified, only the party members on that map will be warped *------------------------------------------*/ -BUILDIN_FUNC(warpparty) +BUILDIN(warpparty) { TBL_PC *sd = NULL; TBL_PC *pl_sd; @@ -5149,7 +4723,7 @@ BUILDIN_FUNC(warpparty) int type; int mapindex; int i; - + const char* str = script_getstr(st,2); int x = script_getnum(st,3); int y = script_getnum(st,4); @@ -5157,235 +4731,235 @@ BUILDIN_FUNC(warpparty) const char* str2 = NULL; if ( script_hasdata(st,6) ) str2 = script_getstr(st,6); - + p = party_search(p_id); if(!p) - return 0; - + return true; + type = ( strcmp(str,"Random")==0 ) ? 0 - : ( strcmp(str,"SavePointAll")==0 ) ? 1 - : ( strcmp(str,"SavePoint")==0 ) ? 2 - : ( strcmp(str,"Leader")==0 ) ? 3 - : 4; - + : ( strcmp(str,"SavePointAll")==0 ) ? 1 + : ( strcmp(str,"SavePoint")==0 ) ? 2 + : ( strcmp(str,"Leader")==0 ) ? 3 + : 4; + switch (type) { - case 3: - for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); - if (i == MAX_PARTY || !p->data[i].sd) //Leader not found / not online - return 0; - pl_sd = p->data[i].sd; - mapindex = pl_sd->mapindex; - x = pl_sd->bl.x; - y = pl_sd->bl.y; - break; - case 4: - mapindex = mapindex_name2id(str); - break; - case 2: - //"SavePoint" uses save point of the currently attached player - if (( sd = script_rid2sd(st) ) == NULL ) - return 0; - default: - mapindex = 0; - break; + case 3: + for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); + if (i == MAX_PARTY || !p->data[i].sd) //Leader not found / not online + return true; + pl_sd = p->data[i].sd; + mapindex = pl_sd->mapindex; + x = pl_sd->bl.x; + y = pl_sd->bl.y; + break; + case 4: + mapindex = mapindex_name2id(str); + break; + case 2: + //"SavePoint" uses save point of the currently attached player + if (( sd = script_rid2sd(st) ) == NULL ) + return true; + default: + mapindex = 0; + break; } - + for (i = 0; i < MAX_PARTY; i++) { if( !(pl_sd = p->data[i].sd) || pl_sd->status.party_id != p_id ) continue; - + if( str2 && strcmp(str2, map[pl_sd->bl.m].name) != 0 ) continue; - + if( pc_isdead(pl_sd) ) continue; - + switch( type ) { - case 0: // Random - if(!map[pl_sd->bl.m].flag.nowarp) - pc_randomwarp(pl_sd,CLR_TELEPORT); - break; - case 1: // SavePointAll - if(!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); - break; - case 2: // SavePoint - if(!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - case 3: // Leader - case 4: // m,x,y - if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) - pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); - break; + case 0: // Random + if(!map[pl_sd->bl.m].flag.nowarp) + pc_randomwarp(pl_sd,CLR_TELEPORT); + break; + case 1: // SavePointAll + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); + break; + case 2: // SavePoint + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + case 3: // Leader + case 4: // m,x,y + if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) + pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); + break; } } - - return 0; + + return true; } /*========================================== * Warpguild - [Fredzilla] * Syntax: warpguild "mapname",x,y,Guild_ID; *------------------------------------------*/ -BUILDIN_FUNC(warpguild) +BUILDIN(warpguild) { TBL_PC *sd = NULL; TBL_PC *pl_sd; struct guild* g; struct s_mapiterator* iter; int type; - + const char* str = script_getstr(st,2); int x = script_getnum(st,3); int y = script_getnum(st,4); int gid = script_getnum(st,5); - - g = guild_search(gid); + + g = guild->search(gid); if( g == NULL ) - return 0; - + return true; + type = ( strcmp(str,"Random")==0 ) ? 0 - : ( strcmp(str,"SavePointAll")==0 ) ? 1 - : ( strcmp(str,"SavePoint")==0 ) ? 2 - : 3; - + : ( strcmp(str,"SavePointAll")==0 ) ? 1 + : ( strcmp(str,"SavePoint")==0 ) ? 2 + : 3; + if( type == 2 && ( sd = script_rid2sd(st) ) == NULL ) {// "SavePoint" uses save point of the currently attached player - return 0; + return true; } - + iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if( pl_sd->status.guild_id != gid ) continue; - + switch( type ) { - case 0: // Random - if(!map[pl_sd->bl.m].flag.nowarp) - pc_randomwarp(pl_sd,CLR_TELEPORT); - break; - case 1: // SavePointAll - if(!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); - break; - case 2: // SavePoint - if(!map[pl_sd->bl.m].flag.noreturn) - pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - case 3: // m,x,y - if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) - pc_setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT); - break; + case 0: // Random + if(!map[pl_sd->bl.m].flag.nowarp) + pc_randomwarp(pl_sd,CLR_TELEPORT); + break; + case 1: // SavePointAll + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,pl_sd->status.save_point.map,pl_sd->status.save_point.x,pl_sd->status.save_point.y,CLR_TELEPORT); + break; + case 2: // SavePoint + if(!map[pl_sd->bl.m].flag.noreturn) + pc_setpos(pl_sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + case 3: // m,x,y + if(!map[pl_sd->bl.m].flag.noreturn && !map[pl_sd->bl.m].flag.nowarp) + pc_setpos(pl_sd,mapindex_name2id(str),x,y,CLR_TELEPORT); + break; } } - mapit_free(iter); - - return 0; + mapit->free(iter); + + return true; } /*========================================== * Force Heal a player (hp and sp) *------------------------------------------*/ -BUILDIN_FUNC(heal) +BUILDIN(heal) { TBL_PC *sd; int hp,sp; - + sd = script_rid2sd(st); - if (!sd) return 0; - + if (!sd) return true; + hp=script_getnum(st,2); sp=script_getnum(st,3); status_heal(&sd->bl, hp, sp, 1); - return 0; + return true; } /*========================================== * Heal a player by item (get vit bonus etc) *------------------------------------------*/ -BUILDIN_FUNC(itemheal) +BUILDIN(itemheal) { TBL_PC *sd; int hp,sp; - + hp=script_getnum(st,2); sp=script_getnum(st,3); - + if(potion_flag==1) { potion_hp = hp; potion_sp = sp; - return 0; + return true; } - + sd = script_rid2sd(st); - if (!sd) return 0; + if (!sd) return true; pc_itemheal(sd,sd->itemid,hp,sp); - return 0; + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(percentheal) +BUILDIN(percentheal) { int hp,sp; TBL_PC* sd; - + hp=script_getnum(st,2); sp=script_getnum(st,3); - + if(potion_flag==1) { potion_per_hp = hp; potion_per_sp = sp; - return 0; + return true; } - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; + return true; #ifdef RENEWAL if( sd->sc.data[SC_EXTREMITYFIST2] ) sp = 0; #endif pc_percentheal(sd,hp,sp); - return 0; + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(jobchange) +BUILDIN(jobchange) { int job, upper=-1; - + job=script_getnum(st,2); if( script_hasdata(st,3) ) upper=script_getnum(st,3); - + if (pcdb_checkid(job)) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pc_jobchange(sd, job, upper); } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(jobname) +BUILDIN(jobname) { int class_=script_getnum(st,2); script_pushconststr(st, (char*)job_name(class_)); - return 0; + return true; } /// Get input from the player. @@ -5395,7 +4969,7 @@ BUILDIN_FUNC(jobname) /// shorter than 'min' and 0 otherwise. /// /// input(<var>{,<min>{,<max>}}) -> <int> -BUILDIN_FUNC(input) +BUILDIN(input) { TBL_PC* sd; struct script_data* data; @@ -5403,31 +4977,35 @@ BUILDIN_FUNC(input) const char* name; int min; int max; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + data = script_getdata(st,2); if( !data_isreference(data) ){ ShowError("script:input: not a variable\n"); script_reportdata(data); st->state = END; - return 1; + return false; } uid = reference_getuid(data); name = reference_getname(data); min = (script_hasdata(st,3) ? script_getnum(st,3) : script_config.input_min_value); max = (script_hasdata(st,4) ? script_getnum(st,4) : script_config.input_max_value); - + +#ifdef SECURE_NPCTIMEOUT + sd->npc_idle_type = NPCT_WAIT; +#endif + if( !sd->state.menu_or_input ) { // first invocation, display npc input box sd->state.menu_or_input = 1; st->state = RERUNLINE; if( is_string_variable(name) ) - clif_scriptinputstr(sd,st->oid); + clif->scriptinputstr(sd,st->oid); else - clif_scriptinput(sd,st->oid); + clif->scriptinput(sd,st->oid); } else { // take received text/value and store it in the designated variable @@ -5441,22 +5019,22 @@ BUILDIN_FUNC(input) else { int amount = sd->npc_amount; - set_reg(st, sd, uid, name, (void*)__64BPRTSIZE(cap_value(amount,min,max)), script_getref(st,2)); + set_reg(st, sd, uid, name, (void*)__64BPTRSIZE(cap_value(amount,min,max)), script_getref(st,2)); script_pushint(st, (amount > max ? 1 : amount < min ? -1 : 0)); } st->state = RUN; } - return 0; + return true; } // declare the copyarray method here for future reference -BUILDIN_FUNC(copyarray); +BUILDIN(copyarray); /// Sets the value of a variable. /// The value is converted to the type of the variable. /// /// set(<variable>,<value>) -> <variable> -BUILDIN_FUNC(set) +BUILDIN(set) { TBL_PC* sd = NULL; struct script_data* data; @@ -5464,7 +5042,7 @@ BUILDIN_FUNC(set) int num; const char* name; char prefix; - + data = script_getdata(st,2); //datavalue = script_getdata(st,3); if( !data_isreference(data) ) @@ -5472,60 +5050,60 @@ BUILDIN_FUNC(set) ShowError("script:set: not a variable\n"); script_reportdata(script_getdata(st,2)); st->state = END; - return 1; + return false; } - + num = reference_getuid(data); name = reference_getname(data); prefix = *name; - + if( not_server_variable(prefix) ) { sd = script_rid2sd(st); if( sd == NULL ) { ShowError("script:set: no player attached for player variable '%s'\n", name); - return 0; + return true; } } - + #if 0 if( data_isreference(datavalue) ) {// the value being referenced is a variable const char* namevalue = reference_getname(datavalue); - + if( !not_array_variable(*namevalue) ) {// array variable being copied into another array variable if( sd == NULL && not_server_variable(*namevalue) && !(sd = script_rid2sd(st)) ) {// player must be attached in order to copy a player variable ShowError("script:set: no player attached for player variable '%s'\n", namevalue); - return 0; + return true; } - + if( is_string_variable(namevalue) != is_string_variable(name) ) {// non-matching array value types ShowWarning("script:set: two array variables do not match in type.\n"); - return 0; + return true; } - + // push the maximum number of array values to the stack push_val(st->stack, C_INT, SCRIPT_MAX_ARRAYSIZE); - + // call the copy array method directly return buildin_copyarray(st); } } #endif - + if( is_string_variable(name) ) set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2)); else - set_reg(st,sd,num,name,(void*)__64BPRTSIZE(script_getnum(st,3)),script_getref(st,2)); - + set_reg(st,sd,num,name,(void*)__64BPTRSIZE(script_getnum(st,3)),script_getref(st,2)); + // return a copy of the variable reference script_pushcopy(st,2); - - return 0; + + return true; } ///////////////////////////////////////////////////////////////////// @@ -5536,7 +5114,7 @@ BUILDIN_FUNC(set) static int32 getarraysize(struct script_state* st, int32 id, int32 idx, int isstring, struct DBMap** ref) { int32 ret = idx; - + if( isstring ) { for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx ) @@ -5551,7 +5129,7 @@ static int32 getarraysize(struct script_state* st, int32 id, int32 idx, int isst { for( ; idx < SCRIPT_MAX_ARRAYSIZE; ++idx ) { - int32 num = (int32)__64BPRTSIZE(get_val2(st, reference_uid(id, idx), ref)); + int32 num = (int32)__64BPTRSIZE(get_val2(st, reference_uid(id, idx), ref)); if( num ) ret = idx + 1; script_removetop(st, -1, 0); @@ -5564,7 +5142,7 @@ static int32 getarraysize(struct script_state* st, int32 id, int32 idx, int isst /// ex: setarray arr[1],1,2,3; /// /// setarray <array variable>,<value1>{,<value2>...}; -BUILDIN_FUNC(setarray) +BUILDIN(setarray) { struct script_data* data; const char* name; @@ -5573,16 +5151,16 @@ BUILDIN_FUNC(setarray) int32 id; int32 i; TBL_PC* sd = NULL; - + data = script_getdata(st, 2); if( !data_isreference(data) ) { ShowError("script:setarray: not a variable\n"); script_reportdata(data); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id = reference_getid(data); start = reference_getindex(data); name = reference_getname(data); @@ -5591,20 +5169,20 @@ BUILDIN_FUNC(setarray) ShowError("script:setarray: illegal scope\n"); script_reportdata(data); st->state = END; - return 1;// not supported + return false;// not supported } - + if( not_server_variable(*name) ) { sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached + return true;// no player attached } - + end = start + script_lastdata(st) - 2; if( end > SCRIPT_MAX_ARRAYSIZE ) end = SCRIPT_MAX_ARRAYSIZE; - + if( is_string_variable(name) ) {// string array for( i = 3; start < end; ++start, ++i ) @@ -5613,16 +5191,16 @@ BUILDIN_FUNC(setarray) else {// int array for( i = 3; start < end; ++start, ++i ) - set_reg(st, sd, reference_uid(id, start), name, (void*)__64BPRTSIZE(script_getnum(st,i)), reference_getref(data)); + set_reg(st, sd, reference_uid(id, start), name, (void*)__64BPTRSIZE(script_getnum(st,i)), reference_getref(data)); } - return 0; + return true; } /// Sets count values of an array, from the starting index. /// ex: cleararray arr[0],0,1; /// /// cleararray <array variable>,<value>,<count>; -BUILDIN_FUNC(cleararray) +BUILDIN(cleararray) { struct script_data* data; const char* name; @@ -5631,16 +5209,16 @@ BUILDIN_FUNC(cleararray) int32 id; void* v; TBL_PC* sd = NULL; - + data = script_getdata(st, 2); if( !data_isreference(data) ) { ShowError("script:cleararray: not a variable\n"); script_reportdata(data); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id = reference_getid(data); start = reference_getindex(data); name = reference_getname(data); @@ -5649,35 +5227,35 @@ BUILDIN_FUNC(cleararray) ShowError("script:cleararray: illegal scope\n"); script_reportdata(data); st->state = END; - return 1;// not supported + return false;// not supported } - + if( not_server_variable(*name) ) { sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached + return true;// no player attached } - + if( is_string_variable(name) ) v = (void*)script_getstr(st, 3); else - v = (void*)__64BPRTSIZE(script_getnum(st, 3)); - + v = (void*)__64BPTRSIZE(script_getnum(st, 3)); + end = start + script_getnum(st, 4); if( end > SCRIPT_MAX_ARRAYSIZE ) end = SCRIPT_MAX_ARRAYSIZE; - + for( ; start < end; ++start ) set_reg(st, sd, reference_uid(id, start), name, v, script_getref(st,2)); - return 0; + return true; } /// Copies data from one array to another. /// ex: copyarray arr[0],arr[2],2; /// /// copyarray <destination array variable>,<source array variable>,<count>; -BUILDIN_FUNC(copyarray) +BUILDIN(copyarray) { struct script_data* data1; struct script_data* data2; @@ -5691,7 +5269,7 @@ BUILDIN_FUNC(copyarray) int32 i; int32 count; TBL_PC* sd = NULL; - + data1 = script_getdata(st, 2); data2 = script_getdata(st, 3); if( !data_isreference(data1) || !data_isreference(data2) ) @@ -5700,9 +5278,9 @@ BUILDIN_FUNC(copyarray) script_reportdata(data1); script_reportdata(data2); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id1 = reference_getid(data1); id2 = reference_getid(data2); idx1 = reference_getindex(data1); @@ -5715,31 +5293,31 @@ BUILDIN_FUNC(copyarray) script_reportdata(data1); script_reportdata(data2); st->state = END; - return 1;// not supported + return false;// not supported } - + if( is_string_variable(name1) != is_string_variable(name2) ) { ShowError("script:copyarray: type mismatch\n"); script_reportdata(data1); script_reportdata(data2); st->state = END; - return 1;// data type mismatch + return false;// data type mismatch } - + if( not_server_variable(*name1) || not_server_variable(*name2) ) { sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached + return true;// no player attached } - + count = script_getnum(st, 4); if( count > SCRIPT_MAX_ARRAYSIZE - idx1 ) count = SCRIPT_MAX_ARRAYSIZE - idx1; if( count <= 0 || (id1 == id2 && idx1 == idx2) ) - return 0;// nothing to copy - + return true;// nothing to copy + if( id1 == id2 && idx1 > idx2 ) {// destination might be overlapping the source - copy in reverse order for( i = count - 1; i >= 0; --i ) @@ -5763,7 +5341,7 @@ BUILDIN_FUNC(copyarray) set_reg(st, sd, reference_uid(id1, idx1 + i), name1, (is_string_variable(name1)?(void*)"":(void*)0), reference_getref(data1)); } } - return 0; + return true; } /// Returns the size of the array. @@ -5771,11 +5349,11 @@ BUILDIN_FUNC(copyarray) /// ex: getarraysize(arr[3]) /// /// getarraysize(<array variable>) -> <int> -BUILDIN_FUNC(getarraysize) +BUILDIN(getarraysize) { struct script_data* data; const char* name; - + data = script_getdata(st, 2); if( !data_isreference(data) ) { @@ -5783,9 +5361,9 @@ BUILDIN_FUNC(getarraysize) script_reportdata(data); script_pushnil(st); st->state = END; - return 1;// not a variable + return false;// not a variable } - + name = reference_getname(data); if( not_array_variable(*name) ) { @@ -5793,11 +5371,11 @@ BUILDIN_FUNC(getarraysize) script_reportdata(data); script_pushnil(st); st->state = END; - return 1;// not supported + return false;// not supported } - + script_pushint(st, getarraysize(st, reference_getid(data), reference_getindex(data), is_string_variable(name), reference_getref(data))); - return 0; + return true; } /// Deletes count or all the elements in an array, from the starting index. @@ -5805,7 +5383,7 @@ BUILDIN_FUNC(getarraysize) /// /// deletearray <array variable>; /// deletearray <array variable>,<count>; -BUILDIN_FUNC(deletearray) +BUILDIN(deletearray) { struct script_data* data; const char* name; @@ -5813,16 +5391,16 @@ BUILDIN_FUNC(deletearray) int end; int id; TBL_PC *sd = NULL; - + data = script_getdata(st, 2); if( !data_isreference(data) ) { ShowError("script:deletearray: not a variable\n"); script_reportdata(data); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id = reference_getid(data); start = reference_getindex(data); name = reference_getname(data); @@ -5831,29 +5409,29 @@ BUILDIN_FUNC(deletearray) ShowError("script:deletearray: illegal scope\n"); script_reportdata(data); st->state = END; - return 1;// not supported + return false;// not supported } - + if( not_server_variable(*name) ) { sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached + return true;// no player attached } - + end = SCRIPT_MAX_ARRAYSIZE; - + if( start >= end ) - return 0;// nothing to free - + return true;// nothing to free + if( script_hasdata(st,3) ) { int count = script_getnum(st, 3); if( count > end - start ) count = end - start; if( count <= 0 ) - return 0;// nothing to free - + return true;// nothing to free + // move rest of the elements backward for( ; start + count < end; ++start ) { @@ -5862,7 +5440,7 @@ BUILDIN_FUNC(deletearray) script_removetop(st, -1, 0); } } - + // clear the rest of the array if( is_string_variable(name) ) { @@ -5874,20 +5452,20 @@ BUILDIN_FUNC(deletearray) for( ; start < end; ++start ) set_reg(st, sd, reference_uid(id, start), name, (void*)0, reference_getref(data)); } - return 0; + return true; } /// Returns a reference to the target index of the array variable. /// Equivalent to var[index]. /// /// getelementofarray(<array variable>,<index>) -> <variable reference> -BUILDIN_FUNC(getelementofarray) +BUILDIN(getelementofarray) { struct script_data* data; const char* name; int32 id; int i; - + data = script_getdata(st, 2); if( !data_isreference(data) ) { @@ -5895,9 +5473,9 @@ BUILDIN_FUNC(getelementofarray) script_reportdata(data); script_pushnil(st); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id = reference_getid(data); name = reference_getname(data); if( not_array_variable(*name) ) @@ -5906,9 +5484,9 @@ BUILDIN_FUNC(getelementofarray) script_reportdata(data); script_pushnil(st); st->state = END; - return 1;// not supported + return false;// not supported } - + i = script_getnum(st, 3); if( i < 0 || i >= SCRIPT_MAX_ARRAYSIZE ) { @@ -5916,11 +5494,11 @@ BUILDIN_FUNC(getelementofarray) script_reportdata(data); script_pushnil(st); st->state = END; - return 1;// out of range + return false;// out of range } - + push_val2(st->stack, C_NAME, reference_uid(id, i), reference_getref(data)); - return 0; + return true; } ///////////////////////////////////////////////////////////////////// @@ -5930,160 +5508,160 @@ BUILDIN_FUNC(getelementofarray) /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(setlook) +BUILDIN(setlook) { int type,val; TBL_PC* sd; - + type=script_getnum(st,2); val=script_getnum(st,3); - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pc_changelook(sd,type,val); - - return 0; + + return true; } -BUILDIN_FUNC(changelook) +BUILDIN(changelook) { // As setlook but only client side int type,val; TBL_PC* sd; - + type=script_getnum(st,2); val=script_getnum(st,3); - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - - clif_changelook(&sd->bl,type,val); - - return 0; + return true; + + clif->changelook(&sd->bl,type,val); + + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(cutin) +BUILDIN(cutin) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - - clif_cutin(sd,script_getstr(st,2),script_getnum(st,3)); - return 0; + return true; + + clif->cutin(sd,script_getstr(st,2),script_getnum(st,3)); + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(viewpoint) +BUILDIN(viewpoint) { int type,x,y,id,color; TBL_PC* sd; - + type=script_getnum(st,2); x=script_getnum(st,3); y=script_getnum(st,4); id=script_getnum(st,5); color=script_getnum(st,6); - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - - clif_viewpoint(sd,st->oid,type,x,y,id,color); - - return 0; + return true; + + clif->viewpoint(sd,st->oid,type,x,y,id,color); + + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(countitem) +BUILDIN(countitem) { int nameid, i; int count = 0; struct item_data* id = NULL; struct script_data* data; - + TBL_PC* sd = script_rid2sd(st); if (!sd) { script_pushint(st,0); - return 0; + return true; } - + data = script_getdata(st,2); get_val(st, data); // convert into value in case of a variable - + if( data_isstring(data) ) {// item name - id = itemdb_searchname(conv_str(st, data)); + id = itemdb_searchname(script->conv_str(st, data)); } else {// item id - id = itemdb_exists(conv_num(st, data)); + id = itemdb_exists(script->conv_num(st, data)); } - + if( id == NULL ) { ShowError("buildin_countitem: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was script_pushint(st,0); - return 1; + return false; } - + nameid = id->nameid; - + for(i = 0; i < MAX_INVENTORY; i++) if(sd->status.inventory[i].nameid == nameid) count += sd->status.inventory[i].amount; - + script_pushint(st,count); - return 0; + return true; } /*========================================== * countitem2(nameID,Identified,Refine,Attribute,Card0,Card1,Card2,Card3) [Lupus] * returns number of items that meet the conditions *------------------------------------------*/ -BUILDIN_FUNC(countitem2) +BUILDIN(countitem2) { int nameid, iden, ref, attr, c1, c2, c3, c4; int count = 0; int i; struct item_data* id = NULL; struct script_data* data; - + TBL_PC* sd = script_rid2sd(st); if (!sd) { script_pushint(st,0); - return 0; + return true; } - + data = script_getdata(st,2); get_val(st, data); // convert into value in case of a variable - + if( data_isstring(data) ) {// item name - id = itemdb_searchname(conv_str(st, data)); + id = itemdb_searchname(script->conv_str(st, data)); } else {// item id - id = itemdb_exists(conv_num(st, data)); + id = itemdb_exists(script->conv_num(st, data)); } - + if( id == NULL ) { ShowError("buildin_countitem2: Invalid item '%s'.\n", script_getstr(st,2)); // returns string, regardless of what it was script_pushint(st,0); - return 1; + return false; } - + nameid = id->nameid; iden = script_getnum(st,3); ref = script_getnum(st,4); @@ -6092,7 +5670,7 @@ BUILDIN_FUNC(countitem2) c2 = (short)script_getnum(st,7); c3 = (short)script_getnum(st,8); c4 = (short)script_getnum(st,9); - + for(i = 0; i < MAX_INVENTORY; i++) if (sd->status.inventory[i].nameid > 0 && sd->inventory_data[i] != NULL && sd->status.inventory[i].amount > 0 && sd->status.inventory[i].nameid == nameid && @@ -6100,11 +5678,11 @@ BUILDIN_FUNC(countitem2) sd->status.inventory[i].attribute == attr && sd->status.inventory[i].card[0] == c1 && sd->status.inventory[i].card[1] == c2 && sd->status.inventory[i].card[2] == c3 && sd->status.inventory[i].card[3] == c4 - ) + ) count += sd->status.inventory[i].amount; - + script_pushint(st,count); - return 0; + return true; } /*========================================== @@ -6114,54 +5692,54 @@ BUILDIN_FUNC(countitem2) * 0 : fail * 1 : success (npc side only) *------------------------------------------*/ -BUILDIN_FUNC(checkweight) +BUILDIN(checkweight) { int nameid, amount, slots, amount2=0; unsigned int weight=0, i, nbargs; struct item_data* id = NULL; struct map_session_data* sd; struct script_data* data; - + if( ( sd = script_rid2sd(st) ) == NULL ){ - return 0; + return true; } nbargs = script_lastdata(st)+1; if(nbargs%2){ ShowError("buildin_checkweight: Invalid nb of args should be a multiple of 2.\n"); script_pushint(st,0); - return 1; + return false; } slots = pc_inventoryblank(sd); //nb of empty slot - + for(i=2; i<nbargs; i=i+2){ data = script_getdata(st,i); get_val(st, data); // convert into value in case of a variable if( data_isstring(data) ){// item name - id = itemdb_searchname(conv_str(st, data)); + id = itemdb_searchname(script->conv_str(st, data)); } else {// item id - id = itemdb_exists(conv_num(st, data)); + id = itemdb_exists(script->conv_num(st, data)); } if( id == NULL ) { ShowError("buildin_checkweight: Invalid item '%s'.\n", script_getstr(st,i)); // returns string, regardless of what it was script_pushint(st,0); - return 1; + return false; } nameid = id->nameid; - + amount = script_getnum(st,i+1); if( amount < 1 ) { ShowError("buildin_checkweight: Invalid amount '%d'.\n", amount); script_pushint(st,0); - return 1; + return false; } - + weight += itemdb_weight(nameid)*amount; //total weight for all chk if( weight + sd->weight > sd->max_weight ) {// too heavy script_pushint(st,0); - return 0; + return true; } - + switch( pc_checkadditem(sd, nameid, amount) ) { case ADDITEM_EXIST: @@ -6172,105 +5750,105 @@ BUILDIN_FUNC(checkweight) amount2++; if( slots < amount2 ) { script_pushint(st,0); - return 0; + return true; } } else {// non-stackable amount2 += amount; if( slots < amount2){ script_pushint(st,0); - return 0; + return true; } } break; case ADDITEM_OVERAMOUNT: script_pushint(st,0); - return 0; + return true; } } script_pushint(st,1); - return 0; + return true; } -BUILDIN_FUNC(checkweight2) +BUILDIN(checkweight2) { - //variable sub checkweight - int32 nameid=-1, amount=-1; - int i=0, amount2=0, slots=0, weight=0; + //variable sub checkweight + int32 nameid=-1, amount=-1; + int i=0, amount2=0, slots=0, weight=0; short fail=0; - - //variable for array parsing - struct script_data* data_it; - struct script_data* data_nb; - const char* name_it; - const char* name_nb; - int32 id_it, id_nb; - int32 idx_it, idx_nb; - int nb_it, nb_nb; //array size - - TBL_PC *sd = script_rid2sd(st); - nullpo_retr(1,sd); - - data_it = script_getdata(st, 2); - data_nb = script_getdata(st, 3); - - if( !data_isreference(data_it) || !data_isreference(data_nb)) - { - ShowError("script:checkweight2: parameter not a variable\n"); - script_pushint(st,0); - return 1;// not a variable - } - id_it = reference_getid(data_it); - id_nb = reference_getid(data_nb); - idx_it = reference_getindex(data_it); - idx_nb = reference_getindex(data_nb); - name_it = reference_getname(data_it); - name_nb = reference_getname(data_nb); - - if( not_array_variable(*name_it) || not_array_variable(*name_nb)) - { - ShowError("script:checkweight2: illegal scope\n"); - script_pushint(st,0); - return 1;// not supported - } - if(is_string_variable(name_it) || is_string_variable(name_nb)){ - ShowError("script:checkweight2: illegal type, need int\n"); - script_pushint(st,0); - return 1;// not supported - } - nb_it = getarraysize(st, id_it, idx_it, 0, reference_getref(data_it)); - nb_nb = getarraysize(st, id_nb, idx_nb, 0, reference_getref(data_nb)); - if(nb_it != nb_nb){ - ShowError("Size mistmatch: nb_it=%d, nb_nb=%d\n",nb_it,nb_nb); + + //variable for array parsing + struct script_data* data_it; + struct script_data* data_nb; + const char* name_it; + const char* name_nb; + int32 id_it, id_nb; + int32 idx_it, idx_nb; + int nb_it, nb_nb; //array size + + TBL_PC *sd = script_rid2sd(st); + nullpo_retr(1,sd); + + data_it = script_getdata(st, 2); + data_nb = script_getdata(st, 3); + + if( !data_isreference(data_it) || !data_isreference(data_nb)) + { + ShowError("script:checkweight2: parameter not a variable\n"); + script_pushint(st,0); + return false;// not a variable + } + id_it = reference_getid(data_it); + id_nb = reference_getid(data_nb); + idx_it = reference_getindex(data_it); + idx_nb = reference_getindex(data_nb); + name_it = reference_getname(data_it); + name_nb = reference_getname(data_nb); + + if( not_array_variable(*name_it) || not_array_variable(*name_nb)) + { + ShowError("script:checkweight2: illegal scope\n"); + script_pushint(st,0); + return false;// not supported + } + if(is_string_variable(name_it) || is_string_variable(name_nb)){ + ShowError("script:checkweight2: illegal type, need int\n"); + script_pushint(st,0); + return false;// not supported + } + nb_it = getarraysize(st, id_it, idx_it, 0, reference_getref(data_it)); + nb_nb = getarraysize(st, id_nb, idx_nb, 0, reference_getref(data_nb)); + if(nb_it != nb_nb){ + ShowError("Size mistmatch: nb_it=%d, nb_nb=%d\n",nb_it,nb_nb); fail = 1; - } - - slots = pc_inventoryblank(sd); - for(i=0; i<nb_it; i++){ - nameid = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it))); + } + + slots = pc_inventoryblank(sd); + for(i=0; i<nb_it; i++){ + nameid = (int32)__64BPTRSIZE(get_val2(st,reference_uid(id_it,idx_it+i),reference_getref(data_it))); script_removetop(st, -1, 0); - amount = (int32)__64BPRTSIZE(get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb))); + amount = (int32)__64BPTRSIZE(get_val2(st,reference_uid(id_nb,idx_nb+i),reference_getref(data_nb))); script_removetop(st, -1, 0); if(fail) continue; //cpntonie to depop rest - - if(itemdb_exists(nameid) == NULL ){ - ShowError("buildin_checkweight2: Invalid item '%d'.\n", nameid); - fail=1; - continue; - } - if(amount < 0 ){ - ShowError("buildin_checkweight2: Invalid amount '%d'.\n", amount); - fail = 1; - continue; - } + + if(itemdb_exists(nameid) == NULL ){ + ShowError("buildin_checkweight2: Invalid item '%d'.\n", nameid); + fail=1; + continue; + } + if(amount < 0 ){ + ShowError("buildin_checkweight2: Invalid amount '%d'.\n", amount); + fail = 1; + continue; + } weight += itemdb_weight(nameid)*amount; if( weight + sd->weight > sd->max_weight ){ - fail = 1; - continue; + fail = 1; + continue; } switch( pc_checkadditem(sd, nameid, amount) ) { case ADDITEM_EXIST: - // item is already in inventory, but there is still space for the requested amount + // item is already in inventory, but there is still space for the requested amount break; case ADDITEM_NEW: if( itemdb_isstackable(nameid) ){// stackable @@ -6289,75 +5867,74 @@ BUILDIN_FUNC(checkweight2) fail = 1; } //end switch } //end loop DO NOT break it prematurly we need to depop all stack - - fail?script_pushint(st,0):script_pushint(st,1); - return 0; + + fail?script_pushint(st,0):script_pushint(st,1); + return true; } /*========================================== * getitem <item id>,<amount>{,<account ID>}; * getitem "<item name>",<amount>{,<account ID>}; *------------------------------------------*/ -BUILDIN_FUNC(getitem) +BUILDIN(getitem) { int nameid,amount,get_count,i,flag = 0; struct item it; TBL_PC *sd; struct script_data *data; - + struct item_data *item_data; + data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) {// "<item name>" - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - if( item_data == NULL ){ + const char *name=script->conv_str(st,data); + if( (item_data = itemdb_searchname(name)) == NULL ){ ShowError("buildin_getitem: Nonexistant item %s requested.\n", name); - return 1; //No item created. + return false; //No item created. } nameid=item_data->nameid; - } else if( data_isint(data) ) - {// <item id> - nameid=conv_num(st,data); + } else if( data_isint(data) ) {// <item id> + nameid=script->conv_num(st,data); //Violet Box, Blue Box, etc - random item pick if( nameid < 0 ) { nameid = -nameid; flag = 1; } - if( nameid <= 0 || !itemdb_exists(nameid) ){ + if( nameid <= 0 || !(item_data = itemdb_exists(nameid)) ){ ShowError("buildin_getitem: Nonexistant item %d requested.\n", nameid); - return 1; //No item created. + return false; //No item created. } } else { ShowError("buildin_getitem: invalid data type for argument #1 (%d).", data->type); - return 1; + return false; } - + // <amount> if( (amount=script_getnum(st,3)) <= 0) - return 0; //return if amount <=0, skip the useles iteration - + return true; //return if amount <=0, skip the useles iteration + memset(&it,0,sizeof(it)); it.nameid=nameid; if(!flag) it.identify=1; else - it.identify=itemdb_isidentified(nameid); - + it.identify=itemdb_isidentified2(item_data); + if( script_hasdata(st,4) ) sd=map_id2sd(script_getnum(st,4)); // <Account ID> else sd=script_rid2sd(st); // Attached player - + if( sd == NULL ) // no target - return 0; - + return true; + //Check if it's stackable. if (!itemdb_isstackable(nameid)) get_count = 1; else get_count = amount; - + for (i = 0; i < amount; i += get_count) { // if not pet egg @@ -6365,20 +5942,20 @@ BUILDIN_FUNC(getitem) { if ((flag = pc_additem(sd, &it, get_count, LOG_TYPE_SCRIPT))) { - clif_additem(sd, 0, 0, flag); + clif->additem(sd, 0, 0, flag); if( pc_candrop(sd,&it) ) map_addflooritem(&it,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(getitem2) +BUILDIN(getitem2) { int nameid,amount,get_count,i,flag = 0; int iden,ref,attr,c1,c2,c3,c4; @@ -6386,27 +5963,27 @@ BUILDIN_FUNC(getitem2) struct item item_tmp; TBL_PC *sd; struct script_data *data; - + if( script_hasdata(st,11) ) sd=map_id2sd(script_getnum(st,11)); // <Account ID> else sd=script_rid2sd(st); // Attached player - + if( sd == NULL ) // no target - return 0; - + return true; + data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); if( item_data ) nameid=item_data->nameid; else nameid=UNKNOWN_ITEM_ID; }else - nameid=conv_num(st,data); - + nameid=script->conv_num(st,data); + amount=script_getnum(st,3); iden=script_getnum(st,4); ref=script_getnum(st,5); @@ -6415,12 +5992,12 @@ BUILDIN_FUNC(getitem2) c2=(short)script_getnum(st,8); c3=(short)script_getnum(st,9); c4=(short)script_getnum(st,10); - + if(nameid<0) { // Invalide nameid nameid = -nameid; flag = 1; } - + if(nameid > 0) { memset(&item_tmp,0,sizeof(item_tmp)); item_data=itemdb_exists(nameid); @@ -6437,7 +6014,7 @@ BUILDIN_FUNC(getitem2) iden = 1; ref = attr = 0; } - + item_tmp.nameid=nameid; if(!flag) item_tmp.identify=iden; @@ -6449,13 +6026,13 @@ BUILDIN_FUNC(getitem2) item_tmp.card[1]=(short)c2; item_tmp.card[2]=(short)c3; item_tmp.card[3]=(short)c4; - + //Check if it's stackable. if (!itemdb_isstackable(nameid)) get_count = 1; else get_count = amount; - + for (i = 0; i < amount; i += get_count) { // if not pet egg @@ -6463,74 +6040,74 @@ BUILDIN_FUNC(getitem2) { if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) { - clif_additem(sd, 0, 0, flag); + clif->additem(sd, 0, 0, flag); if( pc_candrop(sd,&item_tmp) ) map_addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } } } - - return 0; + + return true; } /*========================================== * rentitem <item id>,<seconds> * rentitem "<item name>",<seconds> *------------------------------------------*/ -BUILDIN_FUNC(rentitem) +BUILDIN(rentitem) { struct map_session_data *sd; struct script_data *data; struct item it; int seconds; int nameid = 0, flag; - + data = script_getdata(st,2); get_val(st,data); - + if( (sd = script_rid2sd(st)) == NULL ) - return 0; - + return true; + if( data_isstring(data) ) { - const char *name = conv_str(st,data); + const char *name = script->conv_str(st,data); struct item_data *itd = itemdb_searchname(name); if( itd == NULL ) { ShowError("buildin_rentitem: Nonexistant item %s requested.\n", name); - return 1; + return false; } nameid = itd->nameid; } else if( data_isint(data) ) { - nameid = conv_num(st,data); + nameid = script->conv_num(st,data); if( nameid <= 0 || !itemdb_exists(nameid) ) { ShowError("buildin_rentitem: Nonexistant item %d requested.\n", nameid); - return 1; + return false; } } else { ShowError("buildin_rentitem: invalid data type for argument #1 (%d).\n", data->type); - return 1; + return false; } - + seconds = script_getnum(st,3); memset(&it, 0, sizeof(it)); it.nameid = nameid; it.identify = 1; it.expire_time = (unsigned int)(time(NULL) + seconds); - + if( (flag = pc_additem(sd, &it, 1, LOG_TYPE_SCRIPT)) ) { - clif_additem(sd, 0, 0, flag); - return 1; + clif->additem(sd, 0, 0, flag); + return false; } - - return 0; + + return true; } /*========================================== @@ -6539,53 +6116,53 @@ BUILDIN_FUNC(rentitem) * Returned Qty is always 1, only works on equip-able * equipment *------------------------------------------*/ -BUILDIN_FUNC(getnameditem) +BUILDIN(getnameditem) { int nameid; struct item item_tmp; TBL_PC *sd, *tsd; struct script_data *data; - + sd = script_rid2sd(st); if (sd == NULL) { //Player not attached! script_pushint(st,0); - return 0; + return true; } - + data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); if( item_data == NULL) { //Failed script_pushint(st,0); - return 0; + return true; } nameid = item_data->nameid; }else - nameid = conv_num(st,data); - + nameid = script->conv_num(st,data); + if(!itemdb_exists(nameid)/* || itemdb_isstackable(nameid)*/) { //Even though named stackable items "could" be risky, they are required for certain quests. script_pushint(st,0); - return 0; + return true; } - + data=script_getdata(st,3); get_val(st,data); if( data_isstring(data) ) //Char Name - tsd=map_nick2sd(conv_str(st,data)); + tsd=map_nick2sd(script->conv_str(st,data)); else //Char Id was given - tsd=map_charid2sd(conv_num(st,data)); - + tsd=map_charid2sd(script->conv_num(st,data)); + if( tsd == NULL ) { //Failed script_pushint(st,0); - return 0; + return true; } - + memset(&item_tmp,0,sizeof(item_tmp)); item_tmp.nameid=nameid; item_tmp.amount=1; @@ -6595,80 +6172,77 @@ BUILDIN_FUNC(getnameditem) item_tmp.card[3]=tsd->status.char_id >> 16; if(pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT)) { script_pushint(st,0); - return 0; //Failed to add item, we will not drop if they don't fit + return true; //Failed to add item, we will not drop if they don't fit } - + script_pushint(st,1); - return 0; + return true; } /*========================================== * gets a random item ID from an item group [Skotlex] * groupranditem group_num *------------------------------------------*/ -BUILDIN_FUNC(grouprandomitem) +BUILDIN(grouprandomitem) { int group; - + group = script_getnum(st,2); script_pushint(st,itemdb_searchrandomid(group)); - return 0; + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(makeitem) +BUILDIN(makeitem) { int nameid,amount,flag = 0; int x,y,m; const char *mapname; struct item item_tmp; struct script_data *data; + struct item_data *item_data; data=script_getdata(st,2); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); - struct item_data *item_data = itemdb_searchname(name); - if( item_data ) + const char *name=script->conv_str(st,data); + if( (item_data = itemdb_searchname(name)) ) nameid=item_data->nameid; else nameid=UNKNOWN_ITEM_ID; - }else - nameid=conv_num(st,data); - + } else { + nameid=script->conv_num(st,data); + if( nameid <= 0 || !(item_data = itemdb_exists(nameid)) ){ + ShowError("makeitem: Nonexistant item %d requested.\n", nameid); + return false; //No item created. + } + } amount=script_getnum(st,3); mapname =script_getstr(st,4); x =script_getnum(st,5); y =script_getnum(st,6); - + if(strcmp(mapname,"this")==0) { TBL_PC *sd; sd = script_rid2sd(st); - if (!sd) return 0; //Failed... + if (!sd) return true; //Failed... m=sd->bl.m; } else m=map_mapname2mapid(mapname); - - if(nameid<0) { - nameid = -nameid; - flag = 1; - } - - if(nameid > 0) { - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid=nameid; - if(!flag) - item_tmp.identify=1; - else - item_tmp.identify=itemdb_isidentified(nameid); - - map_addflooritem(&item_tmp,amount,m,x,y,0,0,0,0); - } - - return 0; + + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid=nameid; + if(!flag) + item_tmp.identify=1; + else + item_tmp.identify=itemdb_isidentified2(item_data); + + map_addflooritem(&item_tmp,amount,m,x,y,0,0,0,0); + + return true; } @@ -6679,9 +6253,9 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am { int delamount; struct item* inv = &sd->status.inventory[idx]; - + delamount = ( amount[0] < inv->amount ) ? amount[0] : inv->amount; - + if( delete_items ) { if( sd->inventory_data[idx]->type == IT_PETEGG && inv->card[0] == CARD0_PET ) @@ -6690,7 +6264,7 @@ static void buildin_delitem_delete(struct map_session_data* sd, int idx, int* am } pc_delitem(sd, idx, delamount, 0, 0, LOG_TYPE_SCRIPT); } - + amount[0]-= delamount; } @@ -6705,10 +6279,10 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, bool delete_items = false; int i, amount, important; struct item* inv; - + // prefer always non-equipped items it->equip = 0; - + // when searching for nameid only, prefer additionally if( !exact_match ) { @@ -6717,28 +6291,28 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, // card-less items memset(it->card, 0, sizeof(it->card)); } - + for(;;) { amount = it->amount; important = 0; - + // 1st pass -- less important items / exact match for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ ) { inv = &sd->status.inventory[i]; - + if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid ) {// wrong/invalid item continue; } - + if( inv->equip != it->equip || inv->refine != it->refine ) {// not matching attributes important++; continue; } - + if( exact_match ) { if( inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) ) @@ -6761,11 +6335,11 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, continue; } } - + // count / delete item buildin_delitem_delete(sd, i, &amount, delete_items); } - + // 2nd pass -- any matching item if( amount == 0 || important == 0 ) {// either everything was already consumed or no items were skipped @@ -6774,17 +6348,17 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, else for( i = 0; amount && i < ARRAYLENGTH(sd->status.inventory); i++ ) { inv = &sd->status.inventory[i]; - + if( !inv->nameid || !sd->inventory_data[i] || inv->nameid != it->nameid ) {// wrong/invalid item continue; } - + if( sd->inventory_data[i]->type == IT_PETEGG && inv->card[0] == CARD0_PET && CheckForCharServer() ) {// pet which cannot be deleted continue; } - + if( exact_match ) { if( inv->refine != it->refine || inv->identify != it->identify || inv->attribute != it->attribute || memcmp(inv->card, it->card, sizeof(inv->card)) ) @@ -6792,11 +6366,11 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, continue; } } - + // count / delete item buildin_delitem_delete(sd, i, &amount, delete_items); } - + if( amount ) {// not enough items return false; @@ -6818,12 +6392,12 @@ static bool buildin_delitem_search(struct map_session_data* sd, struct item* it, /// /// delitem <item id>,<amount>{,<account id>} /// delitem "<item name>",<amount>{,<account id>} -BUILDIN_FUNC(delitem) +BUILDIN(delitem) { TBL_PC *sd; struct item it; struct script_data *data; - + if( script_hasdata(st,4) ) { int account_id = script_getnum(st,4); @@ -6832,67 +6406,67 @@ BUILDIN_FUNC(delitem) { ShowError("script:delitem: player not found (AID=%d).\n", account_id); st->state = END; - return 1; + return false; } } else { sd = script_rid2sd(st);// attached player if( sd == NULL ) - return 0; + return true; } - + data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) { - const char* item_name = conv_str(st,data); + const char* item_name = script->conv_str(st,data); struct item_data* id = itemdb_searchname(item_name); if( id == NULL ) { ShowError("script:delitem: unknown item \"%s\".\n", item_name); st->state = END; - return 1; + return false; } it.nameid = id->nameid;// "<item name>" } else { - it.nameid = conv_num(st,data);// <item id> + it.nameid = script->conv_num(st,data);// <item id> if( !itemdb_exists( it.nameid ) ) { ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); st->state = END; - return 1; + return false; } } - + it.amount=script_getnum(st,3); - + if( it.amount <= 0 ) - return 0;// nothing to do - + return true;// nothing to do + if( buildin_delitem_search(sd, &it, false) ) {// success - return 0; + return true; } - + ShowError("script:delitem: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid); st->state = END; - clif_scriptclose(sd, st->oid); - return 1; + clif->scriptclose(sd, st->oid); + return false; } /// Deletes items from the target/attached player. /// /// delitem2 <item id>,<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>} /// delitem2 "<Item name>",<amount>,<identify>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>{,<account ID>} -BUILDIN_FUNC(delitem2) +BUILDIN(delitem2) { TBL_PC *sd; struct item it; struct script_data *data; - + if( script_hasdata(st,11) ) { int account_id = script_getnum(st,11); @@ -6901,41 +6475,41 @@ BUILDIN_FUNC(delitem2) { ShowError("script:delitem2: player not found (AID=%d).\n", account_id); st->state = END; - return 1; + return false; } } else { sd = script_rid2sd(st);// attached player if( sd == NULL ) - return 0; + return true; } - + data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) { - const char* item_name = conv_str(st,data); + const char* item_name = script->conv_str(st,data); struct item_data* id = itemdb_searchname(item_name); if( id == NULL ) { ShowError("script:delitem2: unknown item \"%s\".\n", item_name); st->state = END; - return 1; + return false; } it.nameid = id->nameid;// "<item name>" } else { - it.nameid = conv_num(st,data);// <item id> + it.nameid = script->conv_num(st,data);// <item id> if( !itemdb_exists( it.nameid ) ) { ShowError("script:delitem: unknown item \"%d\".\n", it.nameid); st->state = END; - return 1; + return false; } } - + it.amount=script_getnum(st,3); it.identify=script_getnum(st,4); it.refine=script_getnum(st,5); @@ -6944,65 +6518,65 @@ BUILDIN_FUNC(delitem2) it.card[1]=(short)script_getnum(st,8); it.card[2]=(short)script_getnum(st,9); it.card[3]=(short)script_getnum(st,10); - + if( it.amount <= 0 ) - return 0;// nothing to do - + return true;// nothing to do + if( buildin_delitem_search(sd, &it, true) ) {// success - return 0; + return true; } - + ShowError("script:delitem2: failed to delete %d items (AID=%d item_id=%d).\n", it.amount, sd->status.account_id, it.nameid); st->state = END; - clif_scriptclose(sd, st->oid); - return 1; + clif->scriptclose(sd, st->oid); + return false; } /*========================================== * Enables/Disables use of items while in an NPC [Skotlex] *------------------------------------------*/ -BUILDIN_FUNC(enableitemuse) +BUILDIN(enableitemuse) { TBL_PC *sd; sd=script_rid2sd(st); if (sd) - sd->npc_item_flag = st->oid; - return 0; + st->npc_item_flag = sd->npc_item_flag = 1; + return true; } -BUILDIN_FUNC(disableitemuse) +BUILDIN(disableitemuse) { TBL_PC *sd; sd=script_rid2sd(st); if (sd) - sd->npc_item_flag = 0; - return 0; + st->npc_item_flag = sd->npc_item_flag = 0; + return true; } /*========================================== * return the basic stats of sd * chk pc_readparam for available type *------------------------------------------*/ -BUILDIN_FUNC(readparam) +BUILDIN(readparam) { int type; TBL_PC *sd; - + type=script_getnum(st,2); if( script_hasdata(st,3) ) sd=map_nick2sd(script_getstr(st,3)); else sd=script_rid2sd(st); - + if(sd==NULL){ script_pushint(st,-1); - return 0; + return true; } - + script_pushint(st,pc_readparam(sd,type)); - - return 0; + + return true; } /*========================================== @@ -7014,54 +6588,54 @@ BUILDIN_FUNC(readparam) * 3 : account_id * 4 : bg_id *------------------------------------------*/ -BUILDIN_FUNC(getcharid) +BUILDIN(getcharid) { int num; TBL_PC *sd; - + num = script_getnum(st,2); if( script_hasdata(st,3) ) sd=map_nick2sd(script_getstr(st,3)); else sd=script_rid2sd(st); - + if(sd==NULL){ script_pushint(st,0); //return 0, according docs - return 0; + return true; } - + switch( num ) { - case 0: script_pushint(st,sd->status.char_id); break; - case 1: script_pushint(st,sd->status.party_id); break; - case 2: script_pushint(st,sd->status.guild_id); break; - case 3: script_pushint(st,sd->status.account_id); break; - case 4: script_pushint(st,sd->bg_id); break; - default: - ShowError("buildin_getcharid: invalid parameter (%d).\n", num); - script_pushint(st,0); - break; + case 0: script_pushint(st,sd->status.char_id); break; + case 1: script_pushint(st,sd->status.party_id); break; + case 2: script_pushint(st,sd->status.guild_id); break; + case 3: script_pushint(st,sd->status.account_id); break; + case 4: script_pushint(st,sd->bg_id); break; + default: + ShowError("buildin_getcharid: invalid parameter (%d).\n", num); + script_pushint(st,0); + break; } - - return 0; + + return true; } /*========================================== * returns the GID of an NPC *------------------------------------------*/ -BUILDIN_FUNC(getnpcid) +BUILDIN(getnpcid) { int num = script_getnum(st,2); struct npc_data* nd = NULL; - + if( script_hasdata(st,3) ) {// unique npc name if( ( nd = npc_name2id(script_getstr(st,3)) ) == NULL ) { ShowError("buildin_getnpcid: No such NPC '%s'.\n", script_getstr(st,3)); script_pushint(st,0); - return 1; + return false; } } - + switch (num) { case 0: script_pushint(st,nd ? nd->bl.id : st->oid); @@ -7069,23 +6643,23 @@ BUILDIN_FUNC(getnpcid) default: ShowError("buildin_getnpcid: invalid parameter (%d).\n", num); script_pushint(st,0); - return 1; + return false; } - - return 0; + + return true; } /*========================================== * Return the name of the party_id * null if not found *------------------------------------------*/ -BUILDIN_FUNC(getpartyname) +BUILDIN(getpartyname) { int party_id; struct party_data* p; - + party_id = script_getnum(st,2); - + if( ( p = party_search(party_id) ) != NULL ) { script_pushstrcopy(st,p->party.name); @@ -7094,7 +6668,7 @@ BUILDIN_FUNC(getpartyname) { script_pushconststr(st,"null"); } - return 0; + return true; } /*========================================== @@ -7105,64 +6679,64 @@ BUILDIN_FUNC(getpartyname) * 1 : char_id des membres * 2 : account_id des membres *------------------------------------------*/ -BUILDIN_FUNC(getpartymember) +BUILDIN(getpartymember) { struct party_data *p; int i,j=0,type=0; - + p=party_search(script_getnum(st,2)); - + if( script_hasdata(st,3) ) type=script_getnum(st,3); - + if(p!=NULL){ for(i=0;i<MAX_PARTY;i++){ if(p->party.member[i].account_id){ switch (type) { - case 2: - mapreg_setreg(reference_uid(add_str("$@partymemberaid"), j),p->party.member[i].account_id); - break; - case 1: - mapreg_setreg(reference_uid(add_str("$@partymembercid"), j),p->party.member[i].char_id); - break; - default: - mapreg_setregstr(reference_uid(add_str("$@partymembername$"), j),p->party.member[i].name); + case 2: + mapreg_setreg(reference_uid(add_str("$@partymemberaid"), j),p->party.member[i].account_id); + break; + case 1: + mapreg_setreg(reference_uid(add_str("$@partymembercid"), j),p->party.member[i].char_id); + break; + default: + mapreg_setregstr(reference_uid(add_str("$@partymembername$"), j),p->party.member[i].name); } j++; } } } mapreg_setreg(add_str("$@partymembercount"),j); - - return 0; + + return true; } /*========================================== * Retrieves party leader. if flag is specified, * return some of the leader data. Otherwise, return name. *------------------------------------------*/ -BUILDIN_FUNC(getpartyleader) +BUILDIN(getpartyleader) { int party_id, type = 0, i=0; struct party_data *p; - + party_id=script_getnum(st,2); if( script_hasdata(st,3) ) type=script_getnum(st,3); - + p=party_search(party_id); - + if (p) //Search leader - for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); - + for(i = 0; i < MAX_PARTY && !p->party.member[i].leader; i++); + if (!p || i == MAX_PARTY) { //leader not found if (type) script_pushint(st,-1); else script_pushconststr(st,"null"); - return 0; + return true; } - + switch (type) { case 1: script_pushint(st,p->party.member[i].account_id); break; case 2: script_pushint(st,p->party.member[i].char_id); break; @@ -7171,21 +6745,21 @@ BUILDIN_FUNC(getpartyleader) case 5: script_pushint(st,p->party.member[i].lv); break; default: script_pushstrcopy(st,p->party.member[i].name); break; } - return 0; + return true; } /*========================================== * Return the name of the @guild_id * null if not found *------------------------------------------*/ -BUILDIN_FUNC(getguildname) +BUILDIN(getguildname) { int guild_id; struct guild* g; - + guild_id = script_getnum(st,2); - - if( ( g = guild_search(guild_id) ) != NULL ) + + if( ( g = guild->search(guild_id) ) != NULL ) { script_pushstrcopy(st,g->name); } @@ -7193,21 +6767,21 @@ BUILDIN_FUNC(getguildname) { script_pushconststr(st,"null"); } - return 0; + return true; } /*========================================== * Return the name of the guild master of @guild_id * null if not found *------------------------------------------*/ -BUILDIN_FUNC(getguildmaster) +BUILDIN(getguildmaster) { int guild_id; struct guild* g; - + guild_id = script_getnum(st,2); - - if( ( g = guild_search(guild_id) ) != NULL ) + + if( ( g = guild->search(guild_id) ) != NULL ) { script_pushstrcopy(st,g->member[0].name); } @@ -7215,17 +6789,17 @@ BUILDIN_FUNC(getguildmaster) { script_pushconststr(st,"null"); } - return 0; + return true; } -BUILDIN_FUNC(getguildmasterid) +BUILDIN(getguildmasterid) { int guild_id; struct guild* g; - + guild_id = script_getnum(st,2); - - if( ( g = guild_search(guild_id) ) != NULL ) + + if( ( g = guild->search(guild_id) ) != NULL ) { script_pushint(st,g->member[0].char_id); } @@ -7233,7 +6807,7 @@ BUILDIN_FUNC(getguildmasterid) { script_pushint(st,0); } - return 0; + return true; } /*========================================== @@ -7245,17 +6819,17 @@ BUILDIN_FUNC(getguildmasterid) * 3 : map_name * - : "" *------------------------------------------*/ -BUILDIN_FUNC(strcharinfo) +BUILDIN(strcharinfo) { TBL_PC *sd; int num; struct guild* g; struct party_data* p; - + sd=script_rid2sd(st); if (!sd) { //Avoid crashing.... script_pushconststr(st,""); - return 0; + return true; } num=script_getnum(st,2); switch(num){ @@ -7263,22 +6837,16 @@ BUILDIN_FUNC(strcharinfo) script_pushstrcopy(st,sd->status.name); break; case 1: - if( ( p = party_search(sd->status.party_id) ) != NULL ) - { + if( ( p = party_search(sd->status.party_id) ) != NULL ) { script_pushstrcopy(st,p->party.name); - } - else - { + } else { script_pushconststr(st,""); } break; case 2: - if( ( g = guild_search(sd->status.guild_id) ) != NULL ) - { + if( ( g = sd->guild ) != NULL ) { script_pushstrcopy(st,g->name); - } - else - { + } else { script_pushconststr(st,""); } break; @@ -7290,8 +6858,8 @@ BUILDIN_FUNC(strcharinfo) script_pushconststr(st,""); break; } - - return 0; + + return true; } /*========================================== @@ -7303,18 +6871,18 @@ BUILDIN_FUNC(strcharinfo) * 3 : ::str * 4 : map name *------------------------------------------*/ -BUILDIN_FUNC(strnpcinfo) +BUILDIN(strnpcinfo) { TBL_NPC* nd; int num; char *buf,*name=NULL; - + nd = map_id2nd(st->oid); if (!nd) { script_pushconststr(st, ""); - return 0; + return true; } - + num = script_getnum(st,2); switch(num){ case 0: // display name @@ -7339,204 +6907,204 @@ BUILDIN_FUNC(strnpcinfo) name = aStrdup(map[nd->bl.m].name); break; } - + if(name) script_pushstr(st, name); else script_pushconststr(st, ""); - - return 0; + + return true; } // aegis->athena slot position conversion table -static unsigned int equip[] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW}; +static unsigned int equip[] = {EQP_HEAD_TOP,EQP_ARMOR,EQP_HAND_L,EQP_HAND_R,EQP_GARMENT,EQP_SHOES,EQP_ACC_L,EQP_ACC_R,EQP_HEAD_MID,EQP_HEAD_LOW,EQP_COSTUME_HEAD_LOW,EQP_COSTUME_HEAD_MID,EQP_COSTUME_HEAD_TOP,EQP_COSTUME_GARMENT}; /*========================================== * GetEquipID(Pos); Pos: 1-10 *------------------------------------------*/ -BUILDIN_FUNC(getequipid) +BUILDIN(getequipid) { int i, num; TBL_PC* sd; struct item_data* item; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + num = script_getnum(st,2) - 1; if( num < 0 || num >= ARRAYLENGTH(equip) ) { script_pushint(st,-1); - return 0; + return true; } - + // get inventory position of item i = pc_checkequip(sd,equip[num]); if( i < 0 ) { script_pushint(st,-1); - return 0; + return true; } - + item = sd->inventory_data[i]; if( item != 0 ) script_pushint(st,item->nameid); else script_pushint(st,0); - - return 0; + + return true; } /*========================================== * Get the equipement name at pos * return item jname or "" *------------------------------------------*/ -BUILDIN_FUNC(getequipname) +BUILDIN(getequipname) { int i, num; TBL_PC* sd; struct item_data* item; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + num = script_getnum(st,2) - 1; if( num < 0 || num >= ARRAYLENGTH(equip) ) { script_pushconststr(st,""); - return 0; + return true; } - + // get inventory position of item i = pc_checkequip(sd,equip[num]); if( i < 0 ) { script_pushconststr(st,""); - return 0; + return true; } - + item = sd->inventory_data[i]; if( item != 0 ) script_pushstrcopy(st,item->jname); else script_pushconststr(st,""); - - return 0; + + return true; } /*========================================== * getbrokenid [Valaris] *------------------------------------------*/ -BUILDIN_FUNC(getbrokenid) +BUILDIN(getbrokenid) { int i,num,id=0,brokencounter=0; TBL_PC *sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + num=script_getnum(st,2); for(i=0; i<MAX_INVENTORY; i++) { if(sd->status.inventory[i].attribute){ - brokencounter++; - if(num==brokencounter){ - id=sd->status.inventory[i].nameid; - break; - } + brokencounter++; + if(num==brokencounter){ + id=sd->status.inventory[i].nameid; + break; + } } } - + script_pushint(st,id); - - return 0; + + return true; } /*========================================== * repair [Valaris] *------------------------------------------*/ -BUILDIN_FUNC(repair) +BUILDIN(repair) { int i,num; int repaircounter=0; TBL_PC *sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + num=script_getnum(st,2); for(i=0; i<MAX_INVENTORY; i++) { if(sd->status.inventory[i].attribute){ - repaircounter++; - if(num==repaircounter){ - sd->status.inventory[i].attribute=0; - clif_equiplist(sd); - clif_produceeffect(sd, 0, sd->status.inventory[i].nameid); - clif_misceffect(&sd->bl, 3); - break; - } + repaircounter++; + if(num==repaircounter){ + sd->status.inventory[i].attribute=0; + clif->equiplist(sd); + clif->produce_effect(sd, 0, sd->status.inventory[i].nameid); + clif->misceffect(&sd->bl, 3); + break; + } } } - - return 0; + + return true; } /*========================================== * repairall *------------------------------------------*/ -BUILDIN_FUNC(repairall) +BUILDIN(repairall) { int i, repaircounter = 0; TBL_PC *sd; - + sd = script_rid2sd(st); if(sd == NULL) - return 0; - + return true; + for(i = 0; i < MAX_INVENTORY; i++) { if(sd->status.inventory[i].nameid && sd->status.inventory[i].attribute) { sd->status.inventory[i].attribute = 0; - clif_produceeffect(sd,0,sd->status.inventory[i].nameid); + clif->produce_effect(sd,0,sd->status.inventory[i].nameid); repaircounter++; } } - + if(repaircounter) { - clif_misceffect(&sd->bl, 3); - clif_equiplist(sd); + clif->misceffect(&sd->bl, 3); + clif->equiplist(sd); } - - return 0; + + return true; } /*========================================== * Chk if player have something equiped at pos *------------------------------------------*/ -BUILDIN_FUNC(getequipisequiped) +BUILDIN(getequipisequiped) { int i = -1,num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); - + if(i >= 0) script_pushint(st,1); else - script_pushint(st,0); - return 0; + script_pushint(st,0); + return true; } /*========================================== @@ -7546,24 +7114,24 @@ BUILDIN_FUNC(getequipisequiped) * 1 : true * 0 : false *------------------------------------------*/ -BUILDIN_FUNC(getequipisenableref) +BUILDIN(getequipisenableref) { int i = -1,num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if( num > 0 && num <= ARRAYLENGTH(equip) ) i = pc_checkequip(sd,equip[num-1]); if( i >= 0 && sd->inventory_data[i] && !sd->inventory_data[i]->flag.no_refine && !sd->status.inventory[i].expire_time ) script_pushint(st,1); else script_pushint(st,0); - - return 0; + + return true; } /*========================================== @@ -7572,24 +7140,24 @@ BUILDIN_FUNC(getequipisenableref) * 1 : true * 0 : false *------------------------------------------*/ -BUILDIN_FUNC(getequipisidentify) +BUILDIN(getequipisidentify) { int i = -1,num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0) script_pushint(st,sd->status.inventory[i].identify); else script_pushint(st,0); - - return 0; + + return true; } /*========================================== @@ -7598,24 +7166,24 @@ BUILDIN_FUNC(getequipisidentify) * x : refine amount * 0 : false (not refined) *------------------------------------------*/ -BUILDIN_FUNC(getequiprefinerycnt) +BUILDIN(getequiprefinerycnt) { int i = -1,num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0) script_pushint(st,sd->status.inventory[i].refine); else script_pushint(st,0); - - return 0; + + return true; } /*========================================== @@ -7625,24 +7193,24 @@ BUILDIN_FUNC(getequiprefinerycnt) * x : weapon level * 0 : false *------------------------------------------*/ -BUILDIN_FUNC(getequipweaponlv) +BUILDIN(getequipweaponlv) { int i = -1,num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0 && sd->inventory_data[i]) script_pushint(st,sd->inventory_data[i]->wlv); else script_pushint(st,0); - - return 0; + + return true; } /*========================================== @@ -7651,63 +7219,63 @@ BUILDIN_FUNC(getequipweaponlv) * x : refine chance * 0 : false (max refine level or unequip..) *------------------------------------------*/ -BUILDIN_FUNC(getequippercentrefinery) +BUILDIN(getequippercentrefinery) { int i = -1,num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0 && sd->status.inventory[i].nameid && sd->status.inventory[i].refine < MAX_REFINE) script_pushint(st,status_get_refine_chance(itemdb_wlv(sd->status.inventory[i].nameid), (int)sd->status.inventory[i].refine)); else script_pushint(st,0); - - return 0; + + return true; } /*========================================== * Refine +1 item at pos and log and display refine *------------------------------------------*/ -BUILDIN_FUNC(successrefitem) +BUILDIN(successrefitem) { int i=-1,num,ep; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0) { ep=sd->status.inventory[i].equip; - + //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); - + logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]); + sd->status.inventory[i].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); - clif_delitem(sd,i,1,3); - + + clif->refine(sd->fd,0,i,sd->status.inventory[i].refine); + clif->delitem(sd,i,1,3); + //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); - - clif_additem(sd,i,1,0); + logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]); + + clif->additem(sd,i,1,0); pc_equipitem(sd,i,ep); - clif_misceffect(&sd->bl,3); + clif->misceffect(&sd->bl,3); if(sd->status.inventory[i].refine == MAX_REFINE && - sd->status.inventory[i].card[0] == CARD0_FORGE && - sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) - ){ // Fame point system [DracoRPG] + sd->status.inventory[i].card[0] == CARD0_FORGE && + sd->status.char_id == (int)MakeDWord(sd->status.inventory[i].card[2],sd->status.inventory[i].card[3]) + ){ // Fame point system [DracoRPG] switch (sd->inventory_data[i]->wlv){ case 1: pc_addfame(sd,1); // Success to refine to +10 a lv1 weapon you forged = +1 fame point @@ -7718,113 +7286,136 @@ BUILDIN_FUNC(successrefitem) case 3: pc_addfame(sd,1000); // Success to refine to +10 a lv3 weapon you forged = +1000 fame point break; - } + } } } - - return 0; + + return true; } /*========================================== * Show a failed Refine +1 attempt *------------------------------------------*/ -BUILDIN_FUNC(failedrefitem) +BUILDIN(failedrefitem) { int i=-1,num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); if(i >= 0) { sd->status.inventory[i].refine = 0; pc_unequipitem(sd,i,3); //recalculate bonus - clif_refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure - + clif->refine(sd->fd,1,i,sd->status.inventory[i].refine); //notify client of failure + pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); - - clif_misceffect(&sd->bl,2); // display failure effect + + clif->misceffect(&sd->bl,2); // display failure effect } - - return 0; + + return true; } /*========================================== * Downgrades an Equipment Part by -1 . [Masao] *------------------------------------------*/ -BUILDIN_FUNC(downrefitem) +BUILDIN(downrefitem) { int i = -1,num,ep; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if (num > 0 && num <= ARRAYLENGTH(equip)) i = pc_checkequip(sd,equip[num-1]); if(i >= 0) { ep = sd->status.inventory[i].equip; - + //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i]); - + logs->pick_pc(sd, LOG_TYPE_SCRIPT, -1, &sd->status.inventory[i],sd->inventory_data[i]); + sd->status.inventory[i].refine++; pc_unequipitem(sd,i,2); // status calc will happen in pc_equipitem() below - - clif_refine(sd->fd,2,i,sd->status.inventory[i].refine = sd->status.inventory[i].refine - 2); - clif_delitem(sd,i,1,3); - + + clif->refine(sd->fd,2,i,sd->status.inventory[i].refine = sd->status.inventory[i].refine - 2); + clif->delitem(sd,i,1,3); + //Logs items, got from (N)PC scripts [Lupus] - log_pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i]); - - clif_additem(sd,i,1,0); + logs->pick_pc(sd, LOG_TYPE_SCRIPT, 1, &sd->status.inventory[i],sd->inventory_data[i]); + + clif->additem(sd,i,1,0); pc_equipitem(sd,i,ep); - clif_misceffect(&sd->bl,2); + clif->misceffect(&sd->bl,2); } + + return true; +} - return 0; +/*========================================== + * Delete the item equipped at pos. + *------------------------------------------*/ +BUILDIN(delequip) +{ + int i=-1,num; + TBL_PC *sd; + + num = script_getnum(st,2); + sd = script_rid2sd(st); + if( sd == NULL ) + return true; + + if (num > 0 && num <= ARRAYLENGTH(equip)) + i=pc_checkequip(sd,equip[num-1]); + if(i >= 0) { + pc_unequipitem(sd,i,3); //recalculate bonus + pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); + } + + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(statusup) +BUILDIN(statusup) { int type; TBL_PC *sd; - + type=script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pc_statusup(sd,type); - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(statusup2) +BUILDIN(statusup2) { int type,val; TBL_PC *sd; - + type=script_getnum(st,2); val=script_getnum(st,3); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pc_statusup2(sd,type,val); - - return 0; + + return true; } /// See 'doc/item_bonus.txt' @@ -7834,7 +7425,7 @@ BUILDIN_FUNC(statusup2) /// bonus3 <bonus type>,<val1>,<val2>,<val3>; /// bonus4 <bonus type>,<val1>,<val2>,<val3>,<val4>; /// bonus5 <bonus type>,<val1>,<val2>,<val3>,<val4>,<val5>; -BUILDIN_FUNC(bonus) +BUILDIN(bonus) { int type; int val1; @@ -7843,11 +7434,11 @@ BUILDIN_FUNC(bonus) int val4 = 0; int val5 = 0; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; // no player attached - + return true; // no player attached + type = script_getnum(st,2); switch( type ) { case SP_AUTOSPELL: @@ -7864,15 +7455,16 @@ BUILDIN_FUNC(bonus) case SP_SKILL_FIXEDCAST: case SP_SKILL_VARIABLECAST: case SP_VARCASTRATE: + case SP_FIXCASTRATE: case SP_SKILL_USE_SP: // these bonuses support skill names - val1 = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); + val1 = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) ); break; default: val1 = script_getnum(st,3); break; } - + switch( script_lastdata(st)-2 ) { case 1: pc_bonus(sd, type, val1); @@ -7888,20 +7480,20 @@ BUILDIN_FUNC(bonus) break; case 4: if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) ) - val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name + val2 = skill->name2id(script_getstr(st,4)); // 2nd value can be skill name else val2 = script_getnum(st,4); - + val3 = script_getnum(st,5); val4 = script_getnum(st,6); pc_bonus4(sd, type, val1, val2, val3, val4); break; case 5: if( type == SP_AUTOSPELL_ONSKILL && script_isstring(st,4) ) - val2 = skill_name2id(script_getstr(st,4)); // 2nd value can be skill name + val2 = skill->name2id(script_getstr(st,4)); // 2nd value can be skill name else val2 = script_getnum(st,4); - + val3 = script_getnum(st,5); val4 = script_getnum(st,6); val5 = script_getnum(st,7); @@ -7911,117 +7503,117 @@ BUILDIN_FUNC(bonus) ShowDebug("buildin_bonus: unexpected number of arguments (%d)\n", (script_lastdata(st) - 1)); break; } - - return 0; + + return true; } -BUILDIN_FUNC(autobonus) +BUILDIN(autobonus) { unsigned int dur; short rate; short atk_type = 0; TBL_PC* sd; const char *bonus_script, *other_script = NULL; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; // no player attached - + return true; // no player attached + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) - return 0; - + return true; + rate = script_getnum(st,3); dur = script_getnum(st,4); bonus_script = script_getstr(st,2); if( !rate || !dur || !bonus_script ) - return 0; - + return true; + if( script_hasdata(st,5) ) atk_type = script_getnum(st,5); if( script_hasdata(st,6) ) other_script = script_getstr(st,6); - + if( pc_addautobonus(sd->autobonus,ARRAYLENGTH(sd->autobonus), - bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) { script_add_autobonus(bonus_script); if( other_script ) script_add_autobonus(other_script); } - - return 0; + + return true; } -BUILDIN_FUNC(autobonus2) +BUILDIN(autobonus2) { unsigned int dur; short rate; short atk_type = 0; TBL_PC* sd; const char *bonus_script, *other_script = NULL; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; // no player attached - + return true; // no player attached + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) - return 0; - + return true; + rate = script_getnum(st,3); dur = script_getnum(st,4); bonus_script = script_getstr(st,2); if( !rate || !dur || !bonus_script ) - return 0; - + return true; + if( script_hasdata(st,5) ) atk_type = script_getnum(st,5); if( script_hasdata(st,6) ) other_script = script_getstr(st,6); - + if( pc_addautobonus(sd->autobonus2,ARRAYLENGTH(sd->autobonus2), - bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,false) ) { script_add_autobonus(bonus_script); if( other_script ) script_add_autobonus(other_script); } - - return 0; + + return true; } -BUILDIN_FUNC(autobonus3) +BUILDIN(autobonus3) { unsigned int dur; short rate,atk_type; TBL_PC* sd; const char *bonus_script, *other_script = NULL; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; // no player attached - + return true; // no player attached + if( sd->state.autobonus&sd->status.inventory[current_equip_item_index].equip ) - return 0; - + return true; + rate = script_getnum(st,3); dur = script_getnum(st,4); - atk_type = ( script_isstring(st,5) ? skill_name2id(script_getstr(st,5)) : script_getnum(st,5) ); + atk_type = ( script_isstring(st,5) ? skill->name2id(script_getstr(st,5)) : script_getnum(st,5) ); bonus_script = script_getstr(st,2); if( !rate || !dur || !atk_type || !bonus_script ) - return 0; - + return true; + if( script_hasdata(st,6) ) other_script = script_getstr(st,6); - + if( pc_addautobonus(sd->autobonus3,ARRAYLENGTH(sd->autobonus3), - bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true) ) + bonus_script,rate,dur,atk_type,other_script,sd->status.inventory[current_equip_item_index].equip,true) ) { script_add_autobonus(bonus_script); if( other_script ) script_add_autobonus(other_script); } - - return 0; + + return true; } /// Changes the level of a player skill. @@ -8034,24 +7626,24 @@ BUILDIN_FUNC(autobonus3) /// skill <skill id>,<level> /// skill "<skill name>",<level>,<flag> /// skill "<skill name>",<level> -BUILDIN_FUNC(skill) +BUILDIN(skill) { int id; int level; int flag = 1; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - - id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + return true;// no player attached, report source + + id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); level = script_getnum(st,3); if( script_hasdata(st,4) ) flag = script_getnum(st,4); pc_skill(sd, id, level, flag); - - return 0; + + return true; } /// Changes the level of a player skill. @@ -8063,87 +7655,87 @@ BUILDIN_FUNC(skill) /// addtoskill "<skill name>",<amount> /// /// @see skill -BUILDIN_FUNC(addtoskill) +BUILDIN(addtoskill) { int id; int level; int flag = 2; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - - id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + return true;// no player attached, report source + + id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); level = script_getnum(st,3); if( script_hasdata(st,4) ) flag = script_getnum(st,4); pc_skill(sd, id, level, flag); - - return 0; + + return true; } /// Increases the level of a guild skill. /// /// guildskill <skill id>,<amount>; /// guildskill "<skill name>",<amount>; -BUILDIN_FUNC(guildskill) +BUILDIN(guildskill) { int id; int level; TBL_PC* sd; int i; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - - id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + return true;// no player attached, report source + + id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); level = script_getnum(st,3); for( i=0; i < level; i++ ) - guild_skillup(sd, id); - - return 0; + guild->skillup(sd, id); + + return true; } /// Returns the level of the player skill. /// /// getskilllv(<skill id>) -> <level> /// getskilllv("<skill name>") -> <level> -BUILDIN_FUNC(getskilllv) +BUILDIN(getskilllv) { int id; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - - id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + return true;// no player attached, report source + + id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); script_pushint(st, pc_checkskill(sd,id)); - - return 0; + + return true; } /// Returns the level of the guild skill. /// /// getgdskilllv(<guild id>,<skill id>) -> <level> /// getgdskilllv(<guild id>,"<skill name>") -> <level> -BUILDIN_FUNC(getgdskilllv) +BUILDIN(getgdskilllv) { int guild_id; uint16 skill_id; struct guild* g; - + guild_id = script_getnum(st,2); - skill_id = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); - g = guild_search(guild_id); + skill_id = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) ); + g = guild->search(guild_id); if( g == NULL ) script_pushint(st, -1); else - script_pushint(st, guild_checkskill(g,skill_id)); - - return 0; + script_pushint(st, guild->checkskill(g,skill_id)); + + return true; } /// Returns the 'basic_skill_check' setting. @@ -8151,113 +7743,113 @@ BUILDIN_FUNC(getgdskilllv) /// before allowing the basic actions. /// /// basicskillcheck() -> <bool> -BUILDIN_FUNC(basicskillcheck) +BUILDIN(basicskillcheck) { script_pushint(st, battle_config.basic_skill_check); - return 0; + return true; } /// Returns the GM level of the player. /// /// getgmlevel() -> <level> -BUILDIN_FUNC(getgmlevel) +BUILDIN(getgmlevel) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + script_pushint(st, pc_get_group_level(sd)); - - return 0; + + return true; } /// Returns the group ID of the player. /// /// getgroupid() -> <int> -BUILDIN_FUNC(getgroupid) +BUILDIN(getgroupid) { TBL_PC* sd; - + sd = script_rid2sd(st); if (sd == NULL) - return 1; // no player attached, report source + return false; // no player attached, report source script_pushint(st, pc_get_group_id(sd)); - - return 0; + + return true; } /// Terminates the execution of this script instance. /// /// end -BUILDIN_FUNC(end) +BUILDIN(end) { st->state = END; - return 0; + return true; } /// Checks if the player has that effect state (option). /// /// checkoption(<option>) -> <bool> -BUILDIN_FUNC(checkoption) +BUILDIN(checkoption) { int option; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + option = script_getnum(st,2); if( sd->sc.option&option ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Checks if the player is in that body state (opt1). /// /// checkoption1(<opt1>) -> <bool> -BUILDIN_FUNC(checkoption1) +BUILDIN(checkoption1) { int opt1; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + opt1 = script_getnum(st,2); if( sd->sc.opt1 == opt1 ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Checks if the player has that health state (opt2). /// /// checkoption2(<opt2>) -> <bool> -BUILDIN_FUNC(checkoption2) +BUILDIN(checkoption2) { int opt2; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + opt2 = script_getnum(st,2); if( sd->sc.opt2&opt2 ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Changes the effect state (option) of the player. @@ -8267,16 +7859,16 @@ BUILDIN_FUNC(checkoption2) /// /// setoption <option>,<flag>; /// setoption <option>; -BUILDIN_FUNC(setoption) +BUILDIN(setoption) { int option; int flag = 1; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + option = script_getnum(st,2); if( script_hasdata(st,3) ) flag = script_getnum(st,3); @@ -8293,8 +7885,8 @@ BUILDIN_FUNC(setoption) pc_setoption(sd, sd->sc.option|option); } else// Remove option pc_setoption(sd, sd->sc.option&~option); - - return 0; + + return true; } /// Returns if the player has a cart. @@ -8302,20 +7894,20 @@ BUILDIN_FUNC(setoption) /// checkcart() -> <bool> /// /// @author Valaris -BUILDIN_FUNC(checkcart) +BUILDIN(checkcart) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( pc_iscarton(sd) ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Sets the cart of the player. @@ -8329,20 +7921,20 @@ BUILDIN_FUNC(checkcart) /// /// setcart <type>; /// setcart; -BUILDIN_FUNC(setcart) +BUILDIN(setcart) { int type = 1; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( script_hasdata(st,2) ) type = script_getnum(st,2); pc_setcart(sd, type); - - return 0; + + return true; } /// Returns if the player has a falcon. @@ -8350,20 +7942,20 @@ BUILDIN_FUNC(setcart) /// checkfalcon() -> <bool> /// /// @author Valaris -BUILDIN_FUNC(checkfalcon) +BUILDIN(checkfalcon) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( pc_isfalcon(sd) ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Sets if the player has a falcon or not. @@ -8371,21 +7963,21 @@ BUILDIN_FUNC(checkfalcon) /// /// setfalcon <flag>; /// setfalcon; -BUILDIN_FUNC(setfalcon) +BUILDIN(setfalcon) { int flag = 1; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( script_hasdata(st,2) ) flag = script_getnum(st,2); - + pc_setfalcon(sd, flag); - - return 0; + + return true; } /// Returns if the player is riding. @@ -8393,20 +7985,20 @@ BUILDIN_FUNC(setfalcon) /// checkriding() -> <bool> /// /// @author Valaris -BUILDIN_FUNC(checkriding) +BUILDIN(checkriding) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( pc_isriding(sd) || pc_isridingwug(sd) || pc_isridingdragon(sd) ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Sets if the player is riding. @@ -8414,60 +8006,60 @@ BUILDIN_FUNC(checkriding) /// /// setriding <flag>; /// setriding; -BUILDIN_FUNC(setriding) +BUILDIN(setriding) { int flag = 1; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( script_hasdata(st,2) ) flag = script_getnum(st,2); pc_setriding(sd, flag); - - return 0; + + return true; } /// Returns if the player has a warg. /// /// checkwug() -> <bool> /// -BUILDIN_FUNC(checkwug) +BUILDIN(checkwug) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( pc_iswug(sd) || pc_isridingwug(sd) ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Returns if the player is wearing MADO Gear. /// /// checkmadogear() -> <bool> /// -BUILDIN_FUNC(checkmadogear) +BUILDIN(checkmadogear) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( pc_ismadogear(sd) ) script_pushint(st, 1); else script_pushint(st, 0); - - return 0; + + return true; } /// Sets if the player is riding MADO Gear. @@ -8475,78 +8067,78 @@ BUILDIN_FUNC(checkmadogear) /// /// setmadogear <flag>; /// setmadogear; -BUILDIN_FUNC(setmadogear) +BUILDIN(setmadogear) { int flag = 1; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + if( script_hasdata(st,2) ) flag = script_getnum(st,2); pc_setmadogear(sd, flag); - - return 0; + + return true; } /// Sets the save point of the player. /// /// save "<map name>",<x>,<y> /// savepoint "<map name>",<x>,<y> -BUILDIN_FUNC(savepoint) +BUILDIN(savepoint) { int x; int y; short map; const char* str; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached, report source - + return true;// no player attached, report source + str = script_getstr(st, 2); x = script_getnum(st,3); y = script_getnum(st,4); map = mapindex_name2id(str); if( map ) pc_setsavepoint(sd, map, x, y); - - return 0; + + return true; } /*========================================== * GetTimeTick(0: System Tick, 1: Time Second Tick) *------------------------------------------*/ -BUILDIN_FUNC(gettimetick) /* Asgard Version */ +BUILDIN(gettimetick) /* Asgard Version */ { int type; time_t timer; struct tm *t; - + type=script_getnum(st,2); - + switch(type){ - case 2: - //type 2:(Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC - // from the system clock.) - script_pushint(st,(int)time(NULL)); - break; - case 1: - //type 1:(Second Ticks: 0-86399, 00:00:00-23:59:59) - time(&timer); - t=localtime(&timer); - script_pushint(st,((t->tm_hour)*3600+(t->tm_min)*60+t->tm_sec)); - break; - case 0: - default: - //type 0:(System Ticks) - script_pushint(st,gettick()); - break; + case 2: + //type 2:(Get the number of seconds elapsed since 00:00 hours, Jan 1, 1970 UTC + // from the system clock.) + script_pushint(st,(int)time(NULL)); + break; + case 1: + //type 1:(Second Ticks: 0-86399, 00:00:00-23:59:59) + time(&timer); + t=localtime(&timer); + script_pushint(st,((t->tm_hour)*3600+(t->tm_min)*60+t->tm_sec)); + break; + case 0: + default: + //type 0:(System Ticks) + script_pushint(st,gettick()); + break; } - return 0; + return true; } /*========================================== @@ -8555,250 +8147,255 @@ BUILDIN_FUNC(gettimetick) /* Asgard Version */ * 4: WeekDay 5: MonthDay 6: Month * 7: Year *------------------------------------------*/ -BUILDIN_FUNC(gettime) /* Asgard Version */ +BUILDIN(gettime) /* Asgard Version */ { int type; time_t timer; struct tm *t; - + type=script_getnum(st,2); - + time(&timer); t=localtime(&timer); - + switch(type){ - case 1://Sec(0~59) - script_pushint(st,t->tm_sec); - break; - case 2://Min(0~59) - script_pushint(st,t->tm_min); - break; - case 3://Hour(0~23) - script_pushint(st,t->tm_hour); - break; - case 4://WeekDay(0~6) - script_pushint(st,t->tm_wday); - break; - case 5://MonthDay(01~31) - script_pushint(st,t->tm_mday); - break; - case 6://Month(01~12) - script_pushint(st,t->tm_mon+1); - break; - case 7://Year(20xx) - script_pushint(st,t->tm_year+1900); - break; - case 8://Year Day(01~366) - script_pushint(st,t->tm_yday+1); - break; - default://(format error) - script_pushint(st,-1); - break; + case 1://Sec(0~59) + script_pushint(st,t->tm_sec); + break; + case 2://Min(0~59) + script_pushint(st,t->tm_min); + break; + case 3://Hour(0~23) + script_pushint(st,t->tm_hour); + break; + case 4://WeekDay(0~6) + script_pushint(st,t->tm_wday); + break; + case 5://MonthDay(01~31) + script_pushint(st,t->tm_mday); + break; + case 6://Month(01~12) + script_pushint(st,t->tm_mon+1); + break; + case 7://Year(20xx) + script_pushint(st,t->tm_year+1900); + break; + case 8://Year Day(01~366) + script_pushint(st,t->tm_yday+1); + break; + default://(format error) + script_pushint(st,-1); + break; } - return 0; + return true; } /*========================================== * GetTimeStr("TimeFMT", Length); *------------------------------------------*/ -BUILDIN_FUNC(gettimestr) +BUILDIN(gettimestr) { char *tmpstr; const char *fmtstr; int maxlen; time_t now = time(NULL); - + fmtstr=script_getstr(st,2); maxlen=script_getnum(st,3); - + tmpstr=(char *)aMalloc((maxlen+1)*sizeof(char)); strftime(tmpstr,maxlen,fmtstr,localtime(&now)); tmpstr[maxlen]='\0'; - + script_pushstr(st,tmpstr); - return 0; + return true; } /*========================================== * Open player storage *------------------------------------------*/ -BUILDIN_FUNC(openstorage) +BUILDIN(openstorage) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + storage_storageopen(sd); - return 0; + return true; } -BUILDIN_FUNC(guildopenstorage) +BUILDIN(guildopenstorage) { TBL_PC* sd; int ret; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + ret = storage_guild_storageopen(sd); script_pushint(st,ret); - return 0; + return true; } /*========================================== * Make player use a skill trought item usage *------------------------------------------*/ -/// itemskill <skill id>,<level> -/// itemskill "<skill name>",<level> -BUILDIN_FUNC(itemskill) -{ +/// itemskill <skill id>,<level>{,flag +/// itemskill "<skill name>",<level>{,flag +BUILDIN(itemskill) { int id; int lv; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL || sd->ud.skilltimer != INVALID_TIMER ) - return 0; - - id = ( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + return true; + + id = ( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); lv = script_getnum(st,3); - +/* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ +#if 0 + if( !script_hasdata(st, 4) ) { + if( !skill->check_condition_castbegin(sd,id,lv) || !skill->check_condition_castend(sd,id,lv) ) + return true; + } +#endif sd->skillitem=id; sd->skillitemlv=lv; - clif_item_skill(sd,id,lv); - return 0; + clif->item_skill(sd,id,lv); + return true; } /*========================================== * Attempt to create an item *------------------------------------------*/ -BUILDIN_FUNC(produce) +BUILDIN(produce) { int trigger; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + trigger=script_getnum(st,2); - clif_skill_produce_mix_list(sd, -1, trigger); - return 0; + clif->skill_produce_mix_list(sd, -1, trigger); + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(cooking) +BUILDIN(cooking) { int trigger; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + trigger=script_getnum(st,2); - clif_cooking_list(sd, trigger, AM_PHARMACY, 1, 1); - return 0; + clif->cooking_list(sd, trigger, AM_PHARMACY, 1, 1); + return true; } /*========================================== * Create a pet *------------------------------------------*/ -BUILDIN_FUNC(makepet) +BUILDIN(makepet) { TBL_PC* sd; int id,pet_id; - + id=script_getnum(st,2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pet_id = search_petDB_index(id, PET_CLASS); - + if (pet_id < 0) pet_id = search_petDB_index(id, PET_EGG); if (pet_id >= 0 && sd) { sd->catch_target_class = pet_db[pet_id].class_; intif_create_pet( - sd->status.account_id, sd->status.char_id, - (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, - (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, - 100, 0, 1, pet_db[pet_id].jname); + sd->status.account_id, sd->status.char_id, + (short)pet_db[pet_id].class_, (short)mob_db(pet_db[pet_id].class_)->lv, + (short)pet_db[pet_id].EggID, 0, (short)pet_db[pet_id].intimate, + 100, 0, 1, pet_db[pet_id].jname); } - - return 0; + + return true; } /*========================================== * Give player exp base,job * quest_exp_rate/100 *------------------------------------------*/ -BUILDIN_FUNC(getexp) +BUILDIN(getexp) { TBL_PC* sd; int base=0,job=0; double bonus; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + base=script_getnum(st,2); job =script_getnum(st,3); if(base<0 || job<0) - return 0; - + return true; + // bonus for npc-given exp bonus = battle_config.quest_exp_rate / 100.; base = (int) cap_value(base * bonus, 0, INT_MAX); job = (int) cap_value(job * bonus, 0, INT_MAX); - + pc_gainexp(sd, NULL, base, job, true); - - return 0; + + return true; } /*========================================== * Gain guild exp [Celest] *------------------------------------------*/ -BUILDIN_FUNC(guildgetexp) +BUILDIN(guildgetexp) { TBL_PC* sd; int exp; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + exp = script_getnum(st,2); if(exp < 0) - return 0; + return true; if(sd && sd->status.guild_id > 0) - guild_getexp (sd, exp); - - return 0; + guild->getexp (sd, exp); + + return true; } /*========================================== * Changes the guild master of a guild [Skotlex] *------------------------------------------*/ -BUILDIN_FUNC(guildchangegm) +BUILDIN(guildchangegm) { TBL_PC *sd; int guild_id; const char *name; - + guild_id = script_getnum(st,2); name = script_getstr(st,3); sd=map_nick2sd(name); - + if (!sd) script_pushint(st,0); else - script_pushint(st,guild_gm_change(guild_id, sd)); - - return 0; + script_pushint(st,guild->gm_change(guild_id, sd)); + + return true; } /*========================================== @@ -8809,7 +8406,7 @@ BUILDIN_FUNC(guildchangegm) @amount : nb to spawn @event : event to attach to mob *------------------------------------------*/ -BUILDIN_FUNC(monster) +BUILDIN(monster) { const char* mapn = script_getstr(st,2); int x = script_getnum(st,3); @@ -8820,44 +8417,44 @@ BUILDIN_FUNC(monster) const char* event = ""; unsigned int size = SZ_SMALL; unsigned int ai = AI_NONE; - + struct map_session_data* sd; int16 m; - + if (script_hasdata(st, 8)) { event = script_getstr(st, 8); check_event(st, event); } - + if (script_hasdata(st, 9)) { size = script_getnum(st, 9); if (size > 3) { ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); - return 1; + return false; } } - + if (script_hasdata(st, 10)) { ai = script_getnum(st, 10); if (ai > 4) { ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); - return 1; + return false; } } - + if (class_ >= 0 && !mobdb_checkid(class_)) { ShowWarning("buildin_monster: Attempted to spawn non-existing monster class %d\n", class_); - return 1; + return false; } - + sd = map_id2sd(st->rid); - + if (sd && strcmp(mapn, "this") == 0) m = sd->bl.m; else @@ -8868,53 +8465,53 @@ BUILDIN_FUNC(monster) if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) { ShowError("buildin_monster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); - return 1; + return false; } } } - + mob_once_spawn(sd, m, x, y, str, class_, amount, event, size, ai); - return 0; + return true; } /*========================================== * Request List of Monster Drops *------------------------------------------*/ -BUILDIN_FUNC(getmobdrops) +BUILDIN(getmobdrops) { int class_ = script_getnum(st,2); int i, j = 0; struct mob_db *mob; - + if( !mobdb_checkid(class_) ) { script_pushint(st, 0); - return 0; + return true; } - + mob = mob_db(class_); - + for( i = 0; i < MAX_MOB_DROP; i++ ) { if( mob->dropitem[i].nameid < 1 ) continue; if( itemdb_exists(mob->dropitem[i].nameid) == NULL ) continue; - + mapreg_setreg(reference_uid(add_str("$@MobDrop_item"), j), mob->dropitem[i].nameid); mapreg_setreg(reference_uid(add_str("$@MobDrop_rate"), j), mob->dropitem[i].p); - + j++; } - + mapreg_setreg(add_str("$@MobDrop_count"), j); script_pushint(st, 1); - - return 0; + + return true; } /*========================================== * Same as monster but randomize location in x0,x1,y0,y1 area *------------------------------------------*/ -BUILDIN_FUNC(areamonster) +BUILDIN(areamonster) { const char* mapn = script_getstr(st,2); int x0 = script_getnum(st,3); @@ -8927,38 +8524,38 @@ BUILDIN_FUNC(areamonster) const char* event = ""; unsigned int size = SZ_SMALL; unsigned int ai = AI_NONE; - + struct map_session_data* sd; int16 m; - + if (script_hasdata(st,10)) { event = script_getstr(st, 10); check_event(st, event); } - + if (script_hasdata(st, 11)) { size = script_getnum(st, 11); if (size > 3) { ShowWarning("buildin_monster: Attempted to spawn non-existing size %d for monster class %d\n", size, class_); - return 1; + return false; } } - + if (script_hasdata(st, 12)) { ai = script_getnum(st, 12); if (ai > 4) { ShowWarning("buildin_monster: Attempted to spawn non-existing ai %d for monster class %d\n", ai, class_); - return 1; + return false; } } - + sd = map_id2sd(st->rid); - + if (sd && strcmp(mapn, "this") == 0) m = sd->bl.m; else @@ -8969,25 +8566,25 @@ BUILDIN_FUNC(areamonster) if ((m = instance_mapid2imapid(m, st->instance_id)) < 0) { ShowError("buildin_areamonster: Trying to spawn monster (%d) on instance map (%s) without instance attached.\n", class_, mapn); - return 1; + return false; } } } - + mob_once_spawn_area(sd, m, x0, y0, x1, y1, str, class_, amount, event, size, ai); - return 0; + return true; } /*========================================== * KillMonster subcheck, verify if mob to kill ain't got an even to handle, could be force kill by allflag *------------------------------------------*/ - static int buildin_killmonster_sub_strip(struct block_list *bl,va_list ap) +static int buildin_killmonster_sub_strip(struct block_list *bl,va_list ap) { //same fix but with killmonster instead - stripping events from mobs. TBL_MOB* md = (TBL_MOB*)bl; char *event=va_arg(ap,char *); int allflag=va_arg(ap,int); - + md->state.npc_killmonster = 1; - + if(!allflag){ if(strcmp(event,md->npc_event)==0) status_kill(bl); @@ -9003,7 +8600,7 @@ static int buildin_killmonster_sub(struct block_list *bl,va_list ap) TBL_MOB* md = (TBL_MOB*)bl; char *event=va_arg(ap,char *); int allflag=va_arg(ap,int); - + if(!allflag){ if(strcmp(event,md->npc_event)==0) status_kill(bl); @@ -9013,7 +8610,7 @@ static int buildin_killmonster_sub(struct block_list *bl,va_list ap) } return 0; } -BUILDIN_FUNC(killmonster) +BUILDIN(killmonster) { const char *mapname,*event; int16 m,allflag=0; @@ -9023,34 +8620,34 @@ BUILDIN_FUNC(killmonster) allflag = 1; else check_event(st, event); - + if( (m=map_mapname2mapid(mapname))<0 ) - return 0; - + return true; + if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) - return 0; - + return true; + if( script_hasdata(st,4) ) { if ( script_getnum(st,4) == 1 ) { map_foreachinmap(buildin_killmonster_sub, m, BL_MOB, event ,allflag); - return 0; + return true; } } - + map_freeblock_lock(); map_foreachinmap(buildin_killmonster_sub_strip, m, BL_MOB, event ,allflag); map_freeblock_unlock(); - return 0; + return true; } static int buildin_killmonsterall_sub_strip(struct block_list *bl,va_list ap) { //Strips the event from the mob if it's killed the old method. struct mob_data *md; - + md = BL_CAST(BL_MOB, bl); if (md->npc_event[0]) md->npc_event[0] = 0; - + status_kill(bl); return 0; } @@ -9059,65 +8656,65 @@ static int buildin_killmonsterall_sub(struct block_list *bl,va_list ap) status_kill(bl); return 0; } -BUILDIN_FUNC(killmonsterall) +BUILDIN(killmonsterall) { const char *mapname; int16 m; mapname=script_getstr(st,2); - + if( (m = map_mapname2mapid(mapname))<0 ) - return 0; - + return true; + if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) - return 0; - + return true; + if( script_hasdata(st,3) ) { if ( script_getnum(st,3) == 1 ) { map_foreachinmap(buildin_killmonsterall_sub,m,BL_MOB); - return 0; + return true; } } - + map_foreachinmap(buildin_killmonsterall_sub_strip,m,BL_MOB); - return 0; + return true; } /*========================================== * Creates a clone of a player. * clone map, x, y, event, char_id, master_id, mode, flag, duration *------------------------------------------*/ -BUILDIN_FUNC(clone) +BUILDIN(clone) { TBL_PC *sd, *msd=NULL; int char_id,master_id=0,x,y, mode = 0, flag = 0, m; unsigned int duration = 0; const char *map,*event=""; - + map=script_getstr(st,2); x=script_getnum(st,3); y=script_getnum(st,4); event=script_getstr(st,5); char_id=script_getnum(st,6); - + if( script_hasdata(st,7) ) master_id=script_getnum(st,7); - + if( script_hasdata(st,8) ) mode=script_getnum(st,8); - + if( script_hasdata(st,9) ) flag=script_getnum(st,9); - + if( script_hasdata(st,10) ) duration=script_getnum(st,10); - + check_event(st, event); - + m = map_mapname2mapid(map); - if (m < 0) return 0; - + if (m < 0) return true; + sd = map_charid2sd(char_id); - + if (master_id) { msd = map_charid2sd(master_id); if (msd) @@ -9129,28 +8726,28 @@ BUILDIN_FUNC(clone) script_pushint(st,mob_clone_spawn(sd, m, x, y, event, master_id, mode, flag, 1000*duration)); else //Failed to create clone. script_pushint(st,0); - - return 0; + + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(doevent) +BUILDIN(doevent) { const char* event = script_getstr(st,2); struct map_session_data* sd; - + if( ( sd = script_rid2sd(st) ) == NULL ) { - return 0; + return true; } - + check_event(st, event); npc_event(sd, event, 0); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(donpcevent) +BUILDIN(donpcevent) { const char* event = script_getstr(st,2); check_event(st, event); @@ -9160,12 +8757,12 @@ BUILDIN_FUNC(donpcevent) script_pushint(st, 0); } else script_pushint(st, 1); - return 0; + return true; } /// for Aegis compatibility /// basically a specialized 'donpcevent', with the event specified as two arguments instead of one -BUILDIN_FUNC(cmdothernpc) // Added by RoVeRT +BUILDIN(cmdothernpc) // Added by RoVeRT { const char* npc = script_getstr(st,2); const char* command = script_getstr(st,3); @@ -9173,67 +8770,67 @@ BUILDIN_FUNC(cmdothernpc) // Added by RoVeRT snprintf(event, sizeof(event), "%s::OnCommand%s", npc, command); check_event(st, event); npc_event_do(event); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(addtimer) +BUILDIN(addtimer) { int tick = script_getnum(st,2); const char* event = script_getstr(st, 3); TBL_PC* sd; - + check_event(st, event); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pc_addeventtimer(sd,tick,event); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(deltimer) +BUILDIN(deltimer) { const char *event; TBL_PC* sd; - + event=script_getstr(st, 2); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + check_event(st, event); pc_deleventtimer(sd,event); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(addtimercount) +BUILDIN(addtimercount) { const char *event; int tick; TBL_PC* sd; - + event=script_getstr(st, 2); tick=script_getnum(st,3); sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + check_event(st, event); pc_addeventtimercount(sd,event,tick); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(initnpctimer) +BUILDIN(initnpctimer) { struct npc_data *nd; int flag = 0; - + if( script_hasdata(st,3) ) { //Two arguments: NPC name and attach flag. nd = npc_name2id(script_getstr(st, 2)); @@ -9245,43 +8842,43 @@ BUILDIN_FUNC(initnpctimer) data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) //NPC name - nd = npc_name2id(conv_str(st, data)); + nd = npc_name2id(script->conv_str(st, data)); else if( data_isint(data) ) //Flag { nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); + flag = script->conv_num(st,data); } else { ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); - return 1; + return false; } } else nd = (struct npc_data *)map_id2bl(st->oid); - + if( !nd ) - return 0; + return true; if( flag ) //Attach { TBL_PC* sd = script_rid2sd(st); if( sd == NULL ) - return 0; + return true; nd->u.scr.rid = sd->bl.id; } - + nd->u.scr.timertick = 0; npc_settimerevent_tick(nd,0); npc_timerevent_start(nd, st->rid); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(startnpctimer) +BUILDIN(startnpctimer) { struct npc_data *nd; int flag = 0; - + if( script_hasdata(st,3) ) { //Two arguments: NPC name and attach flag. nd = npc_name2id(script_getstr(st, 2)); @@ -9293,41 +8890,41 @@ BUILDIN_FUNC(startnpctimer) data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) //NPC name - nd = npc_name2id(conv_str(st, data)); + nd = npc_name2id(script->conv_str(st, data)); else if( data_isint(data) ) //Flag { nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); + flag = script->conv_num(st,data); } else { ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); - return 1; + return false; } } else nd=(struct npc_data *)map_id2bl(st->oid); - + if( !nd ) - return 0; + return true; if( flag ) //Attach { TBL_PC* sd = script_rid2sd(st); if( sd == NULL ) - return 0; + return true; nd->u.scr.rid = sd->bl.id; } - + npc_timerevent_start(nd, st->rid); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(stopnpctimer) +BUILDIN(stopnpctimer) { struct npc_data *nd; int flag = 0; - + if( script_hasdata(st,3) ) { //Two arguments: NPC name and attach flag. nd = npc_name2id(script_getstr(st, 2)); @@ -9339,152 +8936,152 @@ BUILDIN_FUNC(stopnpctimer) data = script_getdata(st,2); get_val(st,data); if( data_isstring(data) ) //NPC name - nd = npc_name2id(conv_str(st, data)); + nd = npc_name2id(script->conv_str(st, data)); else if( data_isint(data) ) //Flag { nd = (struct npc_data *)map_id2bl(st->oid); - flag = conv_num(st,data); + flag = script->conv_num(st,data); } else { ShowError("initnpctimer: invalid argument type #1 (needs be int or string)).\n"); - return 1; + return false; } } else nd=(struct npc_data *)map_id2bl(st->oid); - + if( !nd ) - return 0; + return true; if( flag ) //Detach nd->u.scr.rid = 0; - + npc_timerevent_stop(nd); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(getnpctimer) +BUILDIN(getnpctimer) { struct npc_data *nd; TBL_PC *sd; int type = script_getnum(st,2); int val = 0; - + if( script_hasdata(st,3) ) nd = npc_name2id(script_getstr(st,3)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( !nd || nd->bl.type != BL_NPC ) { script_pushint(st,0); ShowError("getnpctimer: Invalid NPC.\n"); - return 1; + return false; } - + switch( type ) { - case 0: val = npc_gettimerevent_tick(nd); break; - case 1: - if( nd->u.scr.rid ) - { - sd = map_id2sd(nd->u.scr.rid); - if( !sd ) + case 0: val = npc_gettimerevent_tick(nd); break; + case 1: + if( nd->u.scr.rid ) { - ShowError("buildin_getnpctimer: Attached player not found!\n"); - break; + sd = map_id2sd(nd->u.scr.rid); + if( !sd ) + { + ShowError("buildin_getnpctimer: Attached player not found!\n"); + break; + } + val = (sd->npc_timer_id != INVALID_TIMER); } - val = (sd->npc_timer_id != INVALID_TIMER); - } - else - val = (nd->u.scr.timerid != INVALID_TIMER); - break; - case 2: val = nd->u.scr.timeramount; break; + else + val = (nd->u.scr.timerid != INVALID_TIMER); + break; + case 2: val = nd->u.scr.timeramount; break; } - + script_pushint(st,val); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(setnpctimer) +BUILDIN(setnpctimer) { int tick; struct npc_data *nd; - + tick = script_getnum(st,2); if( script_hasdata(st,3) ) nd = npc_name2id(script_getstr(st,3)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( !nd || nd->bl.type != BL_NPC ) { script_pushint(st,1); ShowError("setnpctimer: Invalid NPC.\n"); - return 1; + return false; } - + npc_settimerevent_tick(nd,tick); script_pushint(st,0); - return 0; + return true; } /*========================================== * attaches the player rid to the timer [Celest] *------------------------------------------*/ -BUILDIN_FUNC(attachnpctimer) +BUILDIN(attachnpctimer) { TBL_PC *sd; struct npc_data *nd = (struct npc_data *)map_id2bl(st->oid); - + if( !nd || nd->bl.type != BL_NPC ) { script_pushint(st,1); ShowError("setnpctimer: Invalid NPC.\n"); - return 1; + return false; } - + if( script_hasdata(st,2) ) sd = map_nick2sd(script_getstr(st,2)); else sd = script_rid2sd(st); - + if( !sd ) { script_pushint(st,1); ShowWarning("attachnpctimer: Invalid player.\n"); - return 1; + return false; } - + nd->u.scr.rid = sd->bl.id; script_pushint(st,0); - return 0; + return true; } /*========================================== * detaches a player rid from the timer [Celest] *------------------------------------------*/ -BUILDIN_FUNC(detachnpctimer) +BUILDIN(detachnpctimer) { struct npc_data *nd; - + if( script_hasdata(st,2) ) nd = npc_name2id(script_getstr(st,2)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( !nd || nd->bl.type != BL_NPC ) { script_pushint(st,1); ShowError("detachnpctimer: Invalid NPC.\n"); - return 1; + return false; } - + nd->u.scr.rid = 0; script_pushint(st,0); - return 0; + return true; } /*========================================== @@ -9492,18 +9089,18 @@ BUILDIN_FUNC(detachnpctimer) * it checks if there is a player attached to the current script. [Skotlex] * If no, returns 0, if yes, returns the account_id of the attached player. *------------------------------------------*/ -BUILDIN_FUNC(playerattached) +BUILDIN(playerattached) { if(st->rid == 0 || map_id2sd(st->rid) == NULL) script_pushint(st,0); else script_pushint(st,st->rid); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(announce) +BUILDIN(announce) { const char *mes = script_getstr(st,2); int flag = script_getnum(st,3); @@ -9512,23 +9109,23 @@ BUILDIN_FUNC(announce) int fontSize = script_hasdata(st,6) ? script_getnum(st,6) : 12; // default fontSize int fontAlign = script_hasdata(st,7) ? script_getnum(st,7) : 0; // default fontAlign int fontY = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontY - + if (flag&0x0f) // Broadcast source or broadcast region defined { send_target target; struct block_list *bl = (flag&0x08) ? map_id2bl(st->oid) : (struct block_list *)script_rid2sd(st); // If bc_npc flag is set, use NPC as broadcast source if (bl == NULL) - return 0; - + return true; + flag &= 0x07; target = (flag == 1) ? ALL_SAMEMAP : - (flag == 2) ? AREA : - (flag == 3) ? SELF : - ALL_CLIENT; + (flag == 2) ? AREA : + (flag == 3) ? SELF : + ALL_CLIENT; if (fontColor) - clif_broadcast2(bl, mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target); + clif->broadcast2(bl, mes, (int)strlen(mes)+1, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, target); else - clif_broadcast(bl, mes, (int)strlen(mes)+1, flag&0xf0, target); + clif->broadcast(bl, mes, (int)strlen(mes)+1, flag&0xf0, target); } else { @@ -9537,7 +9134,7 @@ BUILDIN_FUNC(announce) else intif_broadcast(mes, (int)strlen(mes)+1, flag&0xf0); } - return 0; + return true; } /*========================================== *------------------------------------------*/ @@ -9552,13 +9149,51 @@ static int buildin_announce_sub(struct block_list *bl, va_list ap) short fontAlign = (short)va_arg(ap, int); short fontY = (short)va_arg(ap, int); if (fontColor) - clif_broadcast2(bl, mes, len, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, SELF); + clif->broadcast2(bl, mes, len, strtol(fontColor, (char **)NULL, 0), fontType, fontSize, fontAlign, fontY, SELF); else - clif_broadcast(bl, mes, len, type, SELF); + clif->broadcast(bl, mes, len, type, SELF); return 0; } +/* Runs item effect on attached character. + * itemeffect <item id>; + * itemeffect "<item name>"; */ +BUILDIN(itemeffect) { + TBL_NPC *nd; + TBL_PC *sd; + struct script_data *data; + struct item_data *item_data; + + nullpo_retr( 1, ( sd = script_rid2sd( st ) ) ); + nullpo_retr( 1, ( nd = (TBL_NPC *)map_id2bl( sd->npc_id ) ) ); + + data = script_getdata( st, 2 ); + get_val( st, data ); + + if( data_isstring( data ) ){ + const char *name = script->conv_str( st, data ); + + if( ( item_data = itemdb_searchname( name ) ) == NULL ){ + ShowError( "buildin_itemeffect: Nonexistant item %s requested.\n", name ); + return false; + } + } else if( data_isint( data ) ){ + int nameid = script->conv_num( st, data ); + + if( ( item_data = itemdb_exists( nameid ) ) == NULL ){ + ShowError("buildin_itemeffect: Nonexistant item %d requested.\n", nameid ); + return false; + } + } else { + ShowError("buildin_itemeffect: invalid data type for argument #1 (%d).", data->type ); + return false; + } + + run_script( item_data->script, 0, sd->bl.id, nd->bl.id ); + + return true; +} -BUILDIN_FUNC(mapannounce) +BUILDIN(mapannounce) { const char *mapname = script_getstr(st,2); const char *mes = script_getstr(st,3); @@ -9569,17 +9204,17 @@ BUILDIN_FUNC(mapannounce) int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY int16 m; - + if ((m = map_mapname2mapid(mapname)) < 0) - return 0; - + return true; + map_foreachinmap(buildin_announce_sub, m, BL_PC, - mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); - return 0; + mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(areaannounce) +BUILDIN(areaannounce) { const char *mapname = script_getstr(st,2); int x0 = script_getnum(st,3); @@ -9594,25 +9229,25 @@ BUILDIN_FUNC(areaannounce) int fontAlign = script_hasdata(st,12) ? script_getnum(st,12) : 0; // default fontAlign int fontY = script_hasdata(st,13) ? script_getnum(st,13) : 0; // default fontY int16 m; - + if ((m = map_mapname2mapid(mapname)) < 0) - return 0; - + return true; + map_foreachinarea(buildin_announce_sub, m, x0, y0, x1, y1, BL_PC, - mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); - return 0; + mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(getusers) +BUILDIN(getusers) { int flag, val = 0; struct map_session_data* sd; struct block_list* bl = NULL; - + flag = script_getnum(st,2); - + switch(flag&0x07) { case 0: @@ -9624,7 +9259,7 @@ BUILDIN_FUNC(getusers) {// pc bl = &sd->bl; } - + if(bl) { val = map[bl->m].users; @@ -9636,45 +9271,45 @@ BUILDIN_FUNC(getusers) default: ShowWarning("buildin_getusers: Unknown type %d.\n", flag); script_pushint(st,0); - return 1; + return false; } - + script_pushint(st,val); - return 0; + return true; } /*========================================== * Works like @WHO - displays all online users names in window *------------------------------------------*/ -BUILDIN_FUNC(getusersname) +BUILDIN(getusersname) { TBL_PC *sd, *pl_sd; int /*disp_num=1,*/ group_level = 0; struct s_mapiterator* iter; - + sd = script_rid2sd(st); - if (!sd) return 0; - + if (!sd) return true; + group_level = pc_get_group_level(sd); iter = mapit_getallusers(); - for( pl_sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); pl_sd = (TBL_PC*)mapit_next(iter) ) + for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) { if (pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) && pc_get_group_level(pl_sd) > group_level) continue; // skip hidden sessions - + /* Temporary fix for bugreport:1023. * Do not uncomment unless you want thousands of 'next' buttons. - if((disp_num++)%10==0) - clif_scriptnext(sd,st->oid);*/ - clif_scriptmes(sd,st->oid,pl_sd->status.name); + if((disp_num++)%10==0) + clif->scriptnext(sd,st->oid);*/ + clif->scriptmes(sd,st->oid,pl_sd->status.name); } - mapit_free(iter); - - return 0; + mapit->free(iter); + + return true; } /*========================================== * getmapguildusers("mapname",guild ID) Returns the number guild members present on a map [Reddozen] *------------------------------------------*/ -BUILDIN_FUNC(getmapguildusers) +BUILDIN(getmapguildusers) { const char *str; int16 m; @@ -9685,10 +9320,10 @@ BUILDIN_FUNC(getmapguildusers) gid=script_getnum(st,3); if ((m = map_mapname2mapid(str)) < 0) { // map id on this server (m == -1 if not in actual map-server) script_pushint(st,-1); - return 0; + return true; } - g = guild_search(gid); - + g = guild->search(gid); + if (g){ for(i = 0; i < g->max_member; i++) { @@ -9696,23 +9331,23 @@ BUILDIN_FUNC(getmapguildusers) c++; } } - + script_pushint(st,c); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(getmapusers) +BUILDIN(getmapusers) { const char *str; int16 m; str=script_getstr(st,2); if( (m=map_mapname2mapid(str))< 0){ script_pushint(st,-1); - return 0; + return true; } script_pushint(st,map[m].users); - return 0; + return true; } /*========================================== *------------------------------------------*/ @@ -9722,7 +9357,7 @@ static int buildin_getareausers_sub(struct block_list *bl,va_list ap) (*users)++; return 0; } -BUILDIN_FUNC(getareausers) +BUILDIN(getareausers) { const char *str; int16 m,x0,y0,x1,y1,users=0; //doubt we can have more then 32k users on @@ -9733,12 +9368,12 @@ BUILDIN_FUNC(getareausers) y1=script_getnum(st,6); if( (m=map_mapname2mapid(str))< 0){ script_pushint(st,-1); - return 0; + return true; } map_foreachinarea(buildin_getareausers_sub, - m,x0,y0,x1,y1,BL_PC,&users); + m,x0,y0,x1,y1,BL_PC,&users); script_pushint(st,users); - return 0; + return true; } /*========================================== @@ -9748,94 +9383,94 @@ static int buildin_getareadropitem_sub(struct block_list *bl,va_list ap) int item=va_arg(ap,int); int *amount=va_arg(ap,int *); struct flooritem_data *drop=(struct flooritem_data *)bl; - + if(drop->item_data.nameid==item) (*amount)+=drop->item_data.amount; - + return 0; } -BUILDIN_FUNC(getareadropitem) +BUILDIN(getareadropitem) { const char *str; int16 m,x0,y0,x1,y1; int item,amount=0; struct script_data *data; - + str=script_getstr(st,2); x0=script_getnum(st,3); y0=script_getnum(st,4); x1=script_getnum(st,5); y1=script_getnum(st,6); - + data=script_getdata(st,7); get_val(st,data); if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); item=UNKNOWN_ITEM_ID; if( item_data ) item=item_data->nameid; }else - item=conv_num(st,data); - + item=script->conv_num(st,data); + if( (m=map_mapname2mapid(str))< 0){ script_pushint(st,-1); - return 0; + return true; } map_foreachinarea(buildin_getareadropitem_sub, - m,x0,y0,x1,y1,BL_ITEM,item,&amount); + m,x0,y0,x1,y1,BL_ITEM,item,&amount); script_pushint(st,amount); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(enablenpc) +BUILDIN(enablenpc) { const char *str; str=script_getstr(st,2); npc_enable(str,1); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(disablenpc) +BUILDIN(disablenpc) { const char *str; str=script_getstr(st,2); npc_enable(str,0); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(hideoffnpc) +BUILDIN(hideoffnpc) { const char *str; str=script_getstr(st,2); npc_enable(str,2); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(hideonnpc) +BUILDIN(hideonnpc) { const char *str; str=script_getstr(st,2); npc_enable(str,4); - return 0; + return true; } /// Starts a status effect on the target unit or on the attached player. /// /// sc_start <effect_id>,<duration>,<val1>{,<unit_id>}; -BUILDIN_FUNC(sc_start) +BUILDIN(sc_start) { struct block_list* bl; enum sc_type type; int tick; int val1; int val4 = 0; - + type = (sc_type)script_getnum(st,2); tick = script_getnum(st,3); val1 = script_getnum(st,4); @@ -9843,29 +9478,29 @@ BUILDIN_FUNC(sc_start) bl = map_id2bl(script_getnum(st,5)); else bl = map_id2bl(st->rid); - + if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 ) {// When there isn't a duration specified, try to get it from the skill_db - tick = skill_get_time(status_sc2skill(type), val1); + tick = skill->get_time(status_sc2skill(type), val1); } - + if( potion_flag == 1 && potion_target ) { //skill.c set the flags before running the script, this must be a potion-pitched effect. bl = map_id2bl(potion_target); tick /= 2;// Thrown potions only last half. val4 = 1;// Mark that this was a thrown sc_effect } - + if( bl ) status_change_start(bl, type, 10000, val1, 0, 0, val4, tick, 2); - - return 0; + + return true; } /// Starts a status effect on the target unit or on the attached player. /// /// sc_start2 <effect_id>,<duration>,<val1>,<percent chance>{,<unit_id>}; -BUILDIN_FUNC(sc_start2) +BUILDIN(sc_start2) { struct block_list* bl; enum sc_type type; @@ -9873,7 +9508,7 @@ BUILDIN_FUNC(sc_start2) int val1; int val4 = 0; int rate; - + type = (sc_type)script_getnum(st,2); tick = script_getnum(st,3); val1 = script_getnum(st,4); @@ -9882,29 +9517,29 @@ BUILDIN_FUNC(sc_start2) bl = map_id2bl(script_getnum(st,6)); else bl = map_id2bl(st->rid); - + if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 ) {// When there isn't a duration specified, try to get it from the skill_db - tick = skill_get_time(status_sc2skill(type), val1); + tick = skill->get_time(status_sc2skill(type), val1); } - + if( potion_flag == 1 && potion_target ) { //skill.c set the flags before running the script, this must be a potion-pitched effect. bl = map_id2bl(potion_target); tick /= 2;// Thrown potions only last half. val4 = 1;// Mark that this was a thrown sc_effect } - + if( bl ) status_change_start(bl, type, rate, val1, 0, 0, val4, tick, 2); - - return 0; + + return true; } /// Starts a status effect on the target unit or on the attached player. /// /// sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<unit_id>}; -BUILDIN_FUNC(sc_start4) +BUILDIN(sc_start4) { struct block_list* bl; enum sc_type type; @@ -9913,7 +9548,7 @@ BUILDIN_FUNC(sc_start4) int val2; int val3; int val4; - + type = (sc_type)script_getnum(st,2); tick = script_getnum(st,3); val1 = script_getnum(st,4); @@ -9924,125 +9559,125 @@ BUILDIN_FUNC(sc_start4) bl = map_id2bl(script_getnum(st,8)); else bl = map_id2bl(st->rid); - + if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status_sc2skill(type) != 0 ) {// When there isn't a duration specified, try to get it from the skill_db - tick = skill_get_time(status_sc2skill(type), val1); + tick = skill->get_time(status_sc2skill(type), val1); } - + if( potion_flag == 1 && potion_target ) { //skill.c set the flags before running the script, this must be a potion-pitched effect. bl = map_id2bl(potion_target); tick /= 2;// Thrown potions only last half. } - + if( bl ) status_change_start(bl, type, 10000, val1, val2, val3, val4, tick, 2); - - return 0; + + return true; } /// Ends one or all status effects on the target unit or on the attached player. /// /// sc_end <effect_id>{,<unit_id>}; -BUILDIN_FUNC(sc_end) +BUILDIN(sc_end) { struct block_list* bl; int type; - + type = script_getnum(st, 2); if (script_hasdata(st, 3)) bl = map_id2bl(script_getnum(st, 3)); else bl = map_id2bl(st->rid); - + if (potion_flag == 1 && potion_target) //##TODO how does this work [FlavioJS] bl = map_id2bl(potion_target); - + if (!bl) - return 0; - + return true; + if (type >= 0 && type < SC_MAX) { struct status_change *sc = status_get_sc(bl); struct status_change_entry *sce = sc ? sc->data[type] : NULL; - + if (!sce) - return 0; - - + return true; + + switch (type) { case SC_WEIGHT50: case SC_WEIGHT90: case SC_NOCHAT: case SC_PUSH_CART: - return 0; - + return true; + default: break; } - + //This should help status_change_end force disabling the SC in case it has no limit. sce->val1 = sce->val2 = sce->val3 = sce->val4 = 0; status_change_end(bl, (sc_type)type, INVALID_TIMER); } else status_change_clear(bl, 3); // remove all effects - - return 0; + + return true; } /*========================================== * @FIXME atm will return reduced tick, 0 immune, 1 no tick *------------------------------------------*/ -BUILDIN_FUNC(getscrate) +BUILDIN(getscrate) { struct block_list *bl; int type,rate; - + type=script_getnum(st,2); rate=script_getnum(st,3); if( script_hasdata(st,4) ) //get for the bl assigned bl = map_id2bl(script_getnum(st,4)); else bl = map_id2bl(st->rid); - + if (bl) rate = status_get_sc_def(bl, (sc_type)type, 10000, 10000, 0); - + script_pushint(st,rate); - return 0; + return true; } /*========================================== * getstatus <type>{, <info>}; *------------------------------------------*/ -BUILDIN_FUNC(getstatus) +BUILDIN(getstatus) { int id, type; struct map_session_data* sd = script_rid2sd(st); - + if( sd == NULL ) {// no player attached - return 0; + return true; } - + id = script_getnum(st, 2); type = script_hasdata(st, 3) ? script_getnum(st, 3) : 0; - + if( id <= SC_NONE || id >= SC_MAX ) {// invalid status type given ShowWarning("script.c:getstatus: Invalid status type given (%d).\n", id); - return 0; + return true; } - + if( sd->sc.count == 0 || !sd->sc.data[id] ) {// no status is active script_pushint(st, 0); - return 0; + return true; } - + switch( type ) { case 1: script_pushint(st, sd->sc.data[id]->val1); break; @@ -10050,115 +9685,113 @@ BUILDIN_FUNC(getstatus) case 3: script_pushint(st, sd->sc.data[id]->val3); break; case 4: script_pushint(st, sd->sc.data[id]->val4); break; case 5: - { - struct TimerData* timer = (struct TimerData*)get_timer(sd->sc.data[id]->timer); - - if( timer ) - {// return the amount of time remaining - script_pushint(st, timer->tick - gettick()); - } + { + struct TimerData* timer = (struct TimerData*)get_timer(sd->sc.data[id]->timer); + + if( timer ) + {// return the amount of time remaining + script_pushint(st, timer->tick - gettick()); } + } break; default: script_pushint(st, 1); break; } - - return 0; + + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(debugmes) +BUILDIN(debugmes) { const char *str; str=script_getstr(st,2); ShowDebug("script debug : %d %d : %s\n",st->rid,st->oid,str); - return 0; + return true; } /*========================================== *------------------------------------------*/ -BUILDIN_FUNC(catchpet) +BUILDIN(catchpet) { int pet_id; TBL_PC *sd; - + pet_id= script_getnum(st,2); sd=script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pet_catch_process1(sd,pet_id); - return 0; + return true; } /*========================================== * [orn] *------------------------------------------*/ -BUILDIN_FUNC(homunculus_evolution) +BUILDIN(homunculus_evolution) { TBL_PC *sd; - + sd=script_rid2sd(st); if( sd == NULL ) - return 0; - - if(merc_is_hom_active(sd->hd)) - { + return true; + + if(homun_alive(sd->hd)) { if (sd->hd->homunculus.intimacy > 91000) - merc_hom_evolution(sd->hd); + homun->evolve(sd->hd); else - clif_emotion(&sd->hd->bl, E_SWT); + clif->emotion(&sd->hd->bl, E_SWT); } - return 0; + return true; } /*========================================== * [Xantara] *------------------------------------------*/ -BUILDIN_FUNC(homunculus_mutate) -{ - int homun_id, m_class, m_id; +BUILDIN(homunculus_mutate) { + int homun_id; + enum homun_type m_class, m_id; TBL_PC *sd; - + sd = script_rid2sd(st); - if( sd == NULL ) - return 0; - + if( sd == NULL || sd->hd == NULL ) + return true; + if(script_hasdata(st,2)) homun_id = script_getnum(st,2); else homun_id = 6048 + (rnd() % 4); - - if(merc_is_hom_active(sd->hd)) { - m_class = hom_class2mapid(sd->hd->homunculus.class_); - m_id = hom_class2mapid(homun_id); - - if ( m_class != -1 && m_id != -1 && m_class&HOM_EVO && m_id&HOM_S && sd->hd->homunculus.level >= 99 ) - hom_mutate(sd->hd, homun_id); + + if(homun_alive(sd->hd)) { + m_class = homun->class2type(sd->hd->homunculus.class_); + m_id = homun->class2type(homun_id); + + if ( m_class != -1 && m_id != -1 && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 ) + homun->mutate(sd->hd, homun_id); else - clif_emotion(&sd->hd->bl, E_SWT); + clif->emotion(&sd->hd->bl, E_SWT); } - return 0; + return true; } // [Zephyrus] -BUILDIN_FUNC(homunculus_shuffle) -{ +BUILDIN(homunculus_shuffle) { TBL_PC *sd; - + sd=script_rid2sd(st); if( sd == NULL ) - return 0; - - if(merc_is_hom_active(sd->hd)) - merc_hom_shuffle(sd->hd); - - return 0; + return true; + + if(homun_alive(sd->hd)) + homun->shuffle(sd->hd); + + return true; } //These two functions bring the eA MAPID_* class functionality to scripts. -BUILDIN_FUNC(eaclass) +BUILDIN(eaclass) { int class_; if( script_hasdata(st,2) ) @@ -10168,15 +9801,15 @@ BUILDIN_FUNC(eaclass) sd=script_rid2sd(st); if (!sd) { script_pushint(st,-1); - return 0; + return true; } class_ = sd->status.class_; } script_pushint(st,pc_jobid2mapid(class_)); - return 0; + return true; } -BUILDIN_FUNC(roclass) +BUILDIN(roclass) { int class_ =script_getnum(st,2); int sex; @@ -10190,26 +9823,26 @@ BUILDIN_FUNC(roclass) sex = 1; //Just use male when not found. } script_pushint(st,pc_mapid2jobid(class_, sex)); - return 0; + return true; } /*========================================== * Tells client to open a hatching window, used for pet incubator *------------------------------------------*/ -BUILDIN_FUNC(birthpet) +BUILDIN(birthpet) { TBL_PC *sd; sd=script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + if( sd->status.pet_id ) {// do not send egg list, when you already have a pet - return 0; + return true; } - - clif_sendegg(sd); - return 0; + + clif->sendegg(sd); + return true; } /*========================================== @@ -10220,128 +9853,128 @@ BUILDIN_FUNC(birthpet) * 3 : don't reset skill, blvl=1 * 4 : jlvl=0 *------------------------------------------*/ -BUILDIN_FUNC(resetlvl) +BUILDIN(resetlvl) { TBL_PC *sd; - + int type=script_getnum(st,2); - + sd=script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + pc_resetlvl(sd,type); - return 0; + return true; } /*========================================== * Reset a player status point *------------------------------------------*/ -BUILDIN_FUNC(resetstatus) +BUILDIN(resetstatus) { TBL_PC *sd; sd=script_rid2sd(st); pc_resetstate(sd); - return 0; + return true; } /*========================================== * script command resetskill *------------------------------------------*/ -BUILDIN_FUNC(resetskill) +BUILDIN(resetskill) { TBL_PC *sd; sd=script_rid2sd(st); pc_resetskill(sd,1); - return 0; + return true; } /*========================================== * Counts total amount of skill points. *------------------------------------------*/ -BUILDIN_FUNC(skillpointcount) +BUILDIN(skillpointcount) { TBL_PC *sd; sd=script_rid2sd(st); script_pushint(st,sd->status.skill_point + pc_resetskill(sd,2)); - return 0; + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(changebase) +BUILDIN(changebase) { TBL_PC *sd=NULL; int vclass; - + if( script_hasdata(st,3) ) sd=map_id2sd(script_getnum(st,3)); else - sd=script_rid2sd(st); - + sd=script_rid2sd(st); + if(sd == NULL) - return 0; - + return true; + vclass = script_getnum(st,2); if(vclass == JOB_WEDDING) { if (!battle_config.wedding_modifydisplay || //Do not show the wedding sprites sd->class_&JOBL_BABY //Baby classes screw up when showing wedding sprites. [Skotlex] They don't seem to anymore. ) - return 0; + return true; } - - if(!sd->disguise && vclass != sd->vd.class_) { + + if(sd->disguise == -1 && vclass != sd->vd.class_) { status_set_viewdata(&sd->bl, vclass); //Updated client view. Base, Weapon and Cloth Colors. - clif_changelook(&sd->bl,LOOK_BASE,sd->vd.class_); - clif_changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); + clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_); + clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon); if (sd->vd.cloth_color) - clif_changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); - clif_skillinfoblock(sd); + clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color); + clif->skillinfoblock(sd); } - - return 0; + + return true; } /*========================================== * Unequip all item and request for a changesex to char-serv *------------------------------------------*/ -BUILDIN_FUNC(changesex) +BUILDIN(changesex) { int i; TBL_PC *sd = NULL; sd = script_rid2sd(st); - + pc_resetskill(sd,4); // to avoid any problem with equipment and invalid sex, equipment is unequiped. for( i=0; i<EQI_MAX; i++ ) if( sd->equip_index[i] >= 0 ) pc_unequipitem(sd, sd->equip_index[i], 3); chrif_changesex(sd); - return 0; + return true; } /*========================================== * Works like 'announce' but outputs in the common chat window *------------------------------------------*/ -BUILDIN_FUNC(globalmes) +BUILDIN(globalmes) { struct block_list *bl = map_id2bl(st->oid); struct npc_data *nd = (struct npc_data *)bl; const char *name=NULL,*mes; - + mes=script_getstr(st,2); - if(mes==NULL) return 0; - + if(mes==NULL) return true; + if(script_hasdata(st,3)){ // npc name to display name=script_getstr(st,3); } else { name=nd->name; //use current npc name } - + npc_globalmessage(name,mes); // broadcast to all players connected - - return 0; + + return true; } ///////////////////////////////////////////////////////////////////// @@ -10351,7 +9984,7 @@ BUILDIN_FUNC(globalmes) /// Creates a waiting room (chat room) for this npc. /// /// waitingroom "<title>",<limit>{,"<event>"{,<trigger>{,<zeny>{,<minlvl>{,<maxlvl>}}}}}; -BUILDIN_FUNC(waitingroom) +BUILDIN(waitingroom) { struct npc_data* nd; int pub = 1; @@ -10362,19 +9995,19 @@ BUILDIN_FUNC(waitingroom) int zeny = script_hasdata(st,6) ? script_getnum(st,6) : 0; int minLvl = script_hasdata(st,7) ? script_getnum(st,7) : 1; int maxLvl = script_hasdata(st,8) ? script_getnum(st,8) : MAX_LEVEL; - + nd = (struct npc_data *)map_id2bl(st->oid); if( nd != NULL ) chat_createnpcchat(nd, title, limit, pub, trigger, ev, zeny, minLvl, maxLvl); - - return 0; + + return true; } /// Removes the waiting room of the current or target npc. /// /// delwaitingroom "<npc_name>"; /// delwaitingroom; -BUILDIN_FUNC(delwaitingroom) +BUILDIN(delwaitingroom) { struct npc_data* nd; if( script_hasdata(st,2) ) @@ -10383,64 +10016,64 @@ BUILDIN_FUNC(delwaitingroom) nd = (struct npc_data *)map_id2bl(st->oid); if( nd != NULL ) chat_deletenpcchat(nd); - return 0; + return true; } /// Kicks all the players from the waiting room of the current or target npc. /// /// kickwaitingroomall "<npc_name>"; /// kickwaitingroomall; -BUILDIN_FUNC(waitingroomkickall) +BUILDIN(waitingroomkickall) { struct npc_data* nd; struct chat_data* cd; - + if( script_hasdata(st,2) ) nd = npc_name2id(script_getstr(st,2)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL ) chat_npckickall(cd); - return 0; + return true; } /// Enables the waiting room event of the current or target npc. /// /// enablewaitingroomevent "<npc_name>"; /// enablewaitingroomevent; -BUILDIN_FUNC(enablewaitingroomevent) +BUILDIN(enablewaitingroomevent) { struct npc_data* nd; struct chat_data* cd; - + if( script_hasdata(st,2) ) nd = npc_name2id(script_getstr(st, 2)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL ) chat_enableevent(cd); - return 0; + return true; } /// Disables the waiting room event of the current or target npc. /// /// disablewaitingroomevent "<npc_name>"; /// disablewaitingroomevent; -BUILDIN_FUNC(disablewaitingroomevent) +BUILDIN(disablewaitingroomevent) { struct npc_data *nd; struct chat_data *cd; - + if( script_hasdata(st,2) ) nd = npc_name2id(script_getstr(st, 2)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( nd != NULL && (cd=(struct chat_data *)map_id2bl(nd->chat_id)) != NULL ) chat_disableevent(cd); - return 0; + return true; } /// Returns info on the waiting room of the current or target npc. @@ -10457,38 +10090,38 @@ BUILDIN_FUNC(disablewaitingroomevent) /// /// getwaitingroomstate(<type>,"<npc_name>") -> <info> /// getwaitingroomstate(<type>) -> <info> -BUILDIN_FUNC(getwaitingroomstate) +BUILDIN(getwaitingroomstate) { struct npc_data *nd; struct chat_data *cd; int type; - + type = script_getnum(st,2); if( script_hasdata(st,3) ) nd = npc_name2id(script_getstr(st, 3)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( nd == NULL || (cd=(struct chat_data *)map_id2bl(nd->chat_id)) == NULL ) { script_pushint(st, -1); - return 0; + return true; } - + switch(type) { - case 0: script_pushint(st, cd->users); break; - case 1: script_pushint(st, cd->limit); break; - case 2: script_pushint(st, cd->trigger&0x7f); break; - case 3: script_pushint(st, ((cd->trigger&0x80)!=0)); break; - case 4: script_pushstrcopy(st, cd->title); break; - case 5: script_pushstrcopy(st, cd->pass); break; - case 16: script_pushstrcopy(st, cd->npc_event);break; - case 32: script_pushint(st, (cd->users >= cd->limit)); break; - case 33: script_pushint(st, (cd->users >= cd->trigger)); break; - default: script_pushint(st, -1); break; + case 0: script_pushint(st, cd->users); break; + case 1: script_pushint(st, cd->limit); break; + case 2: script_pushint(st, cd->trigger&0x7f); break; + case 3: script_pushint(st, ((cd->trigger&0x80)!=0)); break; + case 4: script_pushstrcopy(st, cd->title); break; + case 5: script_pushstrcopy(st, cd->pass); break; + case 16: script_pushstrcopy(st, cd->npc_event);break; + case 32: script_pushint(st, (cd->users >= cd->limit)); break; + case 33: script_pushint(st, (cd->users >= cd->trigger)); break; + default: script_pushint(st, -1); break; } - return 0; + return true; } /// Warps the trigger or target amount of players to the target map and position. @@ -10503,7 +10136,7 @@ BUILDIN_FUNC(getwaitingroomstate) /// /// warpwaitingpc "<map name>",<x>,<y>,<number of players>; /// warpwaitingpc "<map name>",<x>,<y>; -BUILDIN_FUNC(warpwaitingpc) +BUILDIN(warpwaitingpc) { int x; int y; @@ -10513,28 +10146,28 @@ BUILDIN_FUNC(warpwaitingpc) struct npc_data* nd; struct chat_data* cd; TBL_PC* sd; - + nd = (struct npc_data *)map_id2bl(st->oid); if( nd == NULL || (cd=(struct chat_data *)map_id2bl(nd->chat_id)) == NULL ) - return 0; - + return true; + map_name = script_getstr(st,2); x = script_getnum(st,3); y = script_getnum(st,4); n = cd->trigger&0x7f; - + if( script_hasdata(st,5) ) n = script_getnum(st,5); - + for( i = 0; i < n && cd->users > 0; i++ ) { sd = cd->usersd[0]; - + if( strcmp(map_name,"SavePoint") == 0 && map[sd->bl.m].flag.noteleport ) {// can't teleport on this map break; } - + if( cd->zeny ) {// fee set if( (uint32)sd->status.zeny < cd->zeny ) @@ -10543,9 +10176,9 @@ BUILDIN_FUNC(warpwaitingpc) } pc_payzeny(sd, cd->zeny, LOG_TYPE_NPC, NULL); } - + mapreg_setreg(reference_uid(add_str("$@warpwaitingpc"), i), sd->bl.id); - + if( strcmp(map_name,"Random") == 0 ) pc_randomwarp(sd,CLR_TELEPORT); else if( strcmp(map_name,"SavePoint") == 0 ) @@ -10554,7 +10187,7 @@ BUILDIN_FUNC(warpwaitingpc) pc_setpos(sd, mapindex_name2id(map_name), x, y, CLR_OUTSIGHT); } mapreg_setreg(add_str("$@warpwaitingpcnum"), i); - return 0; + return true; } ///////////////////////////////////////////////////////////////////// @@ -10576,77 +10209,76 @@ static void script_detach_rid(struct script_state* st) /*========================================== * Attach sd char id to script and detach current one if any *------------------------------------------*/ -BUILDIN_FUNC(attachrid) +BUILDIN(attachrid) { int rid = script_getnum(st,2); - struct map_session_data* sd; - - if ((sd = map_id2sd(rid))!=NULL) { + + if (map_id2sd(rid) != NULL) { script_detach_rid(st); - + st->rid = rid; script_attach_state(st); script_pushint(st,1); } else script_pushint(st,0); - return 0; + return true; } /*========================================== * Detach script to rid *------------------------------------------*/ -BUILDIN_FUNC(detachrid) +BUILDIN(detachrid) { script_detach_rid(st); - return 0; + return true; } /*========================================== * Chk if account connected, (and charid from account if specified) *------------------------------------------*/ -BUILDIN_FUNC(isloggedin) +BUILDIN(isloggedin) { TBL_PC* sd = map_id2sd(script_getnum(st,2)); if (script_hasdata(st,3) && sd && sd->status.char_id != script_getnum(st,3)) sd = NULL; push_val(st->stack,C_INT,sd!=NULL); - return 0; + return true; } /*========================================== * *------------------------------------------*/ -BUILDIN_FUNC(setmapflagnosave) +BUILDIN(setmapflagnosave) { int16 m,x,y; unsigned short mapindex; const char *str,*str2; - + str=script_getstr(st,2); str2=script_getstr(st,3); x=script_getnum(st,4); y=script_getnum(st,5); m = map_mapname2mapid(str); mapindex = mapindex_name2id(str2); - + if(m >= 0 && mapindex) { map[m].flag.nosave=1; map[m].save.map=mapindex; map[m].save.x=x; map[m].save.y=y; } - - return 0; + + return true; } -BUILDIN_FUNC(getmapflag) +BUILDIN(getmapflag) { int16 m,i; const char *str; - + str=script_getstr(st,2); i=script_getnum(st,3); - + m = map_mapname2mapid(str); if(m >= 0) { switch(i) { @@ -10670,11 +10302,6 @@ BUILDIN_FUNC(getmapflag) case MF_FOG: script_pushint(st,map[m].flag.fog); break; case MF_SAKURA: script_pushint(st,map[m].flag.sakura); break; case MF_LEAVES: script_pushint(st,map[m].flag.leaves); break; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //case MF_RAIN: script_pushint(st,map[m].flag.rain); break; - case MF_NOGO: script_pushint(st,map[m].flag.nogo); break; case MF_CLOUDS: script_pushint(st,map[m].flag.clouds); break; case MF_CLOUDS2: script_pushint(st,map[m].flag.clouds2); break; case MF_FIREWORKS: script_pushint(st,map[m].flag.fireworks); break; @@ -10688,7 +10315,6 @@ BUILDIN_FUNC(getmapflag) case MF_NORETURN: script_pushint(st,map[m].flag.noreturn); break; case MF_NOWARPTO: script_pushint(st,map[m].flag.nowarpto); break; case MF_NIGHTMAREDROP: script_pushint(st,map[m].flag.pvp_nightmaredrop); break; - case MF_RESTRICTED: script_pushint(st,map[m].flag.restricted); break; case MF_NOCOMMAND: script_pushint(st,map[m].nocommand); break; case MF_NODROP: script_pushint(st,map[m].flag.nodrop); break; case MF_JEXP: script_pushint(st,map[m].jexp); break; @@ -10707,8 +10333,8 @@ BUILDIN_FUNC(getmapflag) case MF_RESET: script_pushint(st,map[m].flag.reset); break; } } - - return 0; + + return true; } /* pvp timer handling */ static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) { @@ -10721,21 +10347,34 @@ static int script_mapflag_pvp_sub(struct block_list *bl,va_list ap) { sd->pvp_won = 0; sd->pvp_lost = 0; } - clif_map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->map_property(sd, MAPPROPERTY_FREEPVPZONE); + clif->maptypeproperty2(&sd->bl,SELF); return 0; } -BUILDIN_FUNC(setmapflag) +BUILDIN(setmapflag) { int16 m,i; - const char *str; + const char *str, *val2 = NULL; + struct script_data* data; int val=0; - + str=script_getstr(st,2); - i=script_getnum(st,3); + + i = script_getnum(st, 3); + if(script_hasdata(st,4)){ - val=script_getnum(st,4); + data = script_getdata(st,4); + get_val(st, data); + + + if( data_isstring(data) ) + val2 = script_getstr(st, 4); + else + val = script_getnum(st, 4); + } m = map_mapname2mapid(str); + if(m >= 0) { switch(i) { case MF_NOMEMO: map[m].flag.nomemo = 1; break; @@ -10752,9 +10391,14 @@ BUILDIN_FUNC(setmapflag) break; case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 1; break; case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 1; break; - case MF_GVG: + case MF_GVG: { + struct block_list bl; map[m].flag.gvg = 1; - clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); + clif->map_property_mapall(m, MAPPROPERTY_AGITZONE); + bl.type = BL_NUL; + bl.m = m; + clif->maptypeproperty2(&bl,ALL_SAMEMAP); + } break; case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 1; break; case MF_NOTRADE: map[m].flag.notrade = 1; break; @@ -10766,11 +10410,6 @@ BUILDIN_FUNC(setmapflag) case MF_FOG: map[m].flag.fog = 1; break; case MF_SAKURA: map[m].flag.sakura = 1; break; case MF_LEAVES: map[m].flag.leaves = 1; break; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //case MF_RAIN: map[m].flag.rain = 1; break; - case MF_NOGO: map[m].flag.nogo = 1; break; case MF_CLOUDS: map[m].flag.clouds = 1; break; case MF_CLOUDS2: map[m].flag.clouds2 = 1; break; case MF_FIREWORKS: map[m].flag.fireworks = 1; break; @@ -10784,9 +10423,13 @@ BUILDIN_FUNC(setmapflag) case MF_NORETURN: map[m].flag.noreturn = 1; break; case MF_NOWARPTO: map[m].flag.nowarpto = 1; break; case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 1; break; - case MF_RESTRICTED: - map[m].zone |= 1<<(val+1); - map[m].flag.restricted=1; + case MF_ZONE: { + char zone[6] = "zone\0"; + char empty[1] = "\0"; + char params[MAP_ZONE_MAPFLAG_LENGTH]; + memcpy(params, val2, MAP_ZONE_MAPFLAG_LENGTH); + npc_parse_mapflag(map[m].name, empty, zone, params, empty, empty, empty); + } break; case MF_NOCOMMAND: map[m].nocommand = (val <= 0) ? 100 : val; break; case MF_NODROP: map[m].flag.nodrop = 1; break; @@ -10806,16 +10449,16 @@ BUILDIN_FUNC(setmapflag) case MF_RESET: map[m].flag.reset = 1; break; } } - - return 0; + + return true; } -BUILDIN_FUNC(removemapflag) +BUILDIN(removemapflag) { int16 m,i; const char *str; int val=0; - + str=script_getstr(st,2); i=script_getnum(st,3); if(script_hasdata(st,4)){ @@ -10830,15 +10473,25 @@ BUILDIN_FUNC(removemapflag) case MF_NOBRANCH: map[m].flag.nobranch = 0; break; case MF_NOPENALTY: map[m].flag.noexppenalty = 0; map[m].flag.nozenypenalty = 0; break; case MF_NOZENYPENALTY: map[m].flag.nozenypenalty = 0; break; - case MF_PVP: + case MF_PVP: { + struct block_list bl; + bl.type = BL_NUL; + bl.m = m; map[m].flag.pvp = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); + clif->map_property_mapall(m, MAPPROPERTY_NOTHING); + clif->maptypeproperty2(&bl,ALL_SAMEMAP); + } break; case MF_PVP_NOPARTY: map[m].flag.pvp_noparty = 0; break; case MF_PVP_NOGUILD: map[m].flag.pvp_noguild = 0; break; - case MF_GVG: + case MF_GVG: { + struct block_list bl; + bl.type = BL_NUL; + bl.m = m; map[m].flag.gvg = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); + clif->map_property_mapall(m, MAPPROPERTY_NOTHING); + clif->maptypeproperty2(&bl,ALL_SAMEMAP); + } break; case MF_GVG_NOPARTY: map[m].flag.gvg_noparty = 0; break; case MF_NOTRADE: map[m].flag.notrade = 0; break; @@ -10850,11 +10503,6 @@ BUILDIN_FUNC(removemapflag) case MF_FOG: map[m].flag.fog = 0; break; case MF_SAKURA: map[m].flag.sakura = 0; break; case MF_LEAVES: map[m].flag.leaves = 0; break; - /** - * No longer available, keeping here just in case it's back someday. [Ind] - **/ - //case MF_RAIN: map[m].flag.rain = 0; break; - case MF_NOGO: map[m].flag.nogo = 0; break; case MF_CLOUDS: map[m].flag.clouds = 0; break; case MF_CLOUDS2: map[m].flag.clouds2 = 0; break; case MF_FIREWORKS: map[m].flag.fireworks = 0; break; @@ -10868,11 +10516,8 @@ BUILDIN_FUNC(removemapflag) case MF_NORETURN: map[m].flag.noreturn = 0; break; case MF_NOWARPTO: map[m].flag.nowarpto = 0; break; case MF_NIGHTMAREDROP: map[m].flag.pvp_nightmaredrop = 0; break; - case MF_RESTRICTED: - map[m].zone ^= 1<<(val+1); - if (map[m].zone == 0){ - map[m].flag.restricted=0; - } + case MF_ZONE: + map_zone_change2(m, map[m].prev_zone); break; case MF_NOCOMMAND: map[m].nocommand = 0; break; case MF_NODROP: map[m].flag.nodrop = 0; break; @@ -10892,34 +10537,40 @@ BUILDIN_FUNC(removemapflag) case MF_RESET: map[m].flag.reset = 0; break; } } - - return 0; + + return true; } -BUILDIN_FUNC(pvpon) +BUILDIN(pvpon) { int16 m; const char *str; TBL_PC* sd = NULL; struct s_mapiterator* iter; - + struct block_list bl; + str = script_getstr(st,2); m = map_mapname2mapid(str); if( m < 0 || map[m].flag.pvp ) - return 0; // nothing to do - + return true; // nothing to do + + map_zone_change2(m, strdb_get(zone_db, MAP_ZONE_PVP_NAME)); map[m].flag.pvp = 1; - clif_map_property_mapall(m, MAPPROPERTY_FREEPVPZONE); - + clif->map_property_mapall(m, MAPPROPERTY_FREEPVPZONE); + bl.type = BL_NUL; + bl.m = m; + clif->maptypeproperty2(&bl,ALL_SAMEMAP); + + if(battle_config.pk_mode) // disable ranking functions if pk_mode is on [Valaris] - return 0; - + return true; + iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if( sd->bl.m != m || sd->pvp_timer != INVALID_TIMER ) continue; // not applicable - + sd->pvp_timer = add_timer(gettick()+200,pc_calc_pvprank_timer,sd->bl.id,0); sd->pvp_rank = 0; sd->pvp_lastusers = 0; @@ -10927,15 +10578,15 @@ BUILDIN_FUNC(pvpon) sd->pvp_won = 0; sd->pvp_lost = 0; } - mapit_free(iter); - - return 0; + mapit->free(iter); + + return true; } static int buildin_pvpoff_sub(struct block_list *bl,va_list ap) { TBL_PC* sd = (TBL_PC*)bl; - clif_pvpset(sd, 0, 0, 2); + clif->pvpset(sd, 0, 0, 2); if (sd->pvp_timer != INVALID_TIMER) { delete_timer(sd->pvp_timer, pc_calc_pvprank_timer); sd->pvp_timer = INVALID_TIMER; @@ -10943,71 +10594,86 @@ static int buildin_pvpoff_sub(struct block_list *bl,va_list ap) return 0; } -BUILDIN_FUNC(pvpoff) +BUILDIN(pvpoff) { int16 m; const char *str; - + struct block_list bl; + str=script_getstr(st,2); m = map_mapname2mapid(str); if(m < 0 || !map[m].flag.pvp) - return 0; //fixed Lupus - + return true; //fixed Lupus + + map_zone_change2(m, map[m].prev_zone); map[m].flag.pvp = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); - + clif->map_property_mapall(m, MAPPROPERTY_NOTHING); + bl.type = BL_NUL; + bl.m = m; + clif->maptypeproperty2(&bl,ALL_SAMEMAP); + if(battle_config.pk_mode) // disable ranking options if pk_mode is on [Valaris] - return 0; - + return true; + map_foreachinmap(buildin_pvpoff_sub, m, BL_PC); - return 0; + return true; } -BUILDIN_FUNC(gvgon) +BUILDIN(gvgon) { int16 m; const char *str; - + str=script_getstr(st,2); m = map_mapname2mapid(str); if(m >= 0 && !map[m].flag.gvg) { + struct block_list bl; + map_zone_change2(m, strdb_get(zone_db, MAP_ZONE_GVG_NAME)); map[m].flag.gvg = 1; - clif_map_property_mapall(m, MAPPROPERTY_AGITZONE); + clif->map_property_mapall(m, MAPPROPERTY_AGITZONE); + bl.type = BL_NUL; + bl.m = m; + clif->maptypeproperty2(&bl,ALL_SAMEMAP); } - - return 0; + + return true; } -BUILDIN_FUNC(gvgoff) +BUILDIN(gvgoff) { int16 m; const char *str; - + str=script_getstr(st,2); m = map_mapname2mapid(str); if(m >= 0 && map[m].flag.gvg) { + struct block_list bl; + map_zone_change2(m, map[m].prev_zone); map[m].flag.gvg = 0; - clif_map_property_mapall(m, MAPPROPERTY_NOTHING); + clif->map_property_mapall(m, MAPPROPERTY_NOTHING); + bl.type = BL_NUL; + bl.m = m; + clif->maptypeproperty2(&bl,ALL_SAMEMAP); } - - return 0; + + return true; } /*========================================== * Shows an emoticon on top of the player/npc * emotion emotion#, <target: 0 - NPC, 1 - PC>, <NPC/PC name> *------------------------------------------*/ //Optional second parameter added by [Skotlex] -BUILDIN_FUNC(emotion) +BUILDIN(emotion) { int type; int player=0; - + type=script_getnum(st,2); if(type < 0 || type > 100) - return 0; - + return true; + if( script_hasdata(st,3) ) player=script_getnum(st,3); - + if (player) { TBL_PC *sd = NULL; if( script_hasdata(st,4) ) @@ -11015,17 +10681,17 @@ BUILDIN_FUNC(emotion) else sd = script_rid2sd(st); if (sd) - clif_emotion(&sd->bl,type); + clif->emotion(&sd->bl,type); } else if( script_hasdata(st,4) ) { TBL_NPC *nd = npc_name2id(script_getstr(st,4)); if(nd) - clif_emotion(&nd->bl,type); + clif->emotion(&nd->bl,type); } else - clif_emotion(map_id2bl(st->oid),type); - return 0; + clif->emotion(map_id2bl(st->oid),type); + return true; } static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list ap) @@ -11033,14 +10699,14 @@ static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list int16 m=va_arg(ap,int); int g_id=va_arg(ap,int); int flag=va_arg(ap,int); - + if(!sd || sd->bl.m != m) return 0; if( - (sd->status.guild_id == g_id && flag&1) || //Warp out owners - (sd->status.guild_id != g_id && flag&2) || //Warp out outsiders - (sd->status.guild_id == 0) // Warp out players not in guild [Valaris] - ) + (sd->status.guild_id == g_id && flag&1) || //Warp out owners + (sd->status.guild_id != g_id && flag&2) || //Warp out outsiders + (sd->status.guild_id == 0) // Warp out players not in guild [Valaris] + ) pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); return 1; } @@ -11048,91 +10714,91 @@ static int buildin_maprespawnguildid_sub_pc(struct map_session_data* sd, va_list static int buildin_maprespawnguildid_sub_mob(struct block_list *bl,va_list ap) { struct mob_data *md=(struct mob_data *)bl; - + if(!md->guardian_data && md->class_ != MOBID_EMPERIUM) status_kill(bl); - + return 0; } -BUILDIN_FUNC(maprespawnguildid) +BUILDIN(maprespawnguildid) { const char *mapname=script_getstr(st,2); int g_id=script_getnum(st,3); int flag=script_getnum(st,4); - + int16 m=map_mapname2mapid(mapname); - + if(m == -1) - return 0; - + return true; + //Catch ALL players (in case some are 'between maps' on execution time) map_foreachpc(buildin_maprespawnguildid_sub_pc,m,g_id,flag); if (flag&4) //Remove script mobs. map_foreachinmap(buildin_maprespawnguildid_sub_mob,m,BL_MOB); - return 0; + return true; } -BUILDIN_FUNC(agitstart) +BUILDIN(agitstart) { - if(agit_flag==1) return 0; // Agit already Start. + if(agit_flag==1) return true; // Agit already Start. agit_flag=1; - guild_agit_start(); - return 0; + guild->agit_start(); + return true; } -BUILDIN_FUNC(agitend) +BUILDIN(agitend) { - if(agit_flag==0) return 0; // Agit already End. + if(agit_flag==0) return true; // Agit already End. agit_flag=0; - guild_agit_end(); - return 0; + guild->agit_end(); + return true; } -BUILDIN_FUNC(agitstart2) +BUILDIN(agitstart2) { - if(agit2_flag==1) return 0; // Agit2 already Start. + if(agit2_flag==1) return true; // Agit2 already Start. agit2_flag=1; - guild_agit2_start(); - return 0; + guild->agit2_start(); + return true; } -BUILDIN_FUNC(agitend2) +BUILDIN(agitend2) { - if(agit2_flag==0) return 0; // Agit2 already End. + if(agit2_flag==0) return true; // Agit2 already End. agit2_flag=0; - guild_agit2_end(); - return 0; + guild->agit2_end(); + return true; } /*========================================== * Returns whether woe is on or off. // choice script *------------------------------------------*/ -BUILDIN_FUNC(agitcheck) +BUILDIN(agitcheck) { script_pushint(st,agit_flag); - return 0; + return true; } /*========================================== * Returns whether woese is on or off. // choice script *------------------------------------------*/ -BUILDIN_FUNC(agitcheck2) +BUILDIN(agitcheck2) { script_pushint(st,agit2_flag); - return 0; + return true; } /// Sets the guild_id of this npc. /// /// flagemblem <guild_id>; -BUILDIN_FUNC(flagemblem) +BUILDIN(flagemblem) { TBL_NPC* nd; int g_id = script_getnum(st,2); - - if(g_id < 0) return 0; - + + if(g_id < 0) return true; + nd = (TBL_NPC*)map_id2nd(st->oid); if( nd == NULL ) { ShowError("script:flagemblem: npc %d not found\n", st->oid); @@ -11141,37 +10807,37 @@ BUILDIN_FUNC(flagemblem) } else { bool changed = ( nd->u.scr.guild_id != g_id )?true:false; nd->u.scr.guild_id = g_id; - clif_guild_emblem_area(&nd->bl); + clif->guild_emblem_area(&nd->bl); /* guild flag caching */ if( g_id ) /* adding a id */ - guild_flag_add(nd); + guild->flag_add(nd); else if( changed ) /* removing a flag */ - guild_flag_remove(nd); + guild->flag_remove(nd); } - return 0; + return true; } -BUILDIN_FUNC(getcastlename) +BUILDIN(getcastlename) { const char* mapname = mapindex_getmapname(script_getstr(st,2),NULL); - struct guild_castle* gc = guild_mapname2gc(mapname); + struct guild_castle* gc = guild->mapname2gc(mapname); const char* name = (gc) ? gc->castle_name : ""; script_pushstrcopy(st,name); - return 0; + return true; } -BUILDIN_FUNC(getcastledata) +BUILDIN(getcastledata) { const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); int index = script_getnum(st,3); - struct guild_castle *gc = guild_mapname2gc(mapname); - + struct guild_castle *gc = guild->mapname2gc(mapname); + if (gc == NULL) { script_pushint(st,0); ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname); - return 1; + return false; } - + switch (index) { case 1: script_pushint(st,gc->guild_id); break; @@ -11198,101 +10864,101 @@ BUILDIN_FUNC(getcastledata) } script_pushint(st,0); ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index); - return 1; + return false; } - return 0; + return true; } -BUILDIN_FUNC(setcastledata) +BUILDIN(setcastledata) { const char *mapname = mapindex_getmapname(script_getstr(st,2),NULL); int index = script_getnum(st,3); int value = script_getnum(st,4); - struct guild_castle *gc = guild_mapname2gc(mapname); - + struct guild_castle *gc = guild->mapname2gc(mapname); + if (gc == NULL) { ShowWarning("buildin_setcastledata: guild castle for map '%s' not found\n", mapname); - return 1; + return false; } - + if (index <= 0 || index > 9+MAX_GUARDIANS) { ShowWarning("buildin_setcastledata: index = '%d' is out of allowed range\n", index); - return 1; + return false; } - - guild_castledatasave(gc->castle_id, index, value); - return 0; + + guild->castledatasave(gc->castle_id, index, value); + return true; } /* ===================================================================== * ---------------------------------------------------------------------*/ -BUILDIN_FUNC(requestguildinfo) +BUILDIN(requestguildinfo) { int guild_id=script_getnum(st,2); const char *event=NULL; - + if( script_hasdata(st,3) ){ event=script_getstr(st,3); check_event(st, event); } - + if(guild_id>0) - guild_npc_request_info(guild_id,event); - return 0; + guild->npc_request_info(guild_id,event); + return true; } /// Returns the number of cards that have been compounded onto the specified equipped item. /// getequipcardcnt(<equipment slot>); -BUILDIN_FUNC(getequipcardcnt) +BUILDIN(getequipcardcnt) { int i=-1,j,num; TBL_PC *sd; int count; - + num=script_getnum(st,2); sd=script_rid2sd(st); if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); - + if (i < 0 || !sd->inventory_data[i]) { script_pushint(st,0); - return 0; + return true; } - + if(itemdb_isspecial(sd->status.inventory[i].card[0])) { script_pushint(st,0); - return 0; + return true; } - + count = 0; for( j = 0; j < sd->inventory_data[i]->slot; j++ ) if( sd->status.inventory[i].card[j] && itemdb_type(sd->status.inventory[i].card[j]) == IT_CARD ) count++; - + script_pushint(st,count); - return 0; + return true; } /// Removes all cards from the item found in the specified equipment slot of the invoking character, /// and give them to the character. If any cards were removed in this manner, it will also show a success effect. /// successremovecards <slot>; -BUILDIN_FUNC(successremovecards) { +BUILDIN(successremovecards) { int i=-1,j,c,cardflag=0; - + TBL_PC* sd = script_rid2sd(st); int num = script_getnum(st,2); - + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); - + if (i < 0 || !sd->inventory_data[i]) { - return 0; + return true; } - + if(itemdb_isspecial(sd->status.inventory[i].card[0])) - return 0; - + return true; + for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) {// extract this card from the item int flag; @@ -11301,37 +10967,37 @@ BUILDIN_FUNC(successremovecards) { cardflag = 1; item_tmp.nameid = sd->status.inventory[i].card[c]; item_tmp.identify = 1; - + if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ // get back the cart in inventory - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } } - + if(cardflag == 1) {//if card was remove remplace item with no card int flag; struct item item_tmp; memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = sd->status.inventory[i].nameid; item_tmp.identify = 1; item_tmp.refine = sd->status.inventory[i].refine; item_tmp.attribute = sd->status.inventory[i].attribute; item_tmp.expire_time = sd->status.inventory[i].expire_time; - + for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) item_tmp.card[j]=sd->status.inventory[i].card[j]; - + pc_delitem(sd,i,1,0,3,LOG_TYPE_SCRIPT); if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ //chk if can be spawn in inventory otherwise put on floor - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } - - clif_misceffect(&sd->bl,3); + + clif->misceffect(&sd->bl,3); } - return 0; + return true; } /// Removes all cards from the item found in the specified equipment slot of the invoking character. @@ -11340,43 +11006,43 @@ BUILDIN_FUNC(successremovecards) { /// <type>=1 : will keep the item, but destroy the cards. /// <type>=2 : will keep the cards, but destroy the item. /// <type>=? : will just display the failure effect. -BUILDIN_FUNC(failedremovecards) { +BUILDIN(failedremovecards) { int i=-1,j,c,cardflag=0; - + TBL_PC* sd = script_rid2sd(st); int num = script_getnum(st,2); int typefail = script_getnum(st,3); - + if (num > 0 && num <= ARRAYLENGTH(equip)) i=pc_checkequip(sd,equip[num-1]); - + if (i < 0 || !sd->inventory_data[i]) - return 0; - + return true; + if(itemdb_isspecial(sd->status.inventory[i].card[0])) - return 0; - + return true; + for( c = sd->inventory_data[i]->slot - 1; c >= 0; --c ) { if( sd->status.inventory[i].card[c] && itemdb_type(sd->status.inventory[i].card[c]) == IT_CARD ) { cardflag = 1; - + if(typefail == 2) {// add cards to inventory, clear int flag; struct item item_tmp; - + memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = sd->status.inventory[i].card[c]; item_tmp.identify = 1; - + if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } } } - + if(cardflag == 1) { if(typefail == 0 || typefail == 2){ // destroy the item pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); @@ -11384,29 +11050,29 @@ BUILDIN_FUNC(failedremovecards) { if(typefail == 1){ // destroy the card int flag; struct item item_tmp; - + memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = sd->status.inventory[i].nameid; item_tmp.identify = 1; item_tmp.refine = sd->status.inventory[i].refine; item_tmp.attribute = sd->status.inventory[i].attribute; item_tmp.expire_time = sd->status.inventory[i].expire_time; - + for (j = sd->inventory_data[i]->slot; j < MAX_SLOTS; j++) item_tmp.card[j]=sd->status.inventory[i].card[j]; - + pc_delitem(sd,i,1,0,2,LOG_TYPE_SCRIPT); - + if((flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_SCRIPT))){ - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } - clif_misceffect(&sd->bl,2); + clif->misceffect(&sd->bl,2); } - - return 0; + + return true; } /* ================================================================ @@ -11414,7 +11080,7 @@ BUILDIN_FUNC(failedremovecards) { * type: 0=everyone, 1=guild, 2=party; [Reddozen] * improved by [Lance] * ================================================================*/ -BUILDIN_FUNC(mapwarp) // Added by RoVeRT +BUILDIN(mapwarp) // Added by RoVeRT { int x,y,m,check_val=0,check_ID=0,i=0; struct guild *g = NULL; @@ -11430,16 +11096,16 @@ BUILDIN_FUNC(mapwarp) // Added by RoVeRT check_val=script_getnum(st,6); check_ID=script_getnum(st,7); } - + if((m=map_mapname2mapid(mapname))< 0) - return 0; - + return true; + if(!(index=mapindex_name2id(str))) - return 0; - + return true; + switch(check_val){ case 1: - g = guild_search(check_ID); + g = guild->search(check_ID); if (g){ for( i=0; i < g->max_member; i++) { @@ -11463,8 +11129,8 @@ BUILDIN_FUNC(mapwarp) // Added by RoVeRT map_foreachinmap(buildin_areawarp_sub,m,BL_PC,index,x,y,0,0); break; } - - return 0; + + return true; } static int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by RoVeRT @@ -11476,218 +11142,218 @@ static int buildin_mobcount_sub(struct block_list *bl,va_list ap) // Added by Ro return 0; } -BUILDIN_FUNC(mobcount) // Added by RoVeRT +BUILDIN(mobcount) // Added by RoVeRT { const char *mapname,*event; int16 m; mapname=script_getstr(st,2); event=script_getstr(st,3); - + if( strcmp(event, "all") == 0 ) event = NULL; else check_event(st, event); - + if( strcmp(mapname, "this") == 0 ) { struct map_session_data *sd = script_rid2sd(st); if( sd ) m = sd->bl.m; else { script_pushint(st,-1); - return 0; + return true; } } else if( (m = map_mapname2mapid(mapname)) < 0 ) { script_pushint(st,-1); - return 0; + return true; } - + if( map[m].flag.src4instance && map[m].instance_id == 0 && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) { script_pushint(st,-1); - return 0; + return true; } - + script_pushint(st,map_foreachinmap(buildin_mobcount_sub, m, BL_MOB, event)); - - return 0; + + return true; } -BUILDIN_FUNC(marriage) +BUILDIN(marriage) { const char *partner=script_getstr(st,2); TBL_PC *sd=script_rid2sd(st); TBL_PC *p_sd=map_nick2sd(partner); - + if(sd==NULL || p_sd==NULL || pc_marriage(sd,p_sd) < 0){ script_pushint(st,0); - return 0; + return true; } script_pushint(st,1); - return 0; + return true; } -BUILDIN_FUNC(wedding_effect) +BUILDIN(wedding_effect) { TBL_PC *sd=script_rid2sd(st); struct block_list *bl; - + if(sd==NULL) { bl=map_id2bl(st->oid); } else bl=&sd->bl; - clif_wedding_effect(bl); - return 0; + clif->wedding_effect(bl); + return true; } -BUILDIN_FUNC(divorce) +BUILDIN(divorce) { TBL_PC *sd=script_rid2sd(st); if(sd==NULL || pc_divorce(sd) < 0){ script_pushint(st,0); - return 0; + return true; } script_pushint(st,1); - return 0; + return true; } -BUILDIN_FUNC(ispartneron) +BUILDIN(ispartneron) { TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || !pc_ismarried(sd) || - map_charid2sd(sd->status.partner_id) == NULL) { + map_charid2sd(sd->status.partner_id) == NULL) { script_pushint(st,0); - return 0; + return true; } - + script_pushint(st,1); - return 0; + return true; } -BUILDIN_FUNC(getpartnerid) +BUILDIN(getpartnerid) { TBL_PC *sd=script_rid2sd(st); if (sd == NULL) { script_pushint(st,0); - return 0; + return true; } - + script_pushint(st,sd->status.partner_id); - return 0; + return true; } -BUILDIN_FUNC(getchildid) +BUILDIN(getchildid) { TBL_PC *sd=script_rid2sd(st); if (sd == NULL) { script_pushint(st,0); - return 0; + return true; } - + script_pushint(st,sd->status.child); - return 0; + return true; } -BUILDIN_FUNC(getmotherid) +BUILDIN(getmotherid) { TBL_PC *sd=script_rid2sd(st); if (sd == NULL) { script_pushint(st,0); - return 0; + return true; } - + script_pushint(st,sd->status.mother); - return 0; + return true; } -BUILDIN_FUNC(getfatherid) +BUILDIN(getfatherid) { TBL_PC *sd=script_rid2sd(st); if (sd == NULL) { script_pushint(st,0); - return 0; + return true; } - + script_pushint(st,sd->status.father); - return 0; + return true; } -BUILDIN_FUNC(warppartner) +BUILDIN(warppartner) { int x,y; unsigned short mapindex; const char *str; TBL_PC *sd=script_rid2sd(st); TBL_PC *p_sd=NULL; - + if(sd==NULL || !pc_ismarried(sd) || - (p_sd=map_charid2sd(sd->status.partner_id)) == NULL) { + (p_sd=map_charid2sd(sd->status.partner_id)) == NULL) { script_pushint(st,0); - return 0; + return true; } - + str=script_getstr(st,2); x=script_getnum(st,3); y=script_getnum(st,4); - + mapindex = mapindex_name2id(str); if (mapindex) { pc_setpos(p_sd,mapindex,x,y,CLR_OUTSIGHT); script_pushint(st,1); } else script_pushint(st,0); - return 0; + return true; } /*================================================ * Script for Displaying MOB Information [Valaris] *------------------------------------------------*/ -BUILDIN_FUNC(strmobinfo) +BUILDIN(strmobinfo) { - + int num=script_getnum(st,2); int class_=script_getnum(st,3); - + if(!mobdb_checkid(class_)) { if (num < 3) //requested a string script_pushconststr(st,""); else script_pushint(st,0); - return 0; + return true; } - + switch (num) { - case 1: script_pushstrcopy(st,mob_db(class_)->name); break; - case 2: script_pushstrcopy(st,mob_db(class_)->jname); break; - case 3: script_pushint(st,mob_db(class_)->lv); break; - case 4: script_pushint(st,mob_db(class_)->status.max_hp); break; - case 5: script_pushint(st,mob_db(class_)->status.max_sp); break; - case 6: script_pushint(st,mob_db(class_)->base_exp); break; - case 7: script_pushint(st,mob_db(class_)->job_exp); break; - default: - script_pushint(st,0); - break; + case 1: script_pushstrcopy(st,mob_db(class_)->name); break; + case 2: script_pushstrcopy(st,mob_db(class_)->jname); break; + case 3: script_pushint(st,mob_db(class_)->lv); break; + case 4: script_pushint(st,mob_db(class_)->status.max_hp); break; + case 5: script_pushint(st,mob_db(class_)->status.max_sp); break; + case 6: script_pushint(st,mob_db(class_)->base_exp); break; + case 7: script_pushint(st,mob_db(class_)->job_exp); break; + default: + script_pushint(st,0); + break; } - return 0; + return true; } /*========================================== * Summon guardians [Valaris] * guardian("<map name>",<x>,<y>,"<name to show>",<mob id>{,"<event label>"}{,<guardian index>}) -> <id> *------------------------------------------*/ -BUILDIN_FUNC(guardian) +BUILDIN(guardian) { int class_=0,x=0,y=0,guardian=0; const char *str,*map,*evt=""; struct script_data *data; bool has_index = false; - + map =script_getstr(st,2); x =script_getnum(st,3); y =script_getnum(st,4); str =script_getstr(st,5); class_=script_getnum(st,6); - + if( script_hasdata(st,8) ) {// "<event label>",<guardian index> evt=script_getstr(st,7); @@ -11706,24 +11372,24 @@ BUILDIN_FUNC(guardian) } else { ShowError("script:guardian: invalid data type for argument #6 (from 1)\n"); script_reportdata(data); - return 1; + return false; } } - + check_event(st, evt); script_pushint(st, mob_spawn_guardian(map,x,y,str,class_,evt,guardian,has_index)); - - return 0; + + return true; } /*========================================== * Invisible Walls [Zephyrus] *------------------------------------------*/ -BUILDIN_FUNC(setwall) +BUILDIN(setwall) { const char *map, *name; int x, y, m, size, dir; bool shootable; - + map = script_getstr(st,2); x = script_getnum(st,3); y = script_getnum(st,4); @@ -11731,19 +11397,19 @@ BUILDIN_FUNC(setwall) dir = script_getnum(st,6); shootable = script_getnum(st,7); name = script_getstr(st,8); - + if( (m = map_mapname2mapid(map)) < 0 ) - return 0; // Invalid Map - + return true; // Invalid Map + map_iwall_set(m, x, y, size, dir, shootable, name); - return 0; + return true; } -BUILDIN_FUNC(delwall) +BUILDIN(delwall) { const char *name = script_getstr(st,2); map_iwall_remove(name); - - return 0; + + return true; } /// Retrieves various information about the specified guardian. @@ -11753,90 +11419,90 @@ BUILDIN_FUNC(delwall) /// 1 - maximum hp /// 2 - current hp /// -BUILDIN_FUNC(guardianinfo) +BUILDIN(guardianinfo) { const char* mapname = mapindex_getmapname(script_getstr(st,2),NULL); int id = script_getnum(st,3); int type = script_getnum(st,4); - - struct guild_castle* gc = guild_mapname2gc(mapname); + + struct guild_castle* gc = guild->mapname2gc(mapname); struct mob_data* gd; - + if( gc == NULL || id < 0 || id >= MAX_GUARDIANS ) { script_pushint(st,-1); - return 0; + return true; } - + if( type == 0 ) script_pushint(st, gc->guardian[id].visible); else - if( !gc->guardian[id].visible ) - script_pushint(st,-1); - else - if( (gd = map_id2md(gc->guardian[id].id)) == NULL ) - script_pushint(st,-1); - else - { - if ( type == 1 ) script_pushint(st,gd->status.max_hp); - else if( type == 2 ) script_pushint(st,gd->status.hp); - else + if( !gc->guardian[id].visible ) script_pushint(st,-1); - } - - return 0; + else + if( (gd = map_id2md(gc->guardian[id].id)) == NULL ) + script_pushint(st,-1); + else + { + if ( type == 1 ) script_pushint(st,gd->status.max_hp); + else if( type == 2 ) script_pushint(st,gd->status.hp); + else + script_pushint(st,-1); + } + + return true; } /*========================================== * Get the item name by item_id or null *------------------------------------------*/ -BUILDIN_FUNC(getitemname) +BUILDIN(getitemname) { int item_id=0; struct item_data *i_data; char *item_name; struct script_data *data; - + data=script_getdata(st,2); get_val(st,data); - + if( data_isstring(data) ){ - const char *name=conv_str(st,data); + const char *name=script->conv_str(st,data); struct item_data *item_data = itemdb_searchname(name); if( item_data ) item_id=item_data->nameid; }else - item_id=conv_num(st,data); - + item_id=script->conv_num(st,data); + i_data = itemdb_exists(item_id); if (i_data == NULL) { script_pushconststr(st,"null"); - return 0; + return true; } item_name=(char *)aMalloc(ITEM_NAME_LENGTH*sizeof(char)); - + memcpy(item_name, i_data->jname, ITEM_NAME_LENGTH); script_pushstr(st,item_name); - return 0; + return true; } /*========================================== * Returns number of slots an item has. [Skotlex] *------------------------------------------*/ -BUILDIN_FUNC(getitemslots) +BUILDIN(getitemslots) { int item_id; struct item_data *i_data; - + item_id=script_getnum(st,2); - + i_data = itemdb_exists(item_id); - + if (i_data) script_pushint(st,i_data->slot); else script_pushint(st,-1); - return 0; + return true; } // TODO: add matk here if needed/once we get rid of RENEWAL @@ -11844,103 +11510,103 @@ BUILDIN_FUNC(getitemslots) /*========================================== * Returns some values of an item [Lupus] * Price, Weight, etc... - getiteminfo(itemID,n), where n - 0 value_buy; - 1 value_sell; - 2 type; - 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. - if = 0, then monsters don't drop it at all (rare or a quest item) - if = -1, then this item is sold in NPC shops only - 4 sex; - 5 equip; - 6 weight; - 7 atk; - 8 def; - 9 range; - 10 slot; - 11 look; - 12 elv; - 13 wlv; - 14 view id + getiteminfo(itemID,n), where n + 0 value_buy; + 1 value_sell; + 2 type; + 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. + if = 0, then monsters don't drop it at all (rare or a quest item) + if = -1, then this item is sold in NPC shops only + 4 sex; + 5 equip; + 6 weight; + 7 atk; + 8 def; + 9 range; + 10 slot; + 11 look; + 12 elv; + 13 wlv; + 14 view id *------------------------------------------*/ -BUILDIN_FUNC(getiteminfo) +BUILDIN(getiteminfo) { int item_id,n; int *item_arr; struct item_data *i_data; - + item_id = script_getnum(st,2); n = script_getnum(st,3); i_data = itemdb_exists(item_id); - + if (i_data && n>=0 && n<=14) { item_arr = (int*)&i_data->value_buy; script_pushint(st,item_arr[n]); } else script_pushint(st,-1); - return 0; + return true; } /*========================================== * Set some values of an item [Lupus] * Price, Weight, etc... - setiteminfo(itemID,n,Value), where n - 0 value_buy; - 1 value_sell; - 2 type; - 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. - if = 0, then monsters don't drop it at all (rare or a quest item) - if = -1, then this item is sold in NPC shops only - 4 sex; - 5 equip; - 6 weight; - 7 atk; - 8 def; - 9 range; - 10 slot; - 11 look; - 12 elv; - 13 wlv; - 14 view id - * Returns Value or -1 if the wrong field's been set + setiteminfo(itemID,n,Value), where n + 0 value_buy; + 1 value_sell; + 2 type; + 3 maxchance = Max drop chance of this item e.g. 1 = 0.01% , etc.. + if = 0, then monsters don't drop it at all (rare or a quest item) + if = -1, then this item is sold in NPC shops only + 4 sex; + 5 equip; + 6 weight; + 7 atk; + 8 def; + 9 range; + 10 slot; + 11 look; + 12 elv; + 13 wlv; + 14 view id + * Returns Value or -1 if the wrong field's been set *------------------------------------------*/ -BUILDIN_FUNC(setiteminfo) +BUILDIN(setiteminfo) { int item_id,n,value; int *item_arr; struct item_data *i_data; - + item_id = script_getnum(st,2); n = script_getnum(st,3); value = script_getnum(st,4); i_data = itemdb_exists(item_id); - + if (i_data && n>=0 && n<=14) { item_arr = (int*)&i_data->value_buy; item_arr[n] = value; script_pushint(st,value); } else script_pushint(st,-1); - return 0; + return true; } /*========================================== * Returns value from equipped item slot n [Lupus] - getequipcardid(num,slot) - where - num = eqip position slot - slot = 0,1,2,3 (Card Slot N) - - This func returns CARD ID, 255,254,-255 (for card 0, if the item is produced) - it's useful when you want to check item cards or if it's signed - Useful for such quests as "Sign this refined item with players name" etc - Hat[0] +4 -> Player's Hat[0] +4 + getequipcardid(num,slot) + where + num = eqip position slot + slot = 0,1,2,3 (Card Slot N) + + This func returns CARD ID, 255,254,-255 (for card 0, if the item is produced) + it's useful when you want to check item cards or if it's signed + Useful for such quests as "Sign this refined item with players name" etc + Hat[0] +4 -> Player's Hat[0] +4 *------------------------------------------*/ -BUILDIN_FUNC(getequipcardid) +BUILDIN(getequipcardid) { int i=-1,num,slot; TBL_PC *sd; - + num=script_getnum(st,2); slot=script_getnum(st,3); sd=script_rid2sd(st); @@ -11950,22 +11616,22 @@ BUILDIN_FUNC(getequipcardid) script_pushint(st,sd->status.inventory[i].card[slot]); else script_pushint(st,0); - - return 0; + + return true; } /*========================================== * petskillbonus [Valaris] //Rewritten by [Skotlex] *------------------------------------------*/ -BUILDIN_FUNC(petskillbonus) +BUILDIN(petskillbonus) { struct pet_data *pd; - + TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) - return 0; - + return true; + pd=sd->pd; if (pd->bonus) { //Clear previous bonus @@ -11973,43 +11639,43 @@ BUILDIN_FUNC(petskillbonus) delete_timer(pd->bonus->timer, pet_skill_bonus_timer); } else //init pd->bonus = (struct pet_bonus *) aMalloc(sizeof(struct pet_bonus)); - + pd->bonus->type=script_getnum(st,2); pd->bonus->val=script_getnum(st,3); pd->bonus->duration=script_getnum(st,4); pd->bonus->delay=script_getnum(st,5); - + if (pd->state.skillbonus == 1) pd->state.skillbonus=0; // waiting state - + // wait for timer to start if (battle_config.pet_equip_required && pd->pet.equip == 0) pd->bonus->timer = INVALID_TIMER; else pd->bonus->timer = add_timer(gettick()+pd->bonus->delay*1000, pet_skill_bonus_timer, sd->bl.id, 0); - - return 0; + + return true; } /*========================================== * pet looting [Valaris] //Rewritten by [Skotlex] *------------------------------------------*/ -BUILDIN_FUNC(petloot) +BUILDIN(petloot) { int max; struct pet_data *pd; TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) - return 0; - + return true; + max=script_getnum(st,2); - + if(max < 1) max = 1; //Let'em loot at least 1 item. else if (max > MAX_PETLOOT_SIZE) max = MAX_PETLOOT_SIZE; - + pd = sd->pd; if (pd->loot != NULL) { //Release whatever was there already and reallocate memory @@ -12018,14 +11684,14 @@ BUILDIN_FUNC(petloot) } else pd->loot = (struct pet_loot *)aMalloc(sizeof(struct pet_loot)); - + pd->loot->item = (struct item *)aCalloc(max,sizeof(struct item)); - + pd->loot->max=max; pd->loot->count = 0; pd->loot->weight = 0; - - return 0; + + return true; } /*========================================== * Set arrays with info of all sd inventory : @@ -12034,13 +11700,13 @@ BUILDIN_FUNC(petloot) * @inventorylist_card(0..3), @inventorylist_expire * @inventorylist_count = scalar *------------------------------------------*/ -BUILDIN_FUNC(getinventorylist) +BUILDIN(getinventorylist) { TBL_PC *sd=script_rid2sd(st); char card_var[NAME_LENGTH]; - + int i,j=0,k; - if(!sd) return 0; + if(!sd) return true; for(i=0;i<MAX_INVENTORY;i++){ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0){ pc_setreg(sd,reference_uid(add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid); @@ -12059,14 +11725,14 @@ BUILDIN_FUNC(getinventorylist) } } pc_setreg(sd,add_str("@inventorylist_count"),j); - return 0; + return true; } -BUILDIN_FUNC(getskilllist) +BUILDIN(getskilllist) { TBL_PC *sd=script_rid2sd(st); int i,j=0; - if(!sd) return 0; + if(!sd) return true; for(i=0;i<MAX_SKILL;i++){ if(sd->status.skill[i].id > 0 && sd->status.skill[i].lv > 0){ pc_setreg(sd,reference_uid(add_str("@skilllist_id"), j),sd->status.skill[i].id); @@ -12076,139 +11742,139 @@ BUILDIN_FUNC(getskilllist) } } pc_setreg(sd,add_str("@skilllist_count"),j); - return 0; + return true; } -BUILDIN_FUNC(clearitem) +BUILDIN(clearitem) { TBL_PC *sd=script_rid2sd(st); int i; - if(sd==NULL) return 0; + if(sd==NULL) return true; for (i=0; i<MAX_INVENTORY; i++) { if (sd->status.inventory[i].amount) { pc_delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_SCRIPT); } } - return 0; + return true; } /*========================================== * Disguise Player (returns Mob/NPC ID if success, 0 on fail) *------------------------------------------*/ -BUILDIN_FUNC(disguise) +BUILDIN(disguise) { int id; TBL_PC* sd = script_rid2sd(st); - if (sd == NULL) return 0; - + if (sd == NULL) return true; + id = script_getnum(st,2); - + if (mobdb_checkid(id) || npcdb_checkid(id)) { pc_disguise(sd, id); script_pushint(st,id); } else script_pushint(st,0); - - return 0; + + return true; } /*========================================== * Undisguise Player (returns 1 if success, 0 on fail) *------------------------------------------*/ -BUILDIN_FUNC(undisguise) +BUILDIN(undisguise) { TBL_PC* sd = script_rid2sd(st); - if (sd == NULL) return 0; - - if (sd->disguise) { - pc_disguise(sd, 0); + if (sd == NULL) return true; + + if (sd->disguise != -1) { + pc_disguise(sd, -1); script_pushint(st,0); } else { script_pushint(st,1); } - return 0; + return true; } /*========================================== * Transform a bl to another _class, * @type unused *------------------------------------------*/ -BUILDIN_FUNC(classchange) +BUILDIN(classchange) { int _class,type; struct block_list *bl=map_id2bl(st->oid); - - if(bl==NULL) return 0; - + + if(bl==NULL) return true; + _class=script_getnum(st,2); type=script_getnum(st,3); - clif_class_change(bl,_class,type); - return 0; + clif->class_change(bl,_class,type); + return true; } /*========================================== * Display an effect *------------------------------------------*/ -BUILDIN_FUNC(misceffect) +BUILDIN(misceffect) { int type; - + type=script_getnum(st,2); if(st->oid && st->oid != fake_nd->bl.id) { struct block_list *bl = map_id2bl(st->oid); if (bl) - clif_specialeffect(bl,type,AREA); + clif->specialeffect(bl,type,AREA); } else{ TBL_PC *sd=script_rid2sd(st); if(sd) - clif_specialeffect(&sd->bl,type,AREA); + clif->specialeffect(&sd->bl,type,AREA); } - return 0; + return true; } /*========================================== * Play a BGM on a single client [Rikter/Yommy] *------------------------------------------*/ -BUILDIN_FUNC(playBGM) +BUILDIN(playBGM) { const char* name; struct map_session_data* sd; - + if( ( sd = script_rid2sd(st) ) != NULL ) { name = script_getstr(st,2); - - clif_playBGM(sd, name); + + clif->playBGM(sd, name); } - - return 0; + + return true; } static int playBGM_sub(struct block_list* bl,va_list ap) { const char* name = va_arg(ap,const char*); - - clif_playBGM(BL_CAST(BL_PC, bl), name); - + + clif->playBGM(BL_CAST(BL_PC, bl), name); + return 0; } static int playBGM_foreachpc_sub(struct map_session_data* sd, va_list args) { const char* name = va_arg(args, const char*); - - clif_playBGM(sd, name); + + clif->playBGM(sd, name); return 0; } /*========================================== * Play a BGM on multiple client [Rikter/Yommy] *------------------------------------------*/ -BUILDIN_FUNC(playBGMall) +BUILDIN(playBGMall) { const char* name; - + name = script_getstr(st,2); - + if( script_hasdata(st,7) ) {// specified part of map const char* map = script_getstr(st,3); @@ -12216,133 +11882,133 @@ BUILDIN_FUNC(playBGMall) int y0 = script_getnum(st,5); int x1 = script_getnum(st,6); int y1 = script_getnum(st,7); - + map_foreachinarea(playBGM_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name); } else if( script_hasdata(st,3) ) {// entire map const char* map = script_getstr(st,3); - + map_foreachinmap(playBGM_sub, map_mapname2mapid(map), BL_PC, name); } else {// entire server map_foreachpc(&playBGM_foreachpc_sub, name); } - - return 0; + + return true; } /*========================================== * Play a .wav sound for sd *------------------------------------------*/ -BUILDIN_FUNC(soundeffect) +BUILDIN(soundeffect) { TBL_PC* sd = script_rid2sd(st); const char* name = script_getstr(st,2); int type = script_getnum(st,3); - + if(sd) { - clif_soundeffect(sd,&sd->bl,name,type); + clif->soundeffect(sd,&sd->bl,name,type); } - return 0; + return true; } int soundeffect_sub(struct block_list* bl,va_list ap) { char* name = va_arg(ap,char*); int type = va_arg(ap,int); - - clif_soundeffect((TBL_PC *)bl, bl, name, type); - - return 0; + + clif->soundeffect((TBL_PC *)bl, bl, name, type); + + return true; } /*========================================== * Play a sound effect (.wav) on multiple clients * soundeffectall "<filepath>",<type>{,"<map name>"}{,<x0>,<y0>,<x1>,<y1>}; *------------------------------------------*/ -BUILDIN_FUNC(soundeffectall) +BUILDIN(soundeffectall) { struct block_list* bl; const char* name; int type; - + bl = (st->rid) ? &(script_rid2sd(st)->bl) : map_id2bl(st->oid); if (!bl) - return 0; - + return true; + name = script_getstr(st,2); type = script_getnum(st,3); - + //FIXME: enumerating map squares (map_foreach) is slower than enumerating the list of online players (map_foreachpc?) [ultramage] - + if(!script_hasdata(st,4)) { // area around - clif_soundeffectall(bl, name, type, AREA); - } - else - if(!script_hasdata(st,5)) - { // entire map - const char* map = script_getstr(st,4); - map_foreachinmap(soundeffect_sub, map_mapname2mapid(map), BL_PC, name, type); + clif->soundeffectall(bl, name, type, AREA); } else - if(script_hasdata(st,8)) - { // specified part of map - const char* map = script_getstr(st,4); - int x0 = script_getnum(st,5); - int y0 = script_getnum(st,6); - int x1 = script_getnum(st,7); - int y1 = script_getnum(st,8); - map_foreachinarea(soundeffect_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name, type); - } - else - { - ShowError("buildin_soundeffectall: insufficient arguments for specific area broadcast.\n"); - } - - return 0; + if(!script_hasdata(st,5)) + { // entire map + const char* map = script_getstr(st,4); + map_foreachinmap(soundeffect_sub, map_mapname2mapid(map), BL_PC, name, type); + } + else + if(script_hasdata(st,8)) + { // specified part of map + const char* map = script_getstr(st,4); + int x0 = script_getnum(st,5); + int y0 = script_getnum(st,6); + int x1 = script_getnum(st,7); + int y1 = script_getnum(st,8); + map_foreachinarea(soundeffect_sub, map_mapname2mapid(map), x0, y0, x1, y1, BL_PC, name, type); + } + else + { + ShowError("buildin_soundeffectall: insufficient arguments for specific area broadcast.\n"); + } + + return true; } /*========================================== * pet status recovery [Valaris] / Rewritten by [Skotlex] *------------------------------------------*/ -BUILDIN_FUNC(petrecovery) +BUILDIN(petrecovery) { struct pet_data *pd; TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) - return 0; - + return true; + pd=sd->pd; - + if (pd->recovery) { //Halt previous bonus if (pd->recovery->timer != INVALID_TIMER) delete_timer(pd->recovery->timer, pet_recovery_timer); } else //Init pd->recovery = (struct pet_recovery *)aMalloc(sizeof(struct pet_recovery)); - + pd->recovery->type = (sc_type)script_getnum(st,2); pd->recovery->delay = script_getnum(st,3); pd->recovery->timer = INVALID_TIMER; - - return 0; + + return true; } /*========================================== * pet healing [Valaris] //Rewritten by [Skotlex] *------------------------------------------*/ -BUILDIN_FUNC(petheal) +BUILDIN(petheal) { struct pet_data *pd; TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) - return 0; - + return true; + pd=sd->pd; if (pd->s_skill) { //Clear previous skill @@ -12355,21 +12021,21 @@ BUILDIN_FUNC(petheal) } } else //init memory pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); - + pd->s_skill->id=0; //This id identifies that it IS petheal rather than pet_skillsupport //Use the lv as the amount to heal pd->s_skill->lv=script_getnum(st,2); pd->s_skill->delay=script_getnum(st,3); pd->s_skill->hp=script_getnum(st,4); pd->s_skill->sp=script_getnum(st,5); - + //Use delay as initial offset to avoid skill/heal exploits if (battle_config.pet_equip_required && pd->pet.equip == 0) pd->s_skill->timer = INVALID_TIMER; else pd->s_skill->timer = add_timer(gettick()+pd->s_skill->delay*1000,pet_heal_timer,sd->bl.id,0); - - return 0; + + return true; } /*========================================== @@ -12377,25 +12043,25 @@ BUILDIN_FUNC(petheal) *------------------------------------------*/ /// petskillattack <skill id>,<level>,<rate>,<bonusrate> /// petskillattack "<skill name>",<level>,<rate>,<bonusrate> -BUILDIN_FUNC(petskillattack) +BUILDIN(petskillattack) { struct pet_data *pd; TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) - return 0; - + return true; + pd=sd->pd; if (pd->a_skill == NULL) pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); - - pd->a_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + + pd->a_skill->id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); pd->a_skill->lv=script_getnum(st,3); pd->a_skill->div_ = 0; pd->a_skill->rate=script_getnum(st,4); pd->a_skill->bonusrate=script_getnum(st,5); - - return 0; + + return true; } /*========================================== @@ -12403,25 +12069,25 @@ BUILDIN_FUNC(petskillattack) *------------------------------------------*/ /// petskillattack2 <skill id>,<level>,<div>,<rate>,<bonusrate> /// petskillattack2 "<skill name>",<level>,<div>,<rate>,<bonusrate> -BUILDIN_FUNC(petskillattack2) +BUILDIN(petskillattack2) { struct pet_data *pd; TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) - return 0; - + return true; + pd=sd->pd; if (pd->a_skill == NULL) pd->a_skill = (struct pet_skill_attack *)aMalloc(sizeof(struct pet_skill_attack)); - - pd->a_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + + pd->a_skill->id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); pd->a_skill->lv=script_getnum(st,3); pd->a_skill->div_ = script_getnum(st,4); pd->a_skill->rate=script_getnum(st,5); pd->a_skill->bonusrate=script_getnum(st,6); - - return 0; + + return true; } /*========================================== @@ -12429,14 +12095,14 @@ BUILDIN_FUNC(petskillattack2) *------------------------------------------*/ /// petskillsupport <skill id>,<level>,<delay>,<hp>,<sp> /// petskillsupport "<skill name>",<level>,<delay>,<hp>,<sp> -BUILDIN_FUNC(petskillsupport) +BUILDIN(petskillsupport) { struct pet_data *pd; TBL_PC *sd=script_rid2sd(st); - + if(sd==NULL || sd->pd==NULL) - return 0; - + return true; + pd=sd->pd; if (pd->s_skill) { //Clear previous skill @@ -12449,20 +12115,20 @@ BUILDIN_FUNC(petskillsupport) } } else //init memory pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support)); - - pd->s_skill->id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + + pd->s_skill->id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); pd->s_skill->lv=script_getnum(st,3); pd->s_skill->delay=script_getnum(st,4); pd->s_skill->hp=script_getnum(st,5); pd->s_skill->sp=script_getnum(st,6); - + //Use delay as initial offset to avoid skill/heal exploits if (battle_config.pet_equip_required && pd->pet.equip == 0) pd->s_skill->timer = INVALID_TIMER; else pd->s_skill->timer = add_timer(gettick()+pd->s_skill->delay*1000,pet_skill_support_timer,sd->bl.id,0); - - return 0; + + return true; } /*========================================== @@ -12470,17 +12136,17 @@ BUILDIN_FUNC(petskillsupport) *------------------------------------------*/ /// skilleffect <skill id>,<level> /// skilleffect "<skill name>",<level> -BUILDIN_FUNC(skilleffect) +BUILDIN(skilleffect) { TBL_PC *sd; - - uint16 skill_id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + + uint16 skill_id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); uint16 skill_lv=script_getnum(st,3); sd=script_rid2sd(st); - - clif_skill_nodamage(&sd->bl,&sd->bl,skill_id,skill_lv,1); - - return 0; + + clif->skill_nodamage(&sd->bl,&sd->bl,skill_id,skill_lv,1); + + return true; } /*========================================== @@ -12488,79 +12154,79 @@ BUILDIN_FUNC(skilleffect) *------------------------------------------*/ /// npcskilleffect <skill id>,<level>,<x>,<y> /// npcskilleffect "<skill name>",<level>,<x>,<y> -BUILDIN_FUNC(npcskilleffect) +BUILDIN(npcskilleffect) { struct block_list *bl= map_id2bl(st->oid); - - uint16 skill_id=( script_isstring(st,2) ? skill_name2id(script_getstr(st,2)) : script_getnum(st,2) ); + + uint16 skill_id=( script_isstring(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) ); uint16 skill_lv=script_getnum(st,3); int x=script_getnum(st,4); int y=script_getnum(st,5); - + if (bl) - clif_skill_poseffect(bl,skill_id,skill_lv,x,y,gettick()); - - return 0; + clif->skill_poseffect(bl,skill_id,skill_lv,x,y,gettick()); + + return true; } /*========================================== * Special effects [Valaris] *------------------------------------------*/ -BUILDIN_FUNC(specialeffect) +BUILDIN(specialeffect) { struct block_list *bl=map_id2bl(st->oid); int type = script_getnum(st,2); enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; - + if(bl==NULL) - return 0; - + return true; + if( script_hasdata(st,4) ) { TBL_NPC *nd = npc_name2id(script_getstr(st,4)); if(nd) - clif_specialeffect(&nd->bl, type, target); + clif->specialeffect(&nd->bl, type, target); } else { if (target == SELF) { TBL_PC *sd=script_rid2sd(st); if (sd) - clif_specialeffect_single(bl,type,sd->fd); + clif->specialeffect_single(bl,type,sd->fd); } else { - clif_specialeffect(bl, type, target); + clif->specialeffect(bl, type, target); } } - - return 0; + + return true; } -BUILDIN_FUNC(specialeffect2) +BUILDIN(specialeffect2) { TBL_PC *sd=script_rid2sd(st); int type = script_getnum(st,2); enum send_target target = script_hasdata(st,3) ? (send_target)script_getnum(st,3) : AREA; - + if( script_hasdata(st,4) ) sd = map_nick2sd(script_getstr(st,4)); - + if (sd) - clif_specialeffect(&sd->bl, type, target); - - return 0; + clif->specialeffect(&sd->bl, type, target); + + return true; } /*========================================== * Nude [Valaris] *------------------------------------------*/ -BUILDIN_FUNC(nude) +BUILDIN(nude) { TBL_PC *sd = script_rid2sd(st); int i, calcflag = 0; - + if( sd == NULL ) - return 0; - + return true; + for( i = 0 ; i < EQI_MAX; i++ ) { if( sd->equip_index[ i ] >= 0 ) { if( !calcflag ) @@ -12568,32 +12234,32 @@ BUILDIN_FUNC(nude) pc_unequipitem( sd , sd->equip_index[ i ] , 2); } } - + if( calcflag ) status_calc_pc(sd,0); - - return 0; + + return true; } /*========================================== * gmcommand [MouseJstr] *------------------------------------------*/ -BUILDIN_FUNC(atcommand) +BUILDIN(atcommand) { TBL_PC dummy_sd; TBL_PC* sd; int fd; const char* cmd; - + cmd = script_getstr(st,2); - + if (st->rid) { sd = script_rid2sd(st); fd = sd->fd; } else { //Use a dummy character. sd = &dummy_sd; fd = 0; - + memset(&dummy_sd, 0, sizeof(TBL_PC)); if (st->oid) { @@ -12603,67 +12269,67 @@ BUILDIN_FUNC(atcommand) safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH); } } - - if (!is_atcommand(fd, sd, cmd, 0)) { + + if (!atcommand->parse(fd, sd, cmd, 0)) { ShowWarning("script: buildin_atcommand: failed to execute command '%s'\n", cmd); script_reportsrc(st); - return 1; + return false; } - - return 0; + + return true; } /*========================================== * Displays a message for the player only (like system messages like "you got an apple" ) *------------------------------------------*/ -BUILDIN_FUNC(dispbottom) +BUILDIN(dispbottom) { TBL_PC *sd=script_rid2sd(st); const char *message; message=script_getstr(st,2); if(sd) - clif_disp_onlyself(sd,message,(int)strlen(message)); - return 0; + clif->disp_onlyself(sd,message,(int)strlen(message)); + return true; } /*========================================== * All The Players Full Recovery * (HP/SP full restore and resurrect if need) *------------------------------------------*/ -BUILDIN_FUNC(recovery) +BUILDIN(recovery) { TBL_PC* sd; struct s_mapiterator* iter; - + iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) { if(pc_isdead(sd)) status_revive(&sd->bl, 100, 100); else status_percent_heal(&sd->bl, 100, 100); - clif_displaymessage(sd->fd,msg_txt(680)); + clif->message(sd->fd,msg_txt(680)); } - mapit_free(iter); - return 0; + mapit->free(iter); + return true; } /*========================================== * Get your pet info: getpetinfo(n) * n -> 0:pet_id 1:pet_class 2:pet_name * 3:friendly 4:hungry, 5: rename flag. *------------------------------------------*/ -BUILDIN_FUNC(getpetinfo) +BUILDIN(getpetinfo) { TBL_PC *sd=script_rid2sd(st); TBL_PET *pd; int type=script_getnum(st,2); - + if(!sd || !sd->pd) { if (type == 2) script_pushconststr(st,"null"); else script_pushint(st,0); - return 0; + return true; } pd = sd->pd; switch(type){ @@ -12677,7 +12343,7 @@ BUILDIN_FUNC(getpetinfo) script_pushint(st,0); break; } - return 0; + return true; } /*========================================== @@ -12686,22 +12352,22 @@ BUILDIN_FUNC(getpetinfo) * 3:friendly 4:hungry, 5: rename flag. * 6: level *------------------------------------------*/ -BUILDIN_FUNC(gethominfo) +BUILDIN(gethominfo) { TBL_PC *sd=script_rid2sd(st); TBL_HOM *hd; int type=script_getnum(st,2); - + hd = sd?sd->hd:NULL; - if(!merc_is_hom_active(hd)) + if(!homun_alive(hd)) { if (type == 2) script_pushconststr(st,"null"); else script_pushint(st,0); - return 0; + return true; } - + switch(type){ case 0: script_pushint(st,hd->homunculus.hom_id); break; case 1: script_pushint(st,hd->homunculus.class_); break; @@ -12714,28 +12380,28 @@ BUILDIN_FUNC(gethominfo) script_pushint(st,0); break; } - return 0; + return true; } /// Retrieves information about character's mercenary /// getmercinfo <type>[,<char id>]; -BUILDIN_FUNC(getmercinfo) +BUILDIN(getmercinfo) { int type, char_id; struct map_session_data* sd; struct mercenary_data* md; - + type = script_getnum(st,2); - + if( script_hasdata(st,3) ) { char_id = script_getnum(st,3); - + if( ( sd = map_charid2sd(char_id) ) == NULL ) { ShowError("buildin_getmercinfo: No such character (char_id=%d).\n", char_id); script_pushnil(st); - return 1; + return false; } } else @@ -12743,12 +12409,12 @@ BUILDIN_FUNC(getmercinfo) if( ( sd = script_rid2sd(st) ) == NULL ) { script_pushnil(st); - return 0; + return true; } } - + md = ( sd->status.mer_id && sd->md ) ? sd->md : NULL; - + switch( type ) { case 0: script_pushint(st,md ? md->mercenary.mercenary_id : 0); break; @@ -12767,25 +12433,25 @@ BUILDIN_FUNC(getmercinfo) default: ShowError("buildin_getmercinfo: Invalid type %d (char_id=%d).\n", type, sd->status.char_id); script_pushnil(st); - return 1; + return false; } - - return 0; + + return true; } /*========================================== * Shows wether your inventory(and equips) contain - selected card or not. - checkequipedcard(4001); + selected card or not. + checkequipedcard(4001); *------------------------------------------*/ -BUILDIN_FUNC(checkequipedcard) +BUILDIN(checkequipedcard) { TBL_PC *sd=script_rid2sd(st); - + if(sd){ int n,i,c=0; c=script_getnum(st,2); - + for(i=0;i<MAX_INVENTORY;i++){ if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount && sd->inventory_data[i]){ if (itemdb_isspecial(sd->status.inventory[i].card[0])) @@ -12793,17 +12459,17 @@ BUILDIN_FUNC(checkequipedcard) for(n=0;n<sd->inventory_data[i]->slot;n++){ if(sd->status.inventory[i].card[n]==c){ script_pushint(st,1); - return 0; + return true; } } } } } script_pushint(st,0); - return 0; + return true; } -BUILDIN_FUNC(jump_zero) +BUILDIN(jump_zero) { int sel; sel=script_getnum(st,2); @@ -12812,104 +12478,104 @@ BUILDIN_FUNC(jump_zero) if( !data_islabel(script_getdata(st,3)) ){ ShowError("script: jump_zero: not label !\n"); st->state=END; - return 1; + return false; } - + pos=script_getnum(st,3); st->pos=pos; st->state=GOTO; } - return 0; + return true; } /*========================================== * movenpc [MouseJstr] *------------------------------------------*/ -BUILDIN_FUNC(movenpc) +BUILDIN(movenpc) { TBL_NPC *nd = NULL; const char *npc; int x,y; - + npc = script_getstr(st,2); x = script_getnum(st,3); y = script_getnum(st,4); - + if ((nd = npc_name2id(npc)) == NULL) return -1; - + if (script_hasdata(st,5)) nd->ud.dir = script_getnum(st,5) % 8; npc_movenpc(nd, x, y); - return 0; + return true; } /*========================================== * message [MouseJstr] *------------------------------------------*/ -BUILDIN_FUNC(message) +BUILDIN(message) { const char *msg,*player; TBL_PC *pl_sd = NULL; - + player = script_getstr(st,2); msg = script_getstr(st,3); - + if((pl_sd=map_nick2sd((char *) player)) == NULL) - return 0; - clif_displaymessage(pl_sd->fd, msg); - - return 0; + return true; + clif->message(pl_sd->fd, msg); + + return true; } /*========================================== * npctalk (sends message to surrounding area) *------------------------------------------*/ -BUILDIN_FUNC(npctalk) +BUILDIN(npctalk) { const char* str; char name[NAME_LENGTH], message[256]; - + struct npc_data* nd = (struct npc_data *)map_id2bl(st->oid); str = script_getstr(st,2); - + if(nd) { safestrncpy(name, nd->name, sizeof(name)); strtok(name, "#"); // discard extra name identifier if present safesnprintf(message, sizeof(message), "%s : %s", name, str); - clif_message(&nd->bl, message); + clif->disp_overhead(&nd->bl, message); } - - return 0; + + return true; } // change npc walkspeed [Valaris] -BUILDIN_FUNC(npcspeed) +BUILDIN(npcspeed) { struct npc_data* nd; int speed; - + speed = script_getnum(st,2); nd =(struct npc_data *)map_id2bl(st->oid); - + if( nd ) { nd->speed = speed; nd->ud.state.speed_changed = 1; } - - return 0; + + return true; } // make an npc walk to a position [Valaris] -BUILDIN_FUNC(npcwalkto) +BUILDIN(npcwalkto) { struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); int x=0,y=0; - + x=script_getnum(st,2); y=script_getnum(st,3); - + if(nd) { if (!nd->status.hp) { status_calc_npc(nd, true); @@ -12918,65 +12584,66 @@ BUILDIN_FUNC(npcwalkto) } unit_walktoxy(&nd->bl,x,y,0); } - - return 0; + + return true; } // stop an npc's movement [Valaris] -BUILDIN_FUNC(npcstop) +BUILDIN(npcstop) { struct npc_data *nd=(struct npc_data *)map_id2bl(st->oid); - + if(nd) { unit_stop_walking(&nd->bl,1|4); } - - return 0; + + return true; } /*========================================== * getlook char info. getlook(arg) *------------------------------------------*/ -BUILDIN_FUNC(getlook) -{ - int type,val; - TBL_PC *sd; - sd=script_rid2sd(st); - - type=script_getnum(st,2); - val=-1; - switch(type) { - case LOOK_HAIR: val=sd->status.hair; break; //1 - case LOOK_WEAPON: val=sd->status.weapon; break; //2 - case LOOK_HEAD_BOTTOM: val=sd->status.head_bottom; break; //3 - case LOOK_HEAD_TOP: val=sd->status.head_top; break; //4 - case LOOK_HEAD_MID: val=sd->status.head_mid; break; //5 - case LOOK_HAIR_COLOR: val=sd->status.hair_color; break; //6 - case LOOK_CLOTHES_COLOR: val=sd->status.clothes_color; break; //7 - case LOOK_SHIELD: val=sd->status.shield; break; //8 - case LOOK_SHOES: break; //9 - } - - script_pushint(st,val); - return 0; +BUILDIN(getlook) +{ + int type,val; + TBL_PC *sd; + sd=script_rid2sd(st); + + type=script_getnum(st,2); + val=-1; + switch(type) { + case LOOK_HAIR: val=sd->status.hair; break; //1 + case LOOK_WEAPON: val=sd->status.weapon; break; //2 + case LOOK_HEAD_BOTTOM: val=sd->status.head_bottom; break; //3 + case LOOK_HEAD_TOP: val=sd->status.head_top; break; //4 + case LOOK_HEAD_MID: val=sd->status.head_mid; break; //5 + case LOOK_HAIR_COLOR: val=sd->status.hair_color; break; //6 + case LOOK_CLOTHES_COLOR:val=sd->status.clothes_color; break; //7 + case LOOK_SHIELD: val=sd->status.shield; break; //8 + case LOOK_SHOES: break; //9 + case LOOK_ROBE: val=sd->status.robe; break; //12 + } + + script_pushint(st,val); + return true; } /*========================================== * get char save point. argument: 0- map name, 1- x, 2- y *------------------------------------------*/ -BUILDIN_FUNC(getsavepoint) +BUILDIN(getsavepoint) { TBL_PC* sd; int type; - + sd = script_rid2sd(st); if (sd == NULL) { script_pushint(st,0); - return 0; + return true; } - + type = script_getnum(st,2); - + switch(type) { case 0: script_pushstrcopy(st,mapindex_id2name(sd->status.save_point.map)); break; case 1: script_pushint(st,sd->status.save_point.x); break; @@ -12985,69 +12652,69 @@ BUILDIN_FUNC(getsavepoint) script_pushint(st,0); break; } - return 0; + return true; } /*========================================== - * Get position for char/npc/pet/mob objects. Added by Lorky - * - * int getMapXY(MapName$,MapX,MapY,type,[CharName$]); - * where type: - * MapName$ - String variable for output map name - * MapX - Integer variable for output coord X - * MapY - Integer variable for output coord Y - * type - type of object - * 0 - Character coord - * 1 - NPC coord - * 2 - Pet coord - * 3 - Mob coord (not released) - * 4 - Homun coord - * 5 - Mercenary coord - * 6 - Elemental coord - * CharName$ - Name object. If miss or "this" the current object - * - * Return: - * 0 - success - * -1 - some error, MapName$,MapX,MapY contains unknown value. - *------------------------------------------*/ -BUILDIN_FUNC(getmapxy) + * Get position for char/npc/pet/mob objects. Added by Lorky + * + * int getMapXY(MapName$,MapX,MapY,type,[CharName$]); + * where type: + * MapName$ - String variable for output map name + * MapX - Integer variable for output coord X + * MapY - Integer variable for output coord Y + * type - type of object + * 0 - Character coord + * 1 - NPC coord + * 2 - Pet coord + * 3 - Mob coord (not released) + * 4 - Homun coord + * 5 - Mercenary coord + * 6 - Elemental coord + * CharName$ - Name object. If miss or "this" the current object + * + * Return: + * 0 - success + * -1 - some error, MapName$,MapX,MapY contains unknown value. + *------------------------------------------*/ +BUILDIN(getmapxy) { struct block_list *bl = NULL; TBL_PC *sd=NULL; - + int num; const char *name; char prefix; - + int x,y,type; char mapname[MAP_NAME_LENGTH]; - + if( !data_isreference(script_getdata(st,2)) ){ ShowWarning("script: buildin_getmapxy: not mapname variable\n"); script_pushint(st,-1); - return 1; + return false; } if( !data_isreference(script_getdata(st,3)) ){ ShowWarning("script: buildin_getmapxy: not mapx variable\n"); script_pushint(st,-1); - return 1; + return false; } if( !data_isreference(script_getdata(st,4)) ){ ShowWarning("script: buildin_getmapxy: not mapy variable\n"); script_pushint(st,-1); - return 1; + return false; } - + // Possible needly check function parameters on C_STR,C_INT,C_INT type=script_getnum(st,5); - + switch (type){ case 0: //Get Character Position if( script_hasdata(st,6) ) sd=map_nick2sd(script_getstr(st,6)); else sd=script_rid2sd(st); - + if (sd) bl = &sd->bl; break; @@ -13066,7 +12733,7 @@ BUILDIN_FUNC(getmapxy) sd=map_nick2sd(script_getstr(st,6)); else sd=script_rid2sd(st); - + if (sd && sd->pd) bl = &sd->pd->bl; break; @@ -13077,7 +12744,7 @@ BUILDIN_FUNC(getmapxy) sd=map_nick2sd(script_getstr(st,6)); else sd=script_rid2sd(st); - + if (sd && sd->hd) bl = &sd->hd->bl; break; @@ -13086,7 +12753,7 @@ BUILDIN_FUNC(getmapxy) sd=map_nick2sd(script_getstr(st,6)); else sd=script_rid2sd(st); - + if (sd && sd->md) bl = &sd->md->bl; break; @@ -13095,90 +12762,90 @@ BUILDIN_FUNC(getmapxy) sd=map_nick2sd(script_getstr(st,6)); else sd=script_rid2sd(st); - + if (sd && sd->ed) bl = &sd->ed->bl; break; default: ShowWarning("script: buildin_getmapxy: Invalid type %d\n", type); script_pushint(st,-1); - return 1; + return false; } if (!bl) { //No object found. script_pushint(st,-1); - return 0; + return true; } - + x= bl->x; y= bl->y; safestrncpy(mapname, map[bl->m].name, MAP_NAME_LENGTH); - + //Set MapName$ num=st->stack->stack_data[st->start+2].u.num; name=get_str(num&0x00ffffff); prefix=*name; - + if(not_server_variable(prefix)) sd=script_rid2sd(st); else sd=NULL; set_reg(st,sd,num,name,(void*)mapname,script_getref(st,2)); - + //Set MapX num=st->stack->stack_data[st->start+3].u.num; name=get_str(num&0x00ffffff); prefix=*name; - + if(not_server_variable(prefix)) sd=script_rid2sd(st); else sd=NULL; - set_reg(st,sd,num,name,(void*)__64BPRTSIZE(x),script_getref(st,3)); - + set_reg(st,sd,num,name,(void*)__64BPTRSIZE(x),script_getref(st,3)); + //Set MapY num=st->stack->stack_data[st->start+4].u.num; name=get_str(num&0x00ffffff); prefix=*name; - + if(not_server_variable(prefix)) sd=script_rid2sd(st); else sd=NULL; - set_reg(st,sd,num,name,(void*)__64BPRTSIZE(y),script_getref(st,4)); - + set_reg(st,sd,num,name,(void*)__64BPTRSIZE(y),script_getref(st,4)); + //Return Success value script_pushint(st,0); - return 0; + return true; } /*========================================== * Allows player to write NPC logs (i.e. Bank NPC, etc) [Lupus] *------------------------------------------*/ -BUILDIN_FUNC(logmes) +BUILDIN(logmes) { const char *str; TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 1; - + return false; + str = script_getstr(st,2); - log_npc(sd,str); - return 0; + logs->npc(sd,str); + return true; } -BUILDIN_FUNC(summon) +BUILDIN(summon) { int _class, timeout=0; const char *str,*event=""; TBL_PC *sd; struct mob_data *md; int tick = gettick(); - + sd=script_rid2sd(st); - if (!sd) return 0; - + if (!sd) return true; + str =script_getstr(st,2); _class=script_getnum(st,3); if( script_hasdata(st,4) ) @@ -13187,9 +12854,9 @@ BUILDIN_FUNC(summon) event=script_getstr(st,5); check_event(st, event); } - - clif_skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick); - + + clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick); + md = mob_once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, _class, event, SZ_SMALL, AI_NONE); if (md) { md->master_id=sd->bl.id; @@ -13198,48 +12865,48 @@ BUILDIN_FUNC(summon) delete_timer(md->deletetimer, mob_timer_delete); md->deletetimer = add_timer(tick+(timeout>0?timeout*1000:60000),mob_timer_delete,md->bl.id,0); mob_spawn (md); //Now it is ready for spawning. - clif_specialeffect(&md->bl,344,AREA); + clif->specialeffect(&md->bl,344,AREA); sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000); } - return 0; + return true; } /*========================================== * Checks whether it is daytime/nighttime *------------------------------------------*/ -BUILDIN_FUNC(isnight) +BUILDIN(isnight) { script_pushint(st,(night_flag == 1)); - return 0; + return true; } -BUILDIN_FUNC(isday) +BUILDIN(isday) { script_pushint(st,(night_flag == 0)); - return 0; + return true; } /*================================================ * Check how many items/cards in the list are * equipped - used for 2/15's cards patch [celest] *------------------------------------------------*/ -BUILDIN_FUNC(isequippedcnt) +BUILDIN(isequippedcnt) { TBL_PC *sd; int i, j, k, id = 1; int ret = 0; - + sd = script_rid2sd(st); if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... script_pushint(st,0); - return 0; + return true; } - + for (i=0; id!=0; i++) { FETCH (i+2, id) else id = 0; if (id <= 0) continue; - + for (j=0; j<EQI_MAX; j++) { int index; index = sd->equip_index[j]; @@ -13247,10 +12914,10 @@ BUILDIN_FUNC(isequippedcnt) if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; - + if(!sd->inventory_data[index]) continue; - + if (itemdb_type(id) != IT_CARD) { //No card. Count amount in inventory. if (sd->inventory_data[index]->nameid == id) ret+= sd->status.inventory[index].amount; @@ -13264,9 +12931,9 @@ BUILDIN_FUNC(isequippedcnt) } } } - + script_pushint(st,ret); - return 0; + return true; } /*================================================ @@ -13275,7 +12942,7 @@ BUILDIN_FUNC(isequippedcnt) * -- Items checked cannot be reused in another * card set to prevent exploits *------------------------------------------------*/ -BUILDIN_FUNC(isequipped) +BUILDIN(isequipped) { TBL_PC *sd; int i, j, k, id = 1; @@ -13283,14 +12950,14 @@ BUILDIN_FUNC(isequipped) int ret = -1; //Original hash to reverse it when full check fails. unsigned int setitem_hash = 0, setitem_hash2 = 0; - + sd = script_rid2sd(st); - + if (!sd) { //If the player is not attached it is a script error anyway... but better prevent the map server from crashing... script_pushint(st,0); - return 0; + return true; } - + setitem_hash = sd->bonus.setitem_hash; setitem_hash2 = sd->bonus.setitem_hash2; for (i=0; id!=0; i++) { @@ -13304,10 +12971,10 @@ BUILDIN_FUNC(isequipped) if(j == EQI_HAND_R && sd->equip_index[EQI_HAND_L] == index) continue; if(j == EQI_HEAD_MID && sd->equip_index[EQI_HEAD_LOW] == index) continue; if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == index || sd->equip_index[EQI_HEAD_LOW] == index)) continue; - + if(!sd->inventory_data[index]) continue; - + if (itemdb_type(id) != IT_CARD) { if (sd->inventory_data[index]->nameid != id) continue; @@ -13317,18 +12984,18 @@ BUILDIN_FUNC(isequipped) if (sd->inventory_data[index]->slot == 0 || itemdb_isspecial(sd->status.inventory[index].card[0])) continue; - + for (k = 0; k < sd->inventory_data[index]->slot; k++) { //New hash system which should support up to 4 slots on any equipment. [Skotlex] unsigned int hash = 0; if (sd->status.inventory[index].card[k] != id) continue; - + hash = 1<<((j<5?j:j-5)*4 + k); // check if card is already used by another set if ( ( j < 5 ? sd->bonus.setitem_hash : sd->bonus.setitem_hash2 ) & hash) continue; - + // We have found a match flag = 1; // Set hash so this card cannot be used by another @@ -13352,33 +13019,33 @@ BUILDIN_FUNC(isequipped) sd->bonus.setitem_hash2 = setitem_hash2; } script_pushint(st,ret); - return 0; + return true; } /*================================================ * Check how many given inserted cards in the CURRENT * weapon - used for 2/15's cards patch [Lupus] *------------------------------------------------*/ -BUILDIN_FUNC(cardscnt) +BUILDIN(cardscnt) { TBL_PC *sd; int i, k, id = 1; int ret = 0; int index; - + sd = script_rid2sd(st); - + for (i=0; id!=0; i++) { FETCH (i+2, id) else id = 0; if (id <= 0) continue; - + index = current_equip_item_index; //we get CURRENT WEAPON inventory index from status.c [Lupus] if(index < 0) continue; - + if(!sd->inventory_data[index]) continue; - + if(itemdb_type(id) != IT_CARD) { if (sd->inventory_data[index]->nameid == id) ret+= sd->status.inventory[index].amount; @@ -13392,47 +13059,47 @@ BUILDIN_FUNC(cardscnt) } } script_pushint(st,ret); -// script_pushint(st,current_equip_item_index); - return 0; + // script_pushint(st,current_equip_item_index); + return true; } /*======================================================= * Returns the refined number of the current item, or an * item with inventory index specified *-------------------------------------------------------*/ -BUILDIN_FUNC(getrefine) +BUILDIN(getrefine) { TBL_PC *sd; if ((sd = script_rid2sd(st))!= NULL) script_pushint(st,sd->status.inventory[current_equip_item_index].refine); else script_pushint(st,0); - return 0; + return true; } /*======================================================= * Day/Night controls *-------------------------------------------------------*/ -BUILDIN_FUNC(night) +BUILDIN(night) { if (night_flag != 1) map_night_timer(night_timer_tid, 0, 0, 1); - return 0; + return true; } -BUILDIN_FUNC(day) +BUILDIN(day) { if (night_flag != 0) map_day_timer(day_timer_tid, 0, 0, 1); - return 0; + return true; } //======================================================= // Unequip [Spectre] //------------------------------------------------------- -BUILDIN_FUNC(unequip) +BUILDIN(unequip) { int i; size_t num; TBL_PC *sd; - + num = script_getnum(st,2); sd = script_rid2sd(st); if( sd != NULL && num >= 1 && num <= ARRAYLENGTH(equip) ) @@ -13441,138 +13108,138 @@ BUILDIN_FUNC(unequip) if (i >= 0) pc_unequipitem(sd,i,1|2); } - return 0; + return true; } -BUILDIN_FUNC(equip) +BUILDIN(equip) { int nameid=0,i; TBL_PC *sd; struct item_data *item_data; - + sd = script_rid2sd(st); - + nameid=script_getnum(st,2); if((item_data = itemdb_exists(nameid)) == NULL) { ShowError("wrong item ID : equipitem(%i)\n",nameid); - return 1; + return false; } ARR_FIND( 0, MAX_INVENTORY, i, sd->status.inventory[i].nameid == nameid ); if( i < MAX_INVENTORY ) pc_equipitem(sd,i,item_data->equip); - - return 0; + + return true; } -BUILDIN_FUNC(autoequip) +BUILDIN(autoequip) { int nameid, flag; struct item_data *item_data; nameid=script_getnum(st,2); flag=script_getnum(st,3); - + if( ( item_data = itemdb_exists(nameid) ) == NULL ) { ShowError("buildin_autoequip: Invalid item '%d'.\n", nameid); - return 1; + return false; } - + if( !itemdb_isequip2(item_data) ) { ShowError("buildin_autoequip: Item '%d' cannot be equipped.\n", nameid); - return 1; + return false; } - + item_data->flag.autoequip = flag>0?1:0; - return 0; + return true; } -BUILDIN_FUNC(setbattleflag) +BUILDIN(setbattleflag) { const char *flag, *value; - + flag = script_getstr(st,2); value = script_getstr(st,3); // HACK: Retrieve number as string (auto-converted) for battle_set_value - - if (battle_set_value(flag, value) == 0) + + if (battle->config_set_value(flag, value) == 0) ShowWarning("buildin_setbattleflag: unknown battle_config flag '%s'\n",flag); else ShowInfo("buildin_setbattleflag: battle_config flag '%s' is now set to '%s'.\n",flag,value); - - return 0; + + return true; } -BUILDIN_FUNC(getbattleflag) +BUILDIN(getbattleflag) { const char *flag; flag = script_getstr(st,2); - script_pushint(st,battle_get_value(flag)); - return 0; + script_pushint(st,battle->config_get_value(flag)); + return true; } //======================================================= // strlen [Valaris] //------------------------------------------------------- -BUILDIN_FUNC(getstrlen) +BUILDIN(getstrlen) { - + const char *str = script_getstr(st,2); int len = (str) ? (int)strlen(str) : 0; - + script_pushint(st,len); - return 0; + return true; } //======================================================= // isalpha [Valaris] //------------------------------------------------------- -BUILDIN_FUNC(charisalpha) +BUILDIN(charisalpha) { const char *str=script_getstr(st,2); int pos=script_getnum(st,3); - + int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISALPHA( str[pos] ) != 0 : 0; - + script_pushint(st,val); - return 0; + return true; } //======================================================= // charisupper <str>, <index> //------------------------------------------------------- -BUILDIN_FUNC(charisupper) +BUILDIN(charisupper) { const char *str = script_getstr(st,2); int pos = script_getnum(st,3); - + int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISUPPER( str[pos] ) : 0; - + script_pushint(st,val); - return 0; + return true; } //======================================================= // charislower <str>, <index> //------------------------------------------------------- -BUILDIN_FUNC(charislower) +BUILDIN(charislower) { const char *str = script_getstr(st,2); int pos = script_getnum(st,3); - + int val = ( str && pos >= 0 && (unsigned int)pos < strlen(str) ) ? ISLOWER( str[pos] ) : 0; - + script_pushint(st,val); - return 0; + return true; } //======================================================= // charat <str>, <index> //------------------------------------------------------- -BUILDIN_FUNC(charat) { +BUILDIN(charat) { const char *str = script_getstr(st,2); int pos = script_getnum(st,3); - + if( pos >= 0 && (unsigned int)pos < strlen(str) ) { char output[2]; output[0] = str[pos]; @@ -13580,145 +13247,145 @@ BUILDIN_FUNC(charat) { script_pushstrcopy(st, output); } else script_pushconststr(st, ""); - return 0; + return true; } //======================================================= // setchar <string>, <char>, <index> //------------------------------------------------------- -BUILDIN_FUNC(setchar) +BUILDIN(setchar) { const char *str = script_getstr(st,2); const char *c = script_getstr(st,3); int index = script_getnum(st,4); char *output = aStrdup(str); - + if(index >= 0 && index < strlen(output)) output[index] = *c; - + script_pushstr(st, output); - return 0; + return true; } //======================================================= // insertchar <string>, <char>, <index> //------------------------------------------------------- -BUILDIN_FUNC(insertchar) +BUILDIN(insertchar) { const char *str = script_getstr(st,2); const char *c = script_getstr(st,3); int index = script_getnum(st,4); char *output; size_t len = strlen(str); - + if(index < 0) index = 0; else if(index > len) index = len; - + output = (char*)aMalloc(len + 2); - + memcpy(output, str, index); output[index] = c[0]; memcpy(&output[index+1], &str[index], len - index); output[len+1] = '\0'; - + script_pushstr(st, output); - return 0; + return true; } //======================================================= // delchar <string>, <index> //------------------------------------------------------- -BUILDIN_FUNC(delchar) +BUILDIN(delchar) { const char *str = script_getstr(st,2); int index = script_getnum(st,3); char *output; size_t len = strlen(str); - + if(index < 0 || index > len) { //return original output = aStrdup(str); script_pushstr(st, output); - return 0; + return true; } - + output = (char*)aMalloc(len); - + memcpy(output, str, index); memcpy(&output[index], &str[index+1], len - index); - + script_pushstr(st, output); - return 0; + return true; } //======================================================= // strtoupper <str> //------------------------------------------------------- -BUILDIN_FUNC(strtoupper) +BUILDIN(strtoupper) { const char *str = script_getstr(st,2); char *output = aStrdup(str); char *cursor = output; - + while (*cursor != '\0') { *cursor = TOUPPER(*cursor); cursor++; } - + script_pushstr(st, output); - return 0; + return true; } //======================================================= // strtolower <str> //------------------------------------------------------- -BUILDIN_FUNC(strtolower) +BUILDIN(strtolower) { const char *str = script_getstr(st,2); char *output = aStrdup(str); char *cursor = output; - + while (*cursor != '\0') { *cursor = TOLOWER(*cursor); cursor++; } - + script_pushstr(st, output); - return 0; + return true; } //======================================================= // substr <str>, <start>, <end> //------------------------------------------------------- -BUILDIN_FUNC(substr) +BUILDIN(substr) { const char *str = script_getstr(st,2); char *output; int start = script_getnum(st,3); int end = script_getnum(st,4); - + int len = 0; - + if(start >= 0 && end < strlen(str) && start <= end) { len = end - start + 1; output = (char*)aMalloc(len + 1); memcpy(output, &str[start], len); } else output = (char*)aMalloc(1); - + output[len] = '\0'; - + script_pushstr(st, output); - return 0; + return true; } //======================================================= // explode <dest_string_array>, <str>, <delimiter> // Note: delimiter is limited to 1 char //------------------------------------------------------- -BUILDIN_FUNC(explode) +BUILDIN(explode) { struct script_data* data = script_getdata(st, 2); const char *str = script_getstr(st,3); @@ -13727,50 +13394,50 @@ BUILDIN_FUNC(explode) size_t len = strlen(str); int i = 0, j = 0; int start; - - + + char *temp; const char* name; - + TBL_PC* sd = NULL; - + temp = (char*)aMalloc(len + 1); - + if( !data_isreference(data) ) { ShowError("script:explode: not a variable\n"); script_reportdata(data); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id = reference_getid(data); start = reference_getindex(data); name = reference_getname(data); - + if( not_array_variable(*name) ) { ShowError("script:explode: illegal scope\n"); script_reportdata(data); st->state = END; - return 1;// not supported + return false;// not supported } - + if( !is_string_variable(name) ) { ShowError("script:explode: not string array\n"); script_reportdata(data); st->state = END; - return 1;// data type mismatch + return false;// data type mismatch } - + if( not_server_variable(*name) ) { sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached + return true;// no player attached } - + while(str[i] != '\0') { if(str[i] == delimiter && start < SCRIPT_MAX_ARRAYSIZE-1) { //break at delimiter but ignore after reaching last array index temp[j] = '\0'; @@ -13784,64 +13451,64 @@ BUILDIN_FUNC(explode) //set last string temp[j] = '\0'; set_reg(st, sd, reference_uid(id, start), name, (void*)temp, reference_getref(data)); - + aFree(temp); - return 0; + return true; } //======================================================= // implode <string_array> // implode <string_array>, <glue> //------------------------------------------------------- -BUILDIN_FUNC(implode) +BUILDIN(implode) { struct script_data* data = script_getdata(st, 2); const char *glue = NULL, *name, *temp; int32 glue_len = 0, array_size, id; size_t len = 0; int i, k = 0; - + TBL_PC* sd = NULL; - + char *output; - + if( !data_isreference(data) ) { ShowError("script:implode: not a variable\n"); script_reportdata(data); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id = reference_getid(data); name = reference_getname(data); - + if( not_array_variable(*name) ) { ShowError("script:implode: illegal scope\n"); script_reportdata(data); st->state = END; - return 1;// not supported + return false;// not supported } - + if( !is_string_variable(name) ) { ShowError("script:implode: not string array\n"); script_reportdata(data); st->state = END; - return 1;// data type mismatch + return false;// data type mismatch } - + if( not_server_variable(*name) ) { sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached + return true;// no player attached } - + //count chars array_size = getarraysize(st, id, reference_getindex(data), is_string_variable(name), reference_getref(data)) - 1; - + if(array_size == -1) //empty array check (AmsTaff) { ShowWarning("script:implode: array length = 0\n"); @@ -13853,7 +13520,7 @@ BUILDIN_FUNC(implode) len += strlen(temp); script_removetop(st, -1, 0); } - + //allocate mem if( script_hasdata(st,3) ) { glue = script_getstr(st,3); @@ -13861,7 +13528,7 @@ BUILDIN_FUNC(implode) len += glue_len * (array_size); } output = (char*)aMalloc(len + 1); - + //build output for(i = 0; i < array_size; ++i) { temp = (char*) get_val2(st, reference_uid(id, i), reference_getref(data)); @@ -13879,12 +13546,12 @@ BUILDIN_FUNC(implode) memcpy(&output[k], temp, len); k += len; script_removetop(st, -1, 0); - + output[k] = '\0'; } - + script_pushstr(st, output); - return 0; + return true; } //======================================================= @@ -13892,7 +13559,7 @@ BUILDIN_FUNC(implode) // Implements C sprintf, except format %n. The resulting string is // returned, instead of being saved in variable by reference. //------------------------------------------------------- -BUILDIN_FUNC(sprintf) +BUILDIN(sprintf) { unsigned int len, argc = 0, arg = 0, buf2_len = 0; const char* format; @@ -13902,33 +13569,33 @@ BUILDIN_FUNC(sprintf) char* buf2 = NULL; struct script_data* data; StringBuf final_buf; - + // Fetch init data format = script_getstr(st, 2); argc = script_lastdata(st)-2; len = strlen(format); - + // Skip parsing, where no parsing is required. if(len==0){ script_pushconststr(st,""); - return 0; + return true; } - + // Pessimistic alloc CREATE(buf, char, len+1); - + // Need not be parsed, just solve stuff like %%. if(argc==0){ memcpy(buf,format,len+1); script_pushstrcopy(st, buf); aFree(buf); - return 0; + return true; } - + safestrncpy(buf, format, len+1); - + // Issue sprintf for each parameter - StringBuf_Init(&final_buf); + StrBuf->Init(&final_buf); q = buf; while((p = strchr(q, '%'))!=NULL){ if(p!=q){ @@ -13938,12 +13605,12 @@ BUILDIN_FUNC(sprintf) buf2_len = len; } safestrncpy(buf2, q, len); - StringBuf_AppendStr(&final_buf, buf2); + StrBuf->AppendStr(&final_buf, buf2); q = p; } p = q+1; if(*p=='%'){ // %% - StringBuf_AppendStr(&final_buf, "%"); + StrBuf->AppendStr(&final_buf, "%"); q+=2; continue; } @@ -13957,9 +13624,9 @@ BUILDIN_FUNC(sprintf) ShowError("buildin_sprintf: Not enough arguments passed!\n"); if(buf) aFree(buf); if(buf2) aFree(buf2); - StringBuf_Destroy(&final_buf); + StrBuf->Destroy(&final_buf); script_pushconststr(st,""); - return 1; + return false; } if((p = strchr(q+1, '%'))==NULL){ p = strchr(q, 0); // EOS @@ -13971,7 +13638,7 @@ BUILDIN_FUNC(sprintf) } safestrncpy(buf2, q, len); q = p; - + // Note: This assumes the passed value being the correct // type to the current format specifier. If not, the server // probably crashes or returns anything else, than expected, @@ -13979,52 +13646,52 @@ BUILDIN_FUNC(sprintf) // the scripter's responsibility. data = script_getdata(st, arg+3); if(data_isstring(data)){ // String - StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3)); + StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3)); }else if(data_isint(data)){ // Number - StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3)); + StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3)); }else if(data_isreference(data)){ // Variable char* name = reference_getname(data); if(name[strlen(name)-1]=='$'){ // var Str - StringBuf_Printf(&final_buf, buf2, script_getstr(st, arg+3)); + StrBuf->Printf(&final_buf, buf2, script_getstr(st, arg+3)); }else{ // var Int - StringBuf_Printf(&final_buf, buf2, script_getnum(st, arg+3)); + StrBuf->Printf(&final_buf, buf2, script_getnum(st, arg+3)); } }else{ // Unsupported type ShowError("buildin_sprintf: Unknown argument type!\n"); if(buf) aFree(buf); if(buf2) aFree(buf2); - StringBuf_Destroy(&final_buf); + StrBuf->Destroy(&final_buf); script_pushconststr(st,""); - return 1; + return false; } arg++; } - + // Append anything left if(*q){ - StringBuf_AppendStr(&final_buf, q); + StrBuf->AppendStr(&final_buf, q); } - + // Passed more, than needed if(arg<argc){ ShowWarning("buildin_sprintf: Unused arguments passed.\n"); script_reportsrc(st); } - - script_pushstrcopy(st, StringBuf_Value(&final_buf)); - + + script_pushstrcopy(st, StrBuf->Value(&final_buf)); + if(buf) aFree(buf); if(buf2) aFree(buf2); - StringBuf_Destroy(&final_buf); - - return 0; + StrBuf->Destroy(&final_buf); + + return true; } //======================================================= // sscanf(<str>, <format>, ...); // Implements C sscanf. //------------------------------------------------------- -BUILDIN_FUNC(sscanf){ +BUILDIN(sscanf){ unsigned int argc, arg = 0, len; struct script_data* data; struct map_session_data* sd = NULL; @@ -14036,15 +13703,15 @@ BUILDIN_FUNC(sscanf){ char* buf_p; char* ref_str = NULL; int ref_int; - + // Get data str = script_getstr(st, 2); format = script_getstr(st, 3); argc = script_lastdata(st)-3; - + len = strlen(format); CREATE(buf, char, len*2+1); - + // Issue sscanf for each parameter *buf = 0; q = format; @@ -14064,7 +13731,7 @@ BUILDIN_FUNC(sscanf){ script_pushint(st, -1); if(buf) aFree(buf); if(ref_str) aFree(ref_str); - return 1; + return false; } if((p = strchr(q+1, '%'))==NULL){ p = strchr(q, 0); // EOS @@ -14072,7 +13739,7 @@ BUILDIN_FUNC(sscanf){ len = p-q; strncat(buf, q, len); q = p; - + // Validate output data = script_getdata(st, arg+4); if(!data_isreference(data) || !reference_tovariable(data)){ @@ -14080,16 +13747,16 @@ BUILDIN_FUNC(sscanf){ script_pushint(st, -1); if(buf) aFree(buf); if(ref_str) aFree(ref_str); - return 1; + return false; } buf_p = reference_getname(data); if(not_server_variable(*buf_p) && (sd = script_rid2sd(st))==NULL){ script_pushint(st, -1); if(buf) aFree(buf); if(ref_str) aFree(ref_str); - return 0; + return true; } - + // Save value if any if(buf_p[strlen(buf_p)-1]=='$'){ // String if(ref_str==NULL){ @@ -14098,26 +13765,26 @@ BUILDIN_FUNC(sscanf){ if(sscanf(str, buf, ref_str)==0){ break; } - set_reg(st, sd, add_str(buf_p), buf_p, (void *)(ref_str), reference_getref(data)); - }else{ // Number + set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)(ref_str), reference_getref(data)); + } else { // Number if(sscanf(str, buf, &ref_int)==0){ break; } - set_reg(st, sd, add_str(buf_p), buf_p, (void *)__64BPRTSIZE(ref_int), reference_getref(data)); + set_reg(st, sd, reference_uid( reference_getid(data), reference_getindex(data) ), buf_p, (void *)__64BPTRSIZE(ref_int), reference_getref(data)); } arg++; - + // Disable used format (%... -> %*...) buf_p = strchr(buf, 0); memmove(buf_p-len+2, buf_p-len+1, len); *(buf_p-len+1) = '*'; } - + script_pushint(st, arg); if(buf) aFree(buf); if(ref_str) aFree(ref_str); - - return 0; + + return true; } //======================================================= @@ -14127,22 +13794,22 @@ BUILDIN_FUNC(sscanf){ // Implements PHP style strpos. Adapted from code from // http://www.daniweb.com/code/snippet313.html, Dave Sinkula //------------------------------------------------------- -BUILDIN_FUNC(strpos) { +BUILDIN(strpos) { const char *haystack = script_getstr(st,2); const char *needle = script_getstr(st,3); int i; size_t len; - + if( script_hasdata(st,4) ) i = script_getnum(st,4); else i = 0; - + if (needle[0] == '\0') { script_pushint(st, -1); - return 0; + return true; } - + len = strlen(haystack); for ( ; i < len; ++i ) { if ( haystack[i] == *needle ) { @@ -14155,12 +13822,12 @@ BUILDIN_FUNC(strpos) { } if ( !*n ) { // matched all of 'needle' to null termination script_pushint(st, i); - return 0; + return true; } } } script_pushint(st, -1); - return 0; + return true; } //=============================================================== @@ -14171,7 +13838,7 @@ BUILDIN_FUNC(strpos) { // instances as specified in <count>. By default will be case // sensitive. //--------------------------------------------------------------- -BUILDIN_FUNC(replacestr) +BUILDIN(replacestr) { const char *input = script_getstr(st, 2); const char *find = script_getstr(st, 3); @@ -14180,73 +13847,73 @@ BUILDIN_FUNC(replacestr) size_t findlen = strlen(find); struct StringBuf output; bool usecase = true; - + int count = 0; int numFinds = 0; int i = 0, f = 0; - + if(findlen == 0) { ShowError("script:replacestr: Invalid search length.\n"); st->state = END; - return 1; + return false; } - + if(script_hasdata(st, 5)) { if( !script_isstring(st,5) ) usecase = script_getnum(st, 5) != 0; else { ShowError("script:replacestr: Invalid usecase value. Expected int got string\n"); st->state = END; - return 1; + return false; } } - + if(script_hasdata(st, 6)) { count = script_getnum(st, 6); if(count == 0) { ShowError("script:replacestr: Invalid count value. Expected int got string\n"); st->state = END; - return 1; + return false; } } - - StringBuf_Init(&output); - + + StrBuf->Init(&output); + for(; i < inputlen; i++) { if(count && count == numFinds) { //found enough, stop looking break; } - + for(f = 0; f <= findlen; f++) { if(f == findlen) { //complete match numFinds++; - StringBuf_AppendStr(&output, replace); - + StrBuf->AppendStr(&output, replace); + i += findlen - 1; break; } else { if(usecase) { if((i + f) > inputlen || input[i + f] != find[f]) { - StringBuf_Printf(&output, "%c", input[i]); + StrBuf->Printf(&output, "%c", input[i]); break; } } else { if(((i + f) > inputlen || input[i + f] != find[f]) && TOUPPER(input[i+f]) != TOUPPER(find[f])) { - StringBuf_Printf(&output, "%c", input[i]); + StrBuf->Printf(&output, "%c", input[i]); break; } } } } } - + //append excess after enough found if(i < inputlen) - StringBuf_AppendStr(&output, &(input[i])); - - script_pushstrcopy(st, StringBuf_Value(&output)); - StringBuf_Destroy(&output); - return 0; + StrBuf->AppendStr(&output, &(input[i])); + + script_pushstrcopy(st, StrBuf->Value(&output)); + StrBuf->Destroy(&output); + return true; } //======================================================== @@ -14255,33 +13922,33 @@ BUILDIN_FUNC(replacestr) // Note: Counts the number of times <search> occurs in // <input>. By default will be case sensitive. //-------------------------------------------------------- -BUILDIN_FUNC(countstr) +BUILDIN(countstr) { const char *input = script_getstr(st, 2); const char *find = script_getstr(st, 3); size_t inputlen = strlen(input); size_t findlen = strlen(find); bool usecase = true; - + int numFinds = 0; int i = 0, f = 0; - + if(findlen == 0) { ShowError("script:countstr: Invalid search length.\n"); st->state = END; - return 1; + return false; } - + if(script_hasdata(st, 4)) { if( !script_isstring(st,4) ) usecase = script_getnum(st, 4) != 0; else { ShowError("script:countstr: Invalid usecase value. Expected int got string\n"); st->state = END; - return 1; + return false; } } - + for(; i < inputlen; i++) { for(f = 0; f <= findlen; f++) { if(f == findlen) { //complete match @@ -14302,7 +13969,7 @@ BUILDIN_FUNC(countstr) } } script_pushint(st, numFinds); - return 0; + return true; } @@ -14313,158 +13980,158 @@ BUILDIN_FUNC(countstr) /// setnpcdisplay("<npc name>", "<new display name>", <new class id>) -> <int> /// setnpcdisplay("<npc name>", "<new display name>") -> <int> /// setnpcdisplay("<npc name>", <new class id>) -> <int> -BUILDIN_FUNC(setnpcdisplay) +BUILDIN(setnpcdisplay) { const char* name; const char* newname = NULL; int class_ = -1, size = -1; struct script_data* data; struct npc_data* nd; - + name = script_getstr(st,2); data = script_getdata(st,3); - + if( script_hasdata(st,4) ) class_ = script_getnum(st,4); if( script_hasdata(st,5) ) size = script_getnum(st,5); - + get_val(st, data); if( data_isstring(data) ) - newname = conv_str(st,data); + newname = script->conv_str(st,data); else if( data_isint(data) ) - class_ = conv_num(st,data); + class_ = script->conv_num(st,data); else { ShowError("script:setnpcdisplay: expected a string or number\n"); script_reportdata(data); - return 1; + return false; } - + nd = npc_name2id(name); if( nd == NULL ) {// not found script_pushint(st,1); - return 0; + return true; } - + // update npc if( newname ) npc_setdisplayname(nd, newname); - + if( size != -1 && size != (int)nd->size ) nd->size = size; else size = -1; - + if( class_ != -1 && nd->class_ != class_ ) npc_setclass(nd, class_); else if( size != -1 ) { // Required to update the visual size - clif_clearunit_area(&nd->bl, CLR_OUTSIGHT); - clif_spawn(&nd->bl); + clif->clearunit_area(&nd->bl, CLR_OUTSIGHT); + clif->spawn(&nd->bl); } - + script_pushint(st,0); - return 0; + return true; } -BUILDIN_FUNC(atoi) +BUILDIN(atoi) { const char *value; value = script_getstr(st,2); script_pushint(st,atoi(value)); - return 0; + return true; } // case-insensitive substring search [lordalfa] -BUILDIN_FUNC(compare) +BUILDIN(compare) { const char *message; const char *cmpstring; message = script_getstr(st,2); cmpstring = script_getstr(st,3); script_pushint(st,(stristr(message,cmpstring) != NULL)); - return 0; + return true; } // [zBuffer] List of mathematics commands ---> -BUILDIN_FUNC(sqrt) +BUILDIN(sqrt) { double i, a; i = script_getnum(st,2); a = sqrt(i); script_pushint(st,(int)a); - return 0; + return true; } -BUILDIN_FUNC(pow) +BUILDIN(pow) { double i, a, b; a = script_getnum(st,2); b = script_getnum(st,3); i = pow(a,b); script_pushint(st,(int)i); - return 0; + return true; } -BUILDIN_FUNC(distance) +BUILDIN(distance) { int x0, y0, x1, y1; - + x0 = script_getnum(st,2); y0 = script_getnum(st,3); x1 = script_getnum(st,4); y1 = script_getnum(st,5); - + script_pushint(st,distance_xy(x0,y0,x1,y1)); - return 0; + return true; } // <--- [zBuffer] List of mathematics commands -BUILDIN_FUNC(md5) +BUILDIN(md5) { const char *tmpstr; char *md5str; - + tmpstr = script_getstr(st,2); md5str = (char *)aMalloc((32+1)*sizeof(char)); MD5_String(tmpstr, md5str); script_pushstr(st, md5str); - return 0; + return true; } // [zBuffer] List of dynamic var commands ---> -BUILDIN_FUNC(setd) +BUILDIN(setd) { TBL_PC *sd=NULL; char varname[100]; const char *buffer; int elem; buffer = script_getstr(st, 2); - + if(sscanf(buffer, "%99[^[][%d]", varname, &elem) < 2) elem = 0; - + if( not_server_variable(*varname) ) { sd = script_rid2sd(st); if( sd == NULL ) { ShowError("script:setd: no player attached for player variable '%s'\n", buffer); - return 0; + return true; } } - + if( is_string_variable(varname) ) { setd_sub(st, sd, varname, elem, (void *)script_getstr(st, 3), NULL); } else { - setd_sub(st, sd, varname, elem, (void *)__64BPRTSIZE(script_getnum(st, 3)), NULL); + setd_sub(st, sd, varname, elem, (void *)__64BPTRSIZE(script_getnum(st, 3)), NULL); } - - return 0; + + return true; } int buildin_query_sql_sub(struct script_state* st, Sql* handle) @@ -14477,7 +14144,7 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) int max_rows = SCRIPT_MAX_ARRAYSIZE; // maximum number of rows int num_vars; int num_cols; - + // check target variables for( i = 3; script_hasdata(st,i); ++i ) { data = script_getdata(st, i); @@ -14488,7 +14155,7 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) if( sd == NULL ) { // no player attached script_reportdata(data); st->state = END; - return 1; + return false; } } if( not_array_variable(*name) ) @@ -14497,28 +14164,28 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) ShowError("script:query_sql: not a variable\n"); script_reportdata(data); st->state = END; - return 1; + return false; } } num_vars = i - 3; - + // Execute the query query = script_getstr(st,2); - - if( SQL_ERROR == Sql_QueryStr(handle, query) ) { + + if( SQL_ERROR == SQL->QueryStr(handle, query) ) { Sql_ShowDebug(handle); script_pushint(st, 0); - return 1; + return false; } - - if( Sql_NumRows(handle) == 0 ) { // No data received - Sql_FreeResult(handle); + + if( SQL->NumRows(handle) == 0 ) { // No data received + SQL->FreeResult(handle); script_pushint(st, 0); - return 0; + return true; } - + // Count the number of columns to store - num_cols = Sql_NumColumns(handle); + num_cols = SQL->NumColumns(handle); if( num_vars < num_cols ) { ShowWarning("script:query_sql: Too many columns, discarding last %u columns.\n", (unsigned int)(num_cols-num_vars)); script_reportsrc(st); @@ -14526,105 +14193,82 @@ int buildin_query_sql_sub(struct script_state* st, Sql* handle) ShowWarning("script:query_sql: Too many variables (%u extra).\n", (unsigned int)(num_vars-num_cols)); script_reportsrc(st); } - + // Store data - for( i = 0; i < max_rows && SQL_SUCCESS == Sql_NextRow(handle); ++i ) { + for( i = 0; i < max_rows && SQL_SUCCESS == SQL->NextRow(handle); ++i ) { for( j = 0; j < num_vars; ++j ) { char* str = NULL; - + if( j < num_cols ) - Sql_GetData(handle, j, &str, NULL); - + SQL->GetData(handle, j, &str, NULL); + data = script_getdata(st, j+3); name = reference_getname(data); if( is_string_variable(name) ) setd_sub(st, sd, name, i, (void *)(str?str:""), reference_getref(data)); else - setd_sub(st, sd, name, i, (void *)__64BPRTSIZE((str?atoi(str):0)), reference_getref(data)); + setd_sub(st, sd, name, i, (void *)__64BPTRSIZE((str?atoi(str):0)), reference_getref(data)); } } - if( i == max_rows && max_rows < Sql_NumRows(handle) ) { - ShowWarning("script:query_sql: Only %d/%u rows have been stored.\n", max_rows, (unsigned int)Sql_NumRows(handle)); + if( i == max_rows && max_rows < SQL->NumRows(handle) ) { + ShowWarning("script:query_sql: Only %d/%u rows have been stored.\n", max_rows, (unsigned int)SQL->NumRows(handle)); script_reportsrc(st); } - + // Free data - Sql_FreeResult(handle); + SQL->FreeResult(handle); script_pushint(st, i); - - return 0; + + return true; } - -BUILDIN_FUNC(query_sql) { -#ifdef BETA_THREAD_TEST - if( st->state != RERUNLINE ) { - queryThread_add(st,false); - - st->state = RERUNLINE;/* will continue when the query is finished running. */ - } else - st->state = RUN; - - return 0; -#else +BUILDIN(query_sql) { return buildin_query_sql_sub(st, mmysql_handle); -#endif } -BUILDIN_FUNC(query_logsql) { - if( !log_config.sql_logs ) {// logmysql_handle == NULL +BUILDIN(query_logsql) { + if( !logs->config.sql_logs ) {// logmysql_handle == NULL ShowWarning("buildin_query_logsql: SQL logs are disabled, query '%s' will not be executed.\n", script_getstr(st,2)); script_pushint(st,-1); - return 1; + return false; } -#ifdef BETA_THREAD_TEST - if( st->state != RERUNLINE ) { - queryThread_add(st,true); - - st->state = RERUNLINE;/* will continue when the query is finished running. */ - } else - st->state = RUN; - - return 0; -#else return buildin_query_sql_sub(st, logmysql_handle); -#endif } //Allows escaping of a given string. -BUILDIN_FUNC(escape_sql) +BUILDIN(escape_sql) { const char *str; char *esc_str; size_t len; - + str = script_getstr(st,2); len = strlen(str); esc_str = (char*)aMalloc(len*2+1); - Sql_EscapeStringLen(mmysql_handle, esc_str, str, len); + SQL->EscapeStringLen(mmysql_handle, esc_str, str, len); script_pushstr(st, esc_str); - return 0; + return true; } -BUILDIN_FUNC(getd) +BUILDIN(getd) { char varname[100]; const char *buffer; int elem; - + buffer = script_getstr(st, 2); - + if(sscanf(buffer, "%[^[][%d]", varname, &elem) < 2) elem = 0; - + // Push the 'pointer' so it's more flexible [Lance] push_val(st->stack, C_NAME, reference_uid(add_str(varname), elem)); - - return 0; + + return true; } // <--- [zBuffer] List of dynamic var commands // Pet stat [Lance] -BUILDIN_FUNC(petstat) +BUILDIN(petstat) { TBL_PC *sd = NULL; struct pet_data *pd; @@ -14635,7 +14279,7 @@ BUILDIN_FUNC(petstat) script_pushconststr(st, ""); else script_pushint(st,0); - return 0; + return true; } pd = sd->pd; switch(flag){ @@ -14648,10 +14292,10 @@ BUILDIN_FUNC(petstat) script_pushint(st,0); break; } - return 0; + return true; } -BUILDIN_FUNC(callshop) +BUILDIN(callshop) { TBL_PC *sd = NULL; struct npc_data *nd; @@ -14660,7 +14304,7 @@ BUILDIN_FUNC(callshop) sd = script_rid2sd(st); if (!sd) { script_pushint(st,0); - return 0; + return true; } shopname = script_getstr(st, 2); if( script_hasdata(st,3) ) @@ -14670,45 +14314,45 @@ BUILDIN_FUNC(callshop) { ShowError("buildin_callshop: Shop [%s] not found (or NPC is not shop type)\n", shopname); script_pushint(st,0); - return 1; + return false; } - + if( nd->subtype == SHOP ) { // flag the user as using a valid script call for opening the shop (for floating NPCs) sd->state.callshop = 1; - + switch( flag ) { case 1: npc_buysellsel(sd,nd->bl.id,0); break; //Buy window case 2: npc_buysellsel(sd,nd->bl.id,1); break; //Sell window - default: clif_npcbuysell(sd,nd->bl.id); break; //Show menu + default: clif->npcbuysell(sd,nd->bl.id); break; //Show menu } } else - clif_cashshop_show(sd, nd); - + clif->cashshop_show(sd, nd); + sd->npc_shopid = nd->bl.id; script_pushint(st,1); - return 0; + return true; } -BUILDIN_FUNC(npcshopitem) +BUILDIN(npcshopitem) { const char* npcname = script_getstr(st, 2); struct npc_data* nd = npc_name2id(npcname); int n, i; int amount; - + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) { //Not found. script_pushint(st,0); - return 0; + return true; } - + // get the count of new entries amount = (script_lastdata(st)-2)/2; - + // generate new shop item list RECREATE(nd->u.shop.shop_item, struct npc_item_list, amount); for( n = 0, i = 3; n < amount; n++, i+=2 ) @@ -14717,27 +14361,27 @@ BUILDIN_FUNC(npcshopitem) nd->u.shop.shop_item[n].value = script_getnum(st,i+1); } nd->u.shop.count = n; - + script_pushint(st,1); - return 0; + return true; } -BUILDIN_FUNC(npcshopadditem) +BUILDIN(npcshopadditem) { const char* npcname = script_getstr(st,2); struct npc_data* nd = npc_name2id(npcname); int n, i; int amount; - + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) { //Not found. script_pushint(st,0); - return 0; + return true; } - + // get the count of new entries amount = (script_lastdata(st)-2)/2; - + // append new items to existing shop item list RECREATE(nd->u.shop.shop_item, struct npc_item_list, nd->u.shop.count+amount); for( n = nd->u.shop.count, i = 3; n < nd->u.shop.count+amount; n++, i+=2 ) @@ -14746,12 +14390,12 @@ BUILDIN_FUNC(npcshopadditem) nd->u.shop.shop_item[n].value = script_getnum(st,i+1); } nd->u.shop.count = n; - + script_pushint(st,1); - return 0; + return true; } -BUILDIN_FUNC(npcshopdelitem) +BUILDIN(npcshopdelitem) { const char* npcname = script_getstr(st,2); struct npc_data* nd = npc_name2id(npcname); @@ -14759,21 +14403,21 @@ BUILDIN_FUNC(npcshopdelitem) int n, i; int amount; int size; - + if( !nd || ( nd->subtype != SHOP && nd->subtype != CASHSHOP ) ) { //Not found. script_pushint(st,0); - return 0; + return true; } - + amount = script_lastdata(st)-2; size = nd->u.shop.count; - + // remove specified items from the shop item list for( i = 3; i < 3 + amount; i++ ) { nameid = script_getnum(st,i); - + ARR_FIND( 0, size, n, nd->u.shop.shop_item[n].nameid == nameid ); if( n < size ) { @@ -14781,121 +14425,121 @@ BUILDIN_FUNC(npcshopdelitem) size--; } } - + RECREATE(nd->u.shop.shop_item, struct npc_item_list, size); nd->u.shop.count = size; - + script_pushint(st,1); - return 0; + return true; } //Sets a script to attach to a shop npc. -BUILDIN_FUNC(npcshopattach) +BUILDIN(npcshopattach) { const char* npcname = script_getstr(st,2); struct npc_data* nd = npc_name2id(npcname); int flag = 1; - + if( script_hasdata(st,3) ) flag = script_getnum(st,3); - + if( !nd || nd->subtype != SHOP ) { //Not found. script_pushint(st,0); - return 0; + return true; } - + if (flag) nd->master_nd = ((struct npc_data *)map_id2bl(st->oid)); else nd->master_nd = NULL; - + script_pushint(st,1); - return 0; + return true; } /*========================================== * Returns some values of an item [Lupus] * Price, Weight, etc... - setitemscript(itemID,"{new item bonus script}",[n]); - Where n: - 0 - script - 1 - Equip script - 2 - Unequip script + setitemscript(itemID,"{new item bonus script}",[n]); + Where n: + 0 - script + 1 - Equip script + 2 - Unequip script *------------------------------------------*/ -BUILDIN_FUNC(setitemscript) +BUILDIN(setitemscript) { int item_id,n=0; - const char *script; + const char *new_bonus_script; struct item_data *i_data; struct script_code **dstscript; - + item_id = script_getnum(st,2); - script = script_getstr(st,3); + new_bonus_script = script_getstr(st,3); if( script_hasdata(st,4) ) n=script_getnum(st,4); i_data = itemdb_exists(item_id); - - if (!i_data || script==NULL || ( script[0] && script[0]!='{' )) { + + if (!i_data || new_bonus_script==NULL || ( new_bonus_script[0] && new_bonus_script[0]!='{' )) { script_pushint(st,0); - return 0; + return true; } switch (n) { - case 2: - dstscript = &i_data->unequip_script; - break; - case 1: - dstscript = &i_data->equip_script; - break; - default: - dstscript = &i_data->script; - break; + case 2: + dstscript = &i_data->unequip_script; + break; + case 1: + dstscript = &i_data->equip_script; + break; + default: + dstscript = &i_data->script; + break; } if(*dstscript) script_free_code(*dstscript); - - *dstscript = script[0] ? parse_script(script, "script_setitemscript", 0, 0) : NULL; + + *dstscript = new_bonus_script[0] ? parse_script(new_bonus_script, "script_setitemscript", 0, 0) : NULL; script_pushint(st,1); - return 0; + return true; } /* Work In Progress [Lupus] -BUILDIN_FUNC(addmonsterdrop) -{ - int class_,item_id,chance; - class_=script_getnum(st,2); - item_id=script_getnum(st,3); - chance=script_getnum(st,4); - if(class_>1000 && item_id>500 && chance>0) { - script_pushint(st,1); - } else { - script_pushint(st,0); - } -} - -BUILDIN_FUNC(delmonsterdrop) -{ - int class_,item_id; - class_=script_getnum(st,2); - item_id=script_getnum(st,3); - if(class_>1000 && item_id>500) { - script_pushint(st,1); - } else { - script_pushint(st,0); - } -} -*/ + BUILDIN(addmonsterdrop) + { + int class_,item_id,chance; + class_=script_getnum(st,2); + item_id=script_getnum(st,3); + chance=script_getnum(st,4); + if(class_>1000 && item_id>500 && chance>0) { + script_pushint(st,1); + } else { + script_pushint(st,0); + } + } + + BUILDIN(delmonsterdrop) + { + int class_,item_id; + class_=script_getnum(st,2); + item_id=script_getnum(st,3); + if(class_>1000 && item_id>500) { + script_pushint(st,1); + } else { + script_pushint(st,0); + } + } + */ /*========================================== * Returns some values of a monster [Lupus] * Name, Level, race, size, etc... - getmonsterinfo(monsterID,queryIndex); + getmonsterinfo(monsterID,queryIndex); *------------------------------------------*/ -BUILDIN_FUNC(getmonsterinfo) +BUILDIN(getmonsterinfo) { struct mob_db *mob; int mob_id; - + mob_id = script_getnum(st,2); if (!mobdb_checkid(mob_id)) { ShowError("buildin_getmonsterinfo: Wrong Monster ID: %i\n", mob_id); @@ -14932,77 +14576,94 @@ BUILDIN_FUNC(getmonsterinfo) case 22: script_pushint(st,mob->mexp); break; default: script_pushint(st,-1); //wrong Index } - return 0; + return true; } -BUILDIN_FUNC(checkvending) // check vending [Nab4] +BUILDIN(checkvending) // check vending [Nab4] { TBL_PC *sd = NULL; - + if(script_hasdata(st,2)) sd = map_nick2sd(script_getstr(st,2)); else sd = script_rid2sd(st); - + if(sd) script_pushint(st, sd->state.autotrade ? 2 : sd->state.vending); else script_pushint(st,0); - - return 0; + + return true; } -BUILDIN_FUNC(checkchatting) // check chatting [Marka] +BUILDIN(checkchatting) // check chatting [Marka] { TBL_PC *sd = NULL; - + if(script_hasdata(st,2)) sd = map_nick2sd(script_getstr(st,2)); else sd = script_rid2sd(st); - + if(sd) script_pushint(st,(sd->chatID != 0)); else script_pushint(st,0); + + return true; +} - return 0; +BUILDIN(checkidle) +{ + TBL_PC *sd = NULL; + + if (script_hasdata(st, 2)) + sd = map_nick2sd(script_getstr(st, 2)); + else + sd = script_rid2sd(st); + + if (sd) + script_pushint(st, DIFF_TICK(last_tick, sd->idletime)); + else + script_pushint(st, 0); + + return true; } -BUILDIN_FUNC(searchitem) +BUILDIN(searchitem) { struct script_data* data = script_getdata(st, 2); const char *itemname = script_getstr(st,3); struct item_data *items[MAX_SEARCH]; int count; - + char* name; int32 start; int32 id; int32 i; TBL_PC* sd = NULL; - + if ((items[0] = itemdb_exists(atoi(itemname)))) count = 1; else { count = itemdb_searchname_array(items, ARRAYLENGTH(items), itemname); if (count > MAX_SEARCH) count = MAX_SEARCH; } - + if (!count) { script_pushint(st, 0); - return 0; + return true; } - + if( !data_isreference(data) ) { ShowError("script:searchitem: not a variable\n"); script_reportdata(data); st->state = END; - return 1;// not a variable + return false;// not a variable } - + id = reference_getid(data); start = reference_getindex(data); name = reference_getname(data); @@ -15011,32 +14672,32 @@ BUILDIN_FUNC(searchitem) ShowError("script:searchitem: illegal scope\n"); script_reportdata(data); st->state = END; - return 1;// not supported + return false;// not supported } - + if( not_server_variable(*name) ) { sd = script_rid2sd(st); if( sd == NULL ) - return 0;// no player attached + return true;// no player attached } - + if( is_string_variable(name) ) {// string array ShowError("script:searchitem: not an integer array reference\n"); script_reportdata(data); st->state = END; - return 1;// not supported + return false;// not supported } - + for( i = 0; i < count; ++start, ++i ) {// Set array - void* v = (void*)__64BPRTSIZE((int)items[i]->nameid); + void* v = (void*)__64BPTRSIZE((int)items[i]->nameid); set_reg(st, sd, reference_uid(id, start), name, v, reference_getref(data)); } - + script_pushint(st, count); - return 0; + return true; } int axtoi(const char *hexStg) @@ -15073,15 +14734,15 @@ int axtoi(const char *hexStg) } // [Lance] Hex string to integer converter -BUILDIN_FUNC(axtoi) +BUILDIN(axtoi) { const char *hex = script_getstr(st,2); script_pushint(st,axtoi(hex)); - return 0; + return true; } // [zBuffer] List of player cont commands ---> -BUILDIN_FUNC(rid2name) +BUILDIN(rid2name) { struct block_list *bl = NULL; int rid = script_getnum(st,2); @@ -15103,65 +14764,65 @@ BUILDIN_FUNC(rid2name) ShowError("buildin_rid2name: invalid RID\n"); script_pushconststr(st,"(null)"); } - return 0; + return true; } -BUILDIN_FUNC(pcblockmove) +BUILDIN(pcblockmove) { int id, flag; TBL_PC *sd = NULL; - + id = script_getnum(st,2); flag = script_getnum(st,3); - + if(id) sd = map_id2sd(id); else sd = script_rid2sd(st); - + if(sd) sd->state.blockedmove = flag > 0; - - return 0; + + return true; } -BUILDIN_FUNC(pcfollow) +BUILDIN(pcfollow) { int id, targetid; TBL_PC *sd = NULL; - - + + id = script_getnum(st,2); targetid = script_getnum(st,3); - + if(id) sd = map_id2sd(id); else sd = script_rid2sd(st); - + if(sd) pc_follow(sd, targetid); - - return 0; + + return true; } -BUILDIN_FUNC(pcstopfollow) +BUILDIN(pcstopfollow) { int id; TBL_PC *sd = NULL; - - + + id = script_getnum(st,2); - + if(id) sd = map_id2sd(id); else sd = script_rid2sd(st); - + if(sd) pc_stop_following(sd); - - return 0; + + return true; } // <--- [zBuffer] List of player cont commands // [zBuffer] List of mob control commands ---> @@ -15172,10 +14833,10 @@ BUILDIN_FUNC(pcstopfollow) /// /// unitwalk(<unit_id>,<x>,<y>) -> <bool> /// unitwalk(<unit_id>,<map_id>) -> <bool> -BUILDIN_FUNC(unitwalk) +BUILDIN(unitwalk) { struct block_list* bl; - + bl = map_id2bl(script_getnum(st,2)); if( bl == NULL ) { @@ -15192,27 +14853,27 @@ BUILDIN_FUNC(unitwalk) int map_id = script_getnum(st,3); script_pushint(st, unit_walktobl(bl,map_id2bl(map_id),65025,1)); } - - return 0; + + return true; } /// Kills the unit /// /// unitkill <unit_id>; -BUILDIN_FUNC(unitkill) +BUILDIN(unitkill) { struct block_list* bl = map_id2bl(script_getnum(st,2)); if( bl != NULL ) status_kill(bl); - - return 0; + + return true; } /// Warps the unit to the target position in the target map /// Returns if it was successfull /// /// unitwarp(<unit_id>,"<map name>",<x>,<y>) -> <bool> -BUILDIN_FUNC(unitwarp) +BUILDIN(unitwarp) { int unit_id; int map; @@ -15220,28 +14881,28 @@ BUILDIN_FUNC(unitwarp) short y; struct block_list* bl; const char *mapname; - + unit_id = script_getnum(st,2); mapname = script_getstr(st, 3); x = (short)script_getnum(st,4); y = (short)script_getnum(st,5); - + if (!unit_id) //Warp the script's runner bl = map_id2bl(st->rid); else bl = map_id2bl(unit_id); - + if( strcmp(mapname,"this") == 0 ) map = bl?bl->m:-1; else map = map_mapname2mapid(mapname); - + if( map >= 0 && bl != NULL ) script_pushint(st, unit_warp(bl,map,x,y,CLR_OUTSIGHT)); else script_pushint(st, 0); - - return 0; + + return true; } /// Makes the unit attack the target. @@ -15251,71 +14912,71 @@ BUILDIN_FUNC(unitwarp) /// /// unitattack(<unit_id>,"<target name>"{,<action type>}) -> <bool> /// unitattack(<unit_id>,<target_id>{,<action type>}) -> <bool> -BUILDIN_FUNC(unitattack) +BUILDIN(unitattack) { struct block_list* unit_bl; struct block_list* target_bl = NULL; struct script_data* data; int actiontype = 0; - + // get unit unit_bl = map_id2bl(script_getnum(st,2)); if( unit_bl == NULL ) { script_pushint(st, 0); - return 0; + return true; } - + data = script_getdata(st, 3); get_val(st, data); if( data_isstring(data) ) { - TBL_PC* sd = map_nick2sd(conv_str(st, data)); + TBL_PC* sd = map_nick2sd(script->conv_str(st, data)); if( sd != NULL ) target_bl = &sd->bl; } else - target_bl = map_id2bl(conv_num(st, data)); + target_bl = map_id2bl(script->conv_num(st, data)); // request the attack if( target_bl == NULL ) { script_pushint(st, 0); - return 0; + return true; } - + // get actiontype if( script_hasdata(st,4) ) actiontype = script_getnum(st,4); - + switch( unit_bl->type ) { - case BL_PC: - clif_parse_ActionRequest_sub(((TBL_PC *)unit_bl), actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick()); - script_pushint(st, 1); - return 0; - case BL_MOB: - ((TBL_MOB *)unit_bl)->target_id = target_bl->id; - break; - case BL_PET: - ((TBL_PET *)unit_bl)->target_id = target_bl->id; - break; - default: - ShowError("script:unitattack: unsupported source unit type %d\n", unit_bl->type); - script_pushint(st, 0); - return 1; + case BL_PC: + clif->pActionRequest_sub(((TBL_PC *)unit_bl), actiontype > 0 ? 0x07 : 0x00, target_bl->id, gettick()); + script_pushint(st, 1); + return true; + case BL_MOB: + ((TBL_MOB *)unit_bl)->target_id = target_bl->id; + break; + case BL_PET: + ((TBL_PET *)unit_bl)->target_id = target_bl->id; + break; + default: + ShowError("script:unitattack: unsupported source unit type %d\n", unit_bl->type); + script_pushint(st, 0); + return false; } script_pushint(st, unit_walktobl(unit_bl, target_bl, 65025, 2)); - return 0; + return true; } /// Makes the unit stop attacking and moving /// /// unitstop <unit_id>; -BUILDIN_FUNC(unitstop) +BUILDIN(unitstop) { int unit_id; struct block_list* bl; - + unit_id = script_getnum(st,2); - + bl = map_id2bl(unit_id); if( bl != NULL ) { @@ -15324,35 +14985,35 @@ BUILDIN_FUNC(unitstop) if( bl->type == BL_MOB ) ((TBL_MOB*)bl)->target_id = 0; } - - return 0; + + return true; } /// Makes the unit say the message /// /// unittalk <unit_id>,"<message>"; -BUILDIN_FUNC(unittalk) +BUILDIN(unittalk) { int unit_id; const char* message; struct block_list* bl; - + unit_id = script_getnum(st,2); message = script_getstr(st, 3); - + bl = map_id2bl(unit_id); if( bl != NULL ) { struct StringBuf sbuf; - StringBuf_Init(&sbuf); - StringBuf_Printf(&sbuf, "%s : %s", status_get_name(bl), message); - clif_message(bl, StringBuf_Value(&sbuf)); + StrBuf->Init(&sbuf); + StrBuf->Printf(&sbuf, "%s : %s", status_get_name(bl), message); + clif->disp_overhead(bl, StrBuf->Value(&sbuf)); if( bl->type == BL_PC ) - clif_displaymessage(((TBL_PC*)bl)->fd, StringBuf_Value(&sbuf)); - StringBuf_Destroy(&sbuf); + clif->message(((TBL_PC*)bl)->fd, StrBuf->Value(&sbuf)); + StrBuf->Destroy(&sbuf); } - - return 0; + + return true; } /// Makes the unit do an emotion @@ -15360,50 +15021,50 @@ BUILDIN_FUNC(unittalk) /// unitemote <unit_id>,<emotion>; /// /// @see e_* in const.txt -BUILDIN_FUNC(unitemote) +BUILDIN(unitemote) { int unit_id; int emotion; struct block_list* bl; - + unit_id = script_getnum(st,2); emotion = script_getnum(st,3); bl = map_id2bl(unit_id); if( bl != NULL ) - clif_emotion(bl, emotion); - - return 0; + clif->emotion(bl, emotion); + + return true; } /// Makes the unit cast the skill on the target or self if no target is specified /// /// unitskilluseid <unit_id>,<skill_id>,<skill_lv>{,<target_id>}; /// unitskilluseid <unit_id>,"<skill name>",<skill_lv>{,<target_id>}; -BUILDIN_FUNC(unitskilluseid) +BUILDIN(unitskilluseid) { int unit_id; uint16 skill_id; uint16 skill_lv; int target_id; struct block_list* bl; - + unit_id = script_getnum(st,2); - skill_id = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); + skill_id = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) ); skill_lv = script_getnum(st,4); target_id = ( script_hasdata(st,5) ? script_getnum(st,5) : unit_id ); - + bl = map_id2bl(unit_id); if( bl != NULL ) unit_skilluse_id(bl, target_id, skill_id, skill_lv); - - return 0; + + return true; } /// Makes the unit cast the skill on the target position. /// /// unitskillusepos <unit_id>,<skill_id>,<skill_lv>,<target_x>,<target_y>; /// unitskillusepos <unit_id>,"<skill name>",<skill_lv>,<target_x>,<target_y>; -BUILDIN_FUNC(unitskillusepos) +BUILDIN(unitskillusepos) { int unit_id; uint16 skill_id; @@ -15411,18 +15072,18 @@ BUILDIN_FUNC(unitskillusepos) int skill_x; int skill_y; struct block_list* bl; - + unit_id = script_getnum(st,2); - skill_id = ( script_isstring(st,3) ? skill_name2id(script_getstr(st,3)) : script_getnum(st,3) ); + skill_id = ( script_isstring(st,3) ? skill->name2id(script_getstr(st,3)) : script_getnum(st,3) ); skill_lv = script_getnum(st,4); skill_x = script_getnum(st,5); skill_y = script_getnum(st,6); - + bl = map_id2bl(unit_id); if( bl != NULL ) unit_skilluse_pos(bl, skill_x, skill_y, skill_id, skill_lv); - - return 0; + + return true; } // <--- [zBuffer] List of mob control commands @@ -15430,15 +15091,15 @@ BUILDIN_FUNC(unitskillusepos) /// Pauses the execution of the script, detaching the player /// /// sleep <mili seconds>; -BUILDIN_FUNC(sleep) +BUILDIN(sleep) { int ticks; - + ticks = script_getnum(st,2); - + // detach the player script_detach_rid(st); - + if( ticks <= 0 ) {// do nothing } @@ -15452,19 +15113,19 @@ BUILDIN_FUNC(sleep) st->state = RUN; st->sleep.tick = 0; } - return 0; + return true; } /// Pauses the execution of the script, keeping the player attached /// Returns if a player is still attached /// /// sleep2(<mili secconds>) -> <bool> -BUILDIN_FUNC(sleep2) +BUILDIN(sleep2) { int ticks; - + ticks = script_getnum(st,2); - + if( ticks <= 0 ) {// do nothing script_pushint(st, (map_id2sd(st->rid)!=NULL)); @@ -15480,30 +15141,30 @@ BUILDIN_FUNC(sleep2) st->sleep.tick = 0; script_pushint(st, (map_id2sd(st->rid)!=NULL)); } - return 0; + return true; } /// Awakes all the sleep timers of the target npc /// /// awake "<npc name>"; -BUILDIN_FUNC(awake) +BUILDIN(awake) { struct npc_data* nd; struct linkdb_node *node = (struct linkdb_node *)sleep_db; - + nd = npc_name2id(script_getstr(st, 2)); if( nd == NULL ) { ShowError("awake: NPC \"%s\" not found\n", script_getstr(st, 2)); - return 1; + return false; } - + while( node ) { - if( (int)__64BPRTSIZE(node->key) == nd->bl.id ) + if( (int)__64BPTRSIZE(node->key) == nd->bl.id ) {// sleep timer for the npc struct script_state* tst = (struct script_state*)node->data; TBL_PC* sd = map_id2sd(tst->rid); - + if( tst->sleep.timer == INVALID_TIMER ) {// already awake ??? node = node->next; @@ -15514,7 +15175,7 @@ BUILDIN_FUNC(awake) tst->state = END; tst->rid = 0; } - + delete_timer(tst->sleep.timer, run_script_timer); node = script_erase_sleepdb(node); tst->sleep.timer = INVALID_TIMER; @@ -15527,19 +15188,19 @@ BUILDIN_FUNC(awake) node = node->next; } } - return 0; + return true; } /// Returns a reference to a variable of the target NPC. /// Returns 0 if an error occurs. /// /// getvariableofnpc(<variable>, "<npc name>") -> <reference> -BUILDIN_FUNC(getvariableofnpc) +BUILDIN(getvariableofnpc) { struct script_data* data; const char* name; struct npc_data* nd; - + data = script_getdata(st,2); if( !data_isreference(data) ) {// Not a reference (aka varaible name) @@ -15547,9 +15208,9 @@ BUILDIN_FUNC(getvariableofnpc) script_reportdata(data); script_pushnil(st); st->state = END; - return 1; + return false; } - + name = reference_getname(data); if( *name != '.' || name[1] == '@' ) {// not a npc variable @@ -15557,20 +15218,20 @@ BUILDIN_FUNC(getvariableofnpc) script_reportdata(data); script_pushnil(st); st->state = END; - return 1; + return false; } - + nd = npc_name2id(script_getstr(st,3)); if( nd == NULL || nd->subtype != SCRIPT || nd->u.scr.script == NULL ) {// NPC not found or has no script ShowError("script:getvariableofnpc: can't find npc %s\n", script_getstr(st,3)); script_pushnil(st); st->state = END; - return 1; + return false; } - + push_val2(st->stack, C_NAME, reference_getuid(data), &nd->u.scr.script->script_vars ); - return 0; + return true; } /// Opens a warp portal. @@ -15579,7 +15240,7 @@ BUILDIN_FUNC(getvariableofnpc) /// warpportal <source x>,<source y>,"<target map>",<target x>,<target y>; /// /// @author blackhole89 -BUILDIN_FUNC(warpportal) +BUILDIN(warpportal) { int spx; int spy; @@ -15588,56 +15249,57 @@ BUILDIN_FUNC(warpportal) int tpy; struct skill_unit_group* group; struct block_list* bl; - + bl = map_id2bl(st->oid); if( bl == NULL ) { ShowError("script:warpportal: npc is needed\n"); - return 1; + return false; } - + spx = script_getnum(st,2); spy = script_getnum(st,3); mapindex = mapindex_name2id(script_getstr(st, 4)); tpx = script_getnum(st,5); tpy = script_getnum(st,6); - + if( mapindex == 0 ) - return 0;// map not found - - group = skill_unitsetting(bl, AL_WARP, 4, spx, spy, 0); + return true;// map not found + + group = skill->unitsetting(bl, AL_WARP, 4, spx, spy, 0); if( group == NULL ) - return 0;// failed + return true;// failed + group->val1 = (group->val1<<16)|(short)0; group->val2 = (tpx<<16) | tpy; group->val3 = mapindex; - - return 0; + + return true; } -BUILDIN_FUNC(openmail) +BUILDIN(openmail) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - + return true; + mail_openmail(sd); - - return 0; + + return true; } -BUILDIN_FUNC(openauction) +BUILDIN(openauction) { TBL_PC* sd; - + sd = script_rid2sd(st); if( sd == NULL ) - return 0; - - clif_Auction_openwindow(sd); - - return 0; + return true; + + clif->auction_openwindow(sd); + + return true; } /// Retrieves the value of the specified flag of the specified cell. @@ -15645,16 +15307,16 @@ BUILDIN_FUNC(openauction) /// checkcell("<map name>",<x>,<y>,<type>) -> <bool> /// /// @see cell_chk* constants in const.txt for the types -BUILDIN_FUNC(checkcell) +BUILDIN(checkcell) { int16 m = map_mapname2mapid(script_getstr(st,2)); int16 x = script_getnum(st,3); int16 y = script_getnum(st,4); cell_chk type = (cell_chk)script_getnum(st,5); - + script_pushint(st, map_getcell(m, x, y, type)); - - return 0; + + return true; } /// Modifies flags of cells in the specified area. @@ -15662,7 +15324,7 @@ BUILDIN_FUNC(checkcell) /// setcell "<map name>",<x1>,<y1>,<x2>,<y2>,<type>,<flag>; /// /// @see cell_* constants in const.txt for the types -BUILDIN_FUNC(setcell) +BUILDIN(setcell) { int16 m = map_mapname2mapid(script_getstr(st,2)); int16 x1 = script_getnum(st,3); @@ -15671,79 +15333,79 @@ BUILDIN_FUNC(setcell) int16 y2 = script_getnum(st,6); cell_t type = (cell_t)script_getnum(st,7); bool flag = (bool)script_getnum(st,8); - + int x,y; - + if( x1 > x2 ) swap(x1,x2); if( y1 > y2 ) swap(y1,y2); - + for( y = y1; y <= y2; ++y ) for( x = x1; x <= x2; ++x ) map_setcell(m, x, y, type, flag); - - return 0; + + return true; } /*========================================== * Mercenary Commands *------------------------------------------*/ -BUILDIN_FUNC(mercenary_create) +BUILDIN(mercenary_create) { struct map_session_data *sd; int class_, contract_time; - + if( (sd = script_rid2sd(st)) == NULL || sd->md || sd->status.mer_id != 0 ) - return 0; - + return true; + class_ = script_getnum(st,2); - + if( !merc_class(class_) ) - return 0; - + return true; + contract_time = script_getnum(st,3); merc_create(sd, class_, contract_time); - return 0; + return true; } -BUILDIN_FUNC(mercenary_heal) +BUILDIN(mercenary_heal) { struct map_session_data *sd = script_rid2sd(st); int hp, sp; - + if( sd == NULL || sd->md == NULL ) - return 0; + return true; hp = script_getnum(st,2); sp = script_getnum(st,3); - + status_heal(&sd->md->bl, hp, sp, 0); - return 0; + return true; } -BUILDIN_FUNC(mercenary_sc_start) +BUILDIN(mercenary_sc_start) { struct map_session_data *sd = script_rid2sd(st); enum sc_type type; int tick, val1; - + if( sd == NULL || sd->md == NULL ) - return 0; - + return true; + type = (sc_type)script_getnum(st,2); tick = script_getnum(st,3); val1 = script_getnum(st,4); - + status_change_start(&sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2); - return 0; + return true; } -BUILDIN_FUNC(mercenary_get_calls) +BUILDIN(mercenary_get_calls) { struct map_session_data *sd = script_rid2sd(st); int guild; - + if( sd == NULL ) - return 0; - + return true; + guild = script_getnum(st,2); switch( guild ) { @@ -15760,21 +15422,21 @@ BUILDIN_FUNC(mercenary_get_calls) script_pushint(st,0); break; } - - return 0; + + return true; } -BUILDIN_FUNC(mercenary_set_calls) +BUILDIN(mercenary_set_calls) { struct map_session_data *sd = script_rid2sd(st); int guild, value, *calls; - + if( sd == NULL ) - return 0; - + return true; + guild = script_getnum(st,2); value = script_getnum(st,3); - + switch( guild ) { case ARCH_MERC_GUILD: @@ -15787,23 +15449,23 @@ BUILDIN_FUNC(mercenary_set_calls) calls = &sd->status.sword_calls; break; default: - return 0; // Invalid Guild + return true; // Invalid Guild } - + *calls += value; *calls = cap_value(*calls, 0, INT_MAX); - - return 0; + + return true; } -BUILDIN_FUNC(mercenary_get_faith) +BUILDIN(mercenary_get_faith) { struct map_session_data *sd = script_rid2sd(st); int guild; - + if( sd == NULL ) - return 0; - + return true; + guild = script_getnum(st,2); switch( guild ) { @@ -15820,21 +15482,21 @@ BUILDIN_FUNC(mercenary_get_faith) script_pushint(st,0); break; } - - return 0; + + return true; } -BUILDIN_FUNC(mercenary_set_faith) +BUILDIN(mercenary_set_faith) { struct map_session_data *sd = script_rid2sd(st); int guild, value, *calls; - + if( sd == NULL ) - return 0; - + return true; + guild = script_getnum(st,2); value = script_getnum(st,3); - + switch( guild ) { case ARCH_MERC_GUILD: @@ -15847,130 +15509,130 @@ BUILDIN_FUNC(mercenary_set_faith) calls = &sd->status.sword_faith; break; default: - return 0; // Invalid Guild + return true; // Invalid Guild } - + *calls += value; *calls = cap_value(*calls, 0, INT_MAX); if( mercenary_get_guild(sd->md) == guild ) - clif_mercenary_updatestatus(sd,SP_MERCFAITH); - - return 0; + clif->mercenary_updatestatus(sd,SP_MERCFAITH); + + return true; } /*------------------------------------------ * Book Reading *------------------------------------------*/ -BUILDIN_FUNC(readbook) +BUILDIN(readbook) { struct map_session_data *sd; int book_id, page; - + if( (sd = script_rid2sd(st)) == NULL ) - return 0; - + return true; + book_id = script_getnum(st,2); page = script_getnum(st,3); - - clif_readbook(sd->fd, book_id, page); - return 0; + + clif->readbook(sd->fd, book_id, page); + return true; } /****************** -Questlog script commands -*******************/ + Questlog script commands + *******************/ -BUILDIN_FUNC(setquest) +BUILDIN(setquest) { struct map_session_data *sd = script_rid2sd(st); nullpo_ret(sd); - + quest_add(sd, script_getnum(st, 2)); - return 0; + return true; } -BUILDIN_FUNC(erasequest) +BUILDIN(erasequest) { struct map_session_data *sd = script_rid2sd(st); nullpo_ret(sd); - + quest_delete(sd, script_getnum(st, 2)); - return 0; + return true; } -BUILDIN_FUNC(completequest) +BUILDIN(completequest) { struct map_session_data *sd = script_rid2sd(st); nullpo_ret(sd); - + quest_update_status(sd, script_getnum(st, 2), Q_COMPLETE); - return 0; + return true; } -BUILDIN_FUNC(changequest) +BUILDIN(changequest) { struct map_session_data *sd = script_rid2sd(st); nullpo_ret(sd); - + quest_change(sd, script_getnum(st, 2),script_getnum(st, 3)); - return 0; + return true; } -BUILDIN_FUNC(checkquest) +BUILDIN(checkquest) { struct map_session_data *sd = script_rid2sd(st); quest_check_type type = HAVEQUEST; - + nullpo_ret(sd); - + if( script_hasdata(st, 3) ) type = (quest_check_type)script_getnum(st, 3); - + script_pushint(st, quest_check(sd, script_getnum(st, 2), type)); - - return 0; + + return true; } -BUILDIN_FUNC(showevent) +BUILDIN(showevent) { TBL_PC *sd = script_rid2sd(st); struct npc_data *nd = map_id2nd(st->oid); int state, color; - + if( sd == NULL || nd == NULL ) - return 0; + return true; state = script_getnum(st, 2); color = script_getnum(st, 3); - + if( color < 0 || color > 3 ) - color = 0; // set default color - - clif_quest_show_event(sd, &nd->bl, state, color); - return 0; + color = 0; // set default color + + clif->quest_show_event(sd, &nd->bl, state, color); + return true; } /*========================================== * BattleGround System *------------------------------------------*/ -BUILDIN_FUNC(waitingroom2bg) +BUILDIN(waitingroom2bg) { struct npc_data *nd; struct chat_data *cd; const char *map_name, *ev = "", *dev = ""; int x, y, i, mapindex = 0, bg_id, n; struct map_session_data *sd; - + if( script_hasdata(st,7) ) nd = npc_name2id(script_getstr(st,7)); else nd = (struct npc_data *)map_id2bl(st->oid); - + if( nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL ) { script_pushint(st,0); - return 0; + return true; } - + map_name = script_getstr(st,2); if( strcmp(map_name,"-") != 0 ) { @@ -15978,21 +15640,21 @@ BUILDIN_FUNC(waitingroom2bg) if( mapindex == 0 ) { // Invalid Map script_pushint(st,0); - return 0; + return true; } } - + x = script_getnum(st,3); y = script_getnum(st,4); ev = script_getstr(st,5); // Logout Event dev = script_getstr(st,6); // Die Event - + if( (bg_id = bg_create(mapindex, x, y, ev, dev)) == 0 ) { // Creation failed script_pushint(st,0); - return 0; + return true; } - + n = cd->users; for( i = 0; i < n && i < MAX_BG_MEMBERS; i++ ) { @@ -16001,35 +15663,35 @@ BUILDIN_FUNC(waitingroom2bg) else mapreg_setreg(reference_uid(add_str("$@arenamembers"), i), 0); } - + mapreg_setreg(add_str("$@arenamembersnum"), i); script_pushint(st,bg_id); - return 0; + return true; } -BUILDIN_FUNC(waitingroom2bg_single) +BUILDIN(waitingroom2bg_single) { const char* map_name; struct npc_data *nd; struct chat_data *cd; struct map_session_data *sd; int x, y, mapindex, bg_id; - + bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if( (mapindex = mapindex_name2id(map_name)) == 0 ) - return 0; // Invalid Map - + return true; // Invalid Map + x = script_getnum(st,4); y = script_getnum(st,5); nd = npc_name2id(script_getstr(st,6)); - + if( nd == NULL || (cd = (struct chat_data *)map_id2bl(nd->chat_id)) == NULL || cd->users <= 0 ) - return 0; - + return true; + if( (sd = cd->usersd[0]) == NULL ) - return 0; - + return true; + if( bg_team_join(bg_id, sd) ) { pc_setpos(sd, mapindex, x, y, CLR_TELEPORT); @@ -16037,44 +15699,44 @@ BUILDIN_FUNC(waitingroom2bg_single) } else script_pushint(st,0); - - return 0; + + return true; } -BUILDIN_FUNC(bg_team_setxy) +BUILDIN(bg_team_setxy) { struct battleground_data *bg; int bg_id; - + bg_id = script_getnum(st,2); if( (bg = bg_team_search(bg_id)) == NULL ) - return 0; - + return true; + bg->x = script_getnum(st,3); bg->y = script_getnum(st,4); - return 0; + return true; } -BUILDIN_FUNC(bg_warp) +BUILDIN(bg_warp) { int x, y, mapindex, bg_id; const char* map_name; - + bg_id = script_getnum(st,2); map_name = script_getstr(st,3); if( (mapindex = mapindex_name2id(map_name)) == 0 ) - return 0; // Invalid Map + return true; // Invalid Map x = script_getnum(st,4); y = script_getnum(st,5); bg_team_warp(bg_id, mapindex, x, y); - return 0; + return true; } -BUILDIN_FUNC(bg_monster) +BUILDIN(bg_monster) { int class_ = 0, x = 0, y = 0, bg_id = 0; const char *str,*map, *evt=""; - + bg_id = script_getnum(st,2); map = script_getstr(st,3); x = script_getnum(st,4); @@ -16084,47 +15746,47 @@ BUILDIN_FUNC(bg_monster) if( script_hasdata(st,8) ) evt = script_getstr(st,8); check_event(st, evt); script_pushint(st, mob_spawn_bg(map,x,y,str,class_,evt,bg_id)); - return 0; + return true; } -BUILDIN_FUNC(bg_monster_set_team) +BUILDIN(bg_monster_set_team) { struct mob_data *md; struct block_list *mbl; int id = script_getnum(st,2), - bg_id = script_getnum(st,3); - + bg_id = script_getnum(st,3); + if( (mbl = map_id2bl(id)) == NULL || mbl->type != BL_MOB ) - return 0; + return true; md = (TBL_MOB *)mbl; md->bg_id = bg_id; - + mob_stop_attack(md); mob_stop_walking(md, 0); md->target_id = md->attacked_id = 0; - clif_charnameack(0, &md->bl); - - return 0; + clif->charnameack(0, &md->bl); + + return true; } -BUILDIN_FUNC(bg_leave) +BUILDIN(bg_leave) { struct map_session_data *sd = script_rid2sd(st); if( sd == NULL || !sd->bg_id ) - return 0; - + return true; + bg_team_leave(sd,0); - return 0; + return true; } -BUILDIN_FUNC(bg_destroy) +BUILDIN(bg_destroy) { int bg_id = script_getnum(st,2); bg_team_delete(bg_id); - return 0; + return true; } -BUILDIN_FUNC(bg_getareausers) +BUILDIN(bg_getareausers) { const char *str; int16 m, x0, y0, x1, y1; @@ -16132,21 +15794,21 @@ BUILDIN_FUNC(bg_getareausers) int i = 0, c = 0; struct battleground_data *bg = NULL; struct map_session_data *sd; - + bg_id = script_getnum(st,2); str = script_getstr(st,3); - + if( (bg = bg_team_search(bg_id)) == NULL || (m = map_mapname2mapid(str)) < 0 ) { script_pushint(st,0); - return 0; + return true; } - + x0 = script_getnum(st,4); y0 = script_getnum(st,5); x1 = script_getnum(st,6); y1 = script_getnum(st,7); - + for( i = 0; i < MAX_BG_MEMBERS; i++ ) { if( (sd = bg->members[i].sd) == NULL ) @@ -16155,39 +15817,39 @@ BUILDIN_FUNC(bg_getareausers) continue; c++; } - + script_pushint(st,c); - return 0; + return true; } -BUILDIN_FUNC(bg_updatescore) +BUILDIN(bg_updatescore) { const char *str; int16 m; - + str = script_getstr(st,2); if( (m = map_mapname2mapid(str)) < 0 ) - return 0; - + return true; + map[m].bgscore_lion = script_getnum(st,3); map[m].bgscore_eagle = script_getnum(st,4); - - clif_bg_updatescore(m); - return 0; + + clif->bg_updatescore(m); + return true; } -BUILDIN_FUNC(bg_get_data) +BUILDIN(bg_get_data) { struct battleground_data *bg; int bg_id = script_getnum(st,2), - type = script_getnum(st,3); - + type = script_getnum(st,3); + if( (bg = bg_team_search(bg_id)) == NULL ) { script_pushint(st,0); - return 0; + return true; } - + switch( type ) { case 0: script_pushint(st, bg->count); break; @@ -16195,102 +15857,102 @@ BUILDIN_FUNC(bg_get_data) ShowError("script:bg_get_data: unknown data identifier %d\n", type); break; } - - return 0; + + return true; } /*========================================== * Instancing Script Commands *------------------------------------------*/ -BUILDIN_FUNC(instance_create) +BUILDIN(instance_create) { const char *name; int party_id, res; - + name = script_getstr(st, 2); party_id = script_getnum(st, 3); - + res = instance_create(party_id, name); if( res == -4 ) // Already exists { script_pushint(st, -1); - return 0; + return true; } else if( res < 0 ) { const char *err; switch(res) { - case -3: err = "No free instances"; break; - case -2: err = "Invalid party ID"; break; - case -1: err = "Invalid type"; break; - default: err = "Unknown"; break; + case -3: err = "No free instances"; break; + case -2: err = "Invalid party ID"; break; + case -1: err = "Invalid type"; break; + default: err = "Unknown"; break; } ShowError("buildin_instance_create: %s [%d].\n", err, res); script_pushint(st, -2); - return 0; + return true; } - + script_pushint(st, res); - return 0; + return true; } -BUILDIN_FUNC(instance_destroy) +BUILDIN(instance_destroy) { int instance_id; struct map_session_data *sd; struct party_data *p; - + if( script_hasdata(st, 2) ) instance_id = script_getnum(st, 2); else if( st->instance_id ) instance_id = st->instance_id; else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; - else return 0; - + else return true; + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) { ShowError("buildin_instance_destroy: Trying to destroy invalid instance %d.\n", instance_id); - return 0; + return true; } - + instance_destroy(instance_id); - return 0; + return true; } -BUILDIN_FUNC(instance_attachmap) +BUILDIN(instance_attachmap) { const char *name; int16 m; int instance_id; bool usebasename = false; - + name = script_getstr(st,2); instance_id = script_getnum(st,3); if( script_hasdata(st,4) && script_getnum(st,4) > 0) usebasename = true; - + if( (m = instance_add_map(name, instance_id, usebasename)) < 0 ) // [Saithis] { ShowError("buildin_instance_attachmap: instance creation failed (%s): %d\n", name, m); script_pushconststr(st, ""); - return 0; + return true; } script_pushconststr(st, map[m].name); - - return 0; + + return true; } -BUILDIN_FUNC(instance_detachmap) +BUILDIN(instance_detachmap) { struct map_session_data *sd; struct party_data *p; const char *str; int16 m; int instance_id; - + str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); @@ -16298,38 +15960,39 @@ BUILDIN_FUNC(instance_detachmap) instance_id = st->instance_id; else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; - else return 0; - + else return true; + if( (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m,instance_id)) < 0 ) { ShowError("buildin_instance_detachmap: Trying to detach invalid map %s\n", str); - return 0; + return true; } - + instance_del_map(m); - return 0; + return true; } -BUILDIN_FUNC(instance_attach) +BUILDIN(instance_attach) { int instance_id; - + instance_id = script_getnum(st, 2); if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) - return 0; - + return true; + st->instance_id = instance_id; - return 0; + return true; } -BUILDIN_FUNC(instance_id) +BUILDIN(instance_id) { - int type, instance_id; - struct map_session_data *sd; - struct party_data *p; - + int instance_id; + if( script_hasdata(st, 2) ) { + struct party_data *p; + struct map_session_data *sd; + int type; type = script_getnum(st, 2); if( type == 0 ) instance_id = st->instance_id; @@ -16340,50 +16003,50 @@ BUILDIN_FUNC(instance_id) } else instance_id = st->instance_id; - + script_pushint(st, instance_id); - return 0; + return true; } -BUILDIN_FUNC(instance_set_timeout) +BUILDIN(instance_set_timeout) { int progress_timeout, idle_timeout; int instance_id; struct map_session_data *sd; struct party_data *p; - + progress_timeout = script_getnum(st, 2); idle_timeout = script_getnum(st, 3); - + if( script_hasdata(st, 4) ) instance_id = script_getnum(st, 4); else if( st->instance_id ) instance_id = st->instance_id; else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; - else return 0; - + else return true; + if( instance_id > 0 ) instance_set_timeout(instance_id, progress_timeout, idle_timeout); - - return 0; + + return true; } -BUILDIN_FUNC(instance_init) +BUILDIN(instance_init) { int instance_id = script_getnum(st, 2); - + if( instance[instance_id].state != INSTANCE_IDLE ) { ShowError("instance_init: instance already initialized.\n"); - return 0; + return true; } - + instance_init(instance_id); - return 0; + return true; } -BUILDIN_FUNC(instance_announce) +BUILDIN(instance_announce) { int instance_id = script_getnum(st,2); const char *mes = script_getstr(st,3); @@ -16393,39 +16056,39 @@ BUILDIN_FUNC(instance_announce) int fontSize = script_hasdata(st,7) ? script_getnum(st,7) : 12; // default fontSize int fontAlign = script_hasdata(st,8) ? script_getnum(st,8) : 0; // default fontAlign int fontY = script_hasdata(st,9) ? script_getnum(st,9) : 0; // default fontY - + int i; struct map_session_data *sd; struct party_data *p; - + if( instance_id == 0 ) { if( st->instance_id ) instance_id = st->instance_id; else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; - else return 0; + else return true; } - + if( instance_id <= 0 || instance_id >= MAX_INSTANCE ) - return 0; - + return true; + for( i = 0; i < instance[instance_id].num_map; i++ ) map_foreachinmap(buildin_announce_sub, instance[instance_id].map[i], BL_PC, - mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); - - return 0; + mes, strlen(mes)+1, flag&0xf0, fontColor, fontType, fontSize, fontAlign, fontY); + + return true; } -BUILDIN_FUNC(instance_npcname) +BUILDIN(instance_npcname) { const char *str; int instance_id = 0; - + struct map_session_data *sd; struct party_data *p; struct npc_data *nd; - + str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); @@ -16433,7 +16096,7 @@ BUILDIN_FUNC(instance_npcname) instance_id = st->instance_id; else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; - + if( instance_id && (nd = npc_name2id(str)) != NULL ) { static char npcname[NAME_LENGTH]; @@ -16444,20 +16107,20 @@ BUILDIN_FUNC(instance_npcname) { ShowError("script:instance_npcname: invalid instance NPC (instance_id: %d, NPC name: \"%s\".)\n", instance_id, str); st->state = END; - return 1; + return false; } - - return 0; + + return true; } -BUILDIN_FUNC(has_instance) +BUILDIN(has_instance) { struct map_session_data *sd; struct party_data *p; const char *str; int16 m; int instance_id = 0; - + str = script_getstr(st, 2); if( script_hasdata(st, 3) ) instance_id = script_getnum(st, 3); @@ -16465,18 +16128,18 @@ BUILDIN_FUNC(has_instance) instance_id = st->instance_id; else if( (sd = script_rid2sd(st)) != NULL && sd->status.party_id && (p = party_search(sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; - + if( !instance_id || (m = map_mapname2mapid(str)) < 0 || (m = instance_map2imap(m, instance_id)) < 0 ) { script_pushconststr(st, ""); - return 0; + return true; } - + script_pushconststr(st, map[m].name); - return 0; + return true; } -BUILDIN_FUNC(instance_warpall) +BUILDIN(instance_warpall) { struct map_session_data *pl_sd; int16 m, i; @@ -16485,7 +16148,7 @@ BUILDIN_FUNC(instance_warpall) int x, y; unsigned short mapindex; struct party_data *p = NULL; - + mapn = script_getstr(st,2); x = script_getnum(st,3); y = script_getnum(st,4); @@ -16495,19 +16158,19 @@ BUILDIN_FUNC(instance_warpall) instance_id = st->instance_id; else if( (pl_sd = script_rid2sd(st)) != NULL && pl_sd->status.party_id && (p = party_search(pl_sd->status.party_id)) != NULL && p->instance_id ) instance_id = p->instance_id; - else return 0; - + else return true; + if( (m = map_mapname2mapid(mapn)) < 0 || (map[m].flag.src4instance && (m = instance_mapid2imapid(m, instance_id)) < 0) ) - return 0; - + return true; + if( !(p = party_search(instance[instance_id].party_id)) ) - return 0; - + return true; + mapindex = map_id2index(m); for( i = 0; i < MAX_PARTY; i++ ) if( (pl_sd = p->data[i].sd) && map[pl_sd->bl.m].instance_id == st->instance_id ) pc_setpos(pl_sd,mapindex,x,y,CLR_TELEPORT); - - return 0; + + return true; } /*========================================== @@ -16520,71 +16183,71 @@ BUILDIN_FUNC(instance_warpall) * Example: instance_check_party (getcharid(1){,amount}{,min}{,max}); * Example 2: instance_check_party (getcharid(1),1,1,99); *------------------------------------------*/ -BUILDIN_FUNC(instance_check_party) +BUILDIN(instance_check_party) { struct map_session_data *pl_sd; int amount, min, max, i, party_id, c = 0; struct party_data *p = NULL; - + amount = script_hasdata(st,3) ? script_getnum(st,3) : 1; // Amount of needed Partymembers for the Instance. min = script_hasdata(st,4) ? script_getnum(st,4) : 1; // Minimum Level needed to join the Instance. max = script_hasdata(st,5) ? script_getnum(st,5) : MAX_LEVEL; // Maxium Level allowed to join the Instance. - + if( min < 1 || min > MAX_LEVEL){ ShowError("instance_check_party: Invalid min level, %d\n", min); - return 0; + return true; }else if( max < 1 || max > MAX_LEVEL){ ShowError("instance_check_party: Invalid max level, %d\n", max); - return 0; + return true; } - + if( script_hasdata(st,2) ) party_id = script_getnum(st,2); - else return 0; - + else return true; + if( !(p = party_search(party_id)) ){ script_pushint(st, 0); // Returns false if party does not exist. - return 0; + return true; } - + for( i = 0; i < MAX_PARTY; i++ ) if( (pl_sd = p->data[i].sd) ) if(map_id2bl(pl_sd->bl.id)){ if(pl_sd->status.base_level < min){ script_pushint(st, 0); - return 0; + return true; }else if(pl_sd->status.base_level > max){ script_pushint(st, 0); - return 0; + return true; } - c++; + c++; } - + if(c < amount){ script_pushint(st, 0); // Not enough Members in the Party to join Instance. }else script_pushint(st, 1); - - return 0; + + return true; } /*========================================== * Custom Fonts *------------------------------------------*/ -BUILDIN_FUNC(setfont) +BUILDIN(setfont) { struct map_session_data *sd = script_rid2sd(st); int font = script_getnum(st,2); if( sd == NULL ) - return 0; - + return true; + if( sd->user_font != font ) sd->user_font = font; else sd->user_font = 0; - - clif_font(sd); - return 0; + + clif->font(sd); + return true; } static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap) @@ -16598,231 +16261,228 @@ static int buildin_mobuseskill_sub(struct block_list *bl,va_list ap) int cancel = va_arg(ap,int); int emotion = va_arg(ap,int); int target = va_arg(ap,int); - + if( md->class_ != mobid ) return 0; - + // 0:self, 1:target, 2:master, default:random switch( target ) { case 0: tbl = map_id2bl(md->bl.id); break; case 1: tbl = map_id2bl(md->target_id); break; case 2: tbl = map_id2bl(md->master_id); break; - default:tbl = battle_getenemy(&md->bl, DEFAULT_ENEMY_TYPE(md),skill_get_range2(&md->bl, skill_id, skill_lv)); break; + default:tbl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),skill->get_range2(&md->bl, skill_id, skill_lv)); break; } - + if( !tbl ) return 0; - + if( md->ud.skilltimer != INVALID_TIMER ) // Cancel the casting skill. unit_skillcastcancel(bl,0); - - if( skill_get_casttype(skill_id) == CAST_GROUND ) + + if( skill->get_casttype(skill_id) == CAST_GROUND ) unit_skilluse_pos2(&md->bl, tbl->x, tbl->y, skill_id, skill_lv, casttime, cancel); else unit_skilluse_id2(&md->bl, tbl->id, skill_id, skill_lv, casttime, cancel); - - clif_emotion(&md->bl, emotion); - + + clif->emotion(&md->bl, emotion); + return 0; } /*========================================== * areamobuseskill "Map Name",<x>,<y>,<range>,<Mob ID>,"Skill Name"/<Skill ID>,<Skill Lv>,<Cast Time>,<Cancelable>,<Emotion>,<Target Type>; *------------------------------------------*/ -BUILDIN_FUNC(areamobuseskill) +BUILDIN(areamobuseskill) { struct block_list center; int16 m; int range,mobid,skill_id,skill_lv,casttime,emotion,target,cancel; - + if( (m = map_mapname2mapid(script_getstr(st,2))) < 0 ) { ShowError("areamobuseskill: invalid map name.\n"); - return 0; + return true; } - + if( map[m].flag.src4instance && st->instance_id && (m = instance_mapid2imapid(m, st->instance_id)) < 0 ) - return 0; - + return true; + center.m = m; center.x = script_getnum(st,3); center.y = script_getnum(st,4); range = script_getnum(st,5); mobid = script_getnum(st,6); - skill_id = ( script_isstring(st,7) ? skill_name2id(script_getstr(st,7)) : script_getnum(st,7) ); - if( (skill_lv = script_getnum(st,8)) > battle_config.mob_max_skilllvl ) - skill_lv = battle_config.mob_max_skilllvl; - + skill_id = ( script_isstring(st,7) ? skill->name2id(script_getstr(st,7)) : script_getnum(st,7) ); + skill_lv = script_getnum(st,8); casttime = script_getnum(st,9); cancel = script_getnum(st,10); emotion = script_getnum(st,11); target = script_getnum(st,12); - + map_foreachinrange(buildin_mobuseskill_sub, ¢er, range, BL_MOB, mobid, skill_id, skill_lv, casttime, cancel, emotion, target); - return 0; + return true; } -BUILDIN_FUNC(progressbar) +BUILDIN(progressbar) { struct map_session_data * sd = script_rid2sd(st); const char * color; unsigned int second; - + if( !st || !sd ) - return 0; - + return true; + st->state = STOP; - + color = script_getstr(st,2); second = script_getnum(st,3); - + sd->progressbar.npc_id = st->oid; sd->progressbar.timeout = gettick() + second*1000; - - clif_progressbar(sd, strtol(color, (char **)NULL, 0), second); - return 0; + + clif->progressbar(sd, strtol(color, (char **)NULL, 0), second); + return true; } -BUILDIN_FUNC(pushpc) +BUILDIN(pushpc) { uint8 dir; int cells, dx, dy; struct map_session_data* sd; - + if((sd = script_rid2sd(st))==NULL) { - return 0; + return true; } - + dir = script_getnum(st,2); cells = script_getnum(st,3); - + if(dir>7) { ShowWarning("buildin_pushpc: Invalid direction %d specified.\n", dir); script_reportsrc(st); - + dir%= 8; // trim spin-over } - + if(!cells) {// zero distance - return 0; + return true; } else if(cells<0) {// pushing backwards dir = (dir+4)%8; // turn around cells = -cells; } - + dx = dirx[dir]; dy = diry[dir]; - + unit_blown(&sd->bl, dx, dy, cells, 0); - return 0; + return true; } /// Invokes buying store preparation window /// buyingstore <slots>; -BUILDIN_FUNC(buyingstore) +BUILDIN(buyingstore) { struct map_session_data* sd; - - if( ( sd = script_rid2sd(st) ) == NULL ) - { - return 0; + + if( ( sd = script_rid2sd(st) ) == NULL ) { + return true; } - - buyingstore_setup(sd, script_getnum(st,2)); - return 0; + + buyingstore->setup(sd, script_getnum(st,2)); + return true; } /// Invokes search store info window /// searchstores <uses>,<effect>; -BUILDIN_FUNC(searchstores) +BUILDIN(searchstores) { unsigned short effect; unsigned int uses; struct map_session_data* sd; - + if( ( sd = script_rid2sd(st) ) == NULL ) { - return 0; + return true; } - + uses = script_getnum(st,2); effect = script_getnum(st,3); - + if( !uses ) { ShowError("buildin_searchstores: Amount of uses cannot be zero.\n"); - return 1; + return false; } - + if( effect > 1 ) { ShowError("buildin_searchstores: Invalid effect id %hu, specified.\n", effect); - return 1; + return false; } - - searchstore_open(sd, uses, effect); - return 0; + + searchstore->open(sd, uses, effect); + return true; } /// Displays a number as large digital clock. /// showdigit <value>[,<type>]; -BUILDIN_FUNC(showdigit) +BUILDIN(showdigit) { unsigned int type = 0; int value; struct map_session_data* sd; - + if( ( sd = script_rid2sd(st) ) == NULL ) { - return 0; + return true; } - + value = script_getnum(st,2); - + if( script_hasdata(st,3) ) { type = script_getnum(st,3); - + if( type > 3 ) { ShowError("buildin_showdigit: Invalid type %u.\n", type); - return 1; + return false; } } - - clif_showdigit(sd, (unsigned char)type, value); - return 0; + + clif->showdigit(sd, (unsigned char)type, value); + return true; } /** * Rune Knight **/ -BUILDIN_FUNC(makerune) { +BUILDIN(makerune) { TBL_PC* sd; if( (sd = script_rid2sd(st)) == NULL ) - return 0; - clif_skill_produce_mix_list(sd,RK_RUNEMASTERY,24); + return true; + clif->skill_produce_mix_list(sd,RK_RUNEMASTERY,24); sd->itemid = script_getnum(st,2); - return 0; + return true; } /** * checkdragon() returns 1 if mounting a dragon or 0 otherwise. **/ -BUILDIN_FUNC(checkdragon) { +BUILDIN(checkdragon) { TBL_PC* sd; if( (sd = script_rid2sd(st)) == NULL ) - return 0; + return true; if( pc_isridingdragon(sd) ) script_pushint(st,1); else script_pushint(st,0); - return 0; + return true; } /** * setdragon({optional Color}) returns 1 on success or 0 otherwise @@ -16834,24 +16494,25 @@ BUILDIN_FUNC(checkdragon) { * - 4 : Blue Dragon * - 5 : Red Dragon **/ -BUILDIN_FUNC(setdragon) { +BUILDIN(setdragon) { TBL_PC* sd; int color = script_hasdata(st,2) ? script_getnum(st,2) : 0; - unsigned int option = OPTION_DRAGON1; + if( (sd = script_rid2sd(st)) == NULL ) - return 0; + return true; if( !pc_checkskill(sd,RK_DRAGONTRAINING) || (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT ) script_pushint(st,0);//Doesn't have the skill or it's not a Rune Knight else if ( pc_isridingdragon(sd) ) {//Is mounted; release pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); script_pushint(st,1); } else {//Not mounted; Mount now. + unsigned int option = OPTION_DRAGON1; if( color ) { option = ( color == 1 ? OPTION_DRAGON1 : - color == 2 ? OPTION_DRAGON2 : - color == 3 ? OPTION_DRAGON3 : - color == 4 ? OPTION_DRAGON4 : - color == 5 ? OPTION_DRAGON5 : 0); + color == 2 ? OPTION_DRAGON2 : + color == 3 ? OPTION_DRAGON3 : + color == 4 ? OPTION_DRAGON4 : + color == 5 ? OPTION_DRAGON5 : 0); if( !option ) { ShowWarning("script_setdragon: Unknown Color %d used; changing to green (1)\n",color); option = OPTION_DRAGON1; @@ -16860,21 +16521,21 @@ BUILDIN_FUNC(setdragon) { pc_setoption(sd, sd->sc.option|option); script_pushint(st,1); } - return 0; + return true; } /** * ismounting() returns 1 if mounting a new mount or 0 otherwise **/ -BUILDIN_FUNC(ismounting) { +BUILDIN(ismounting) { TBL_PC* sd; if( (sd = script_rid2sd(st)) == NULL ) - return 0; - if( sd->sc.option&OPTION_MOUNTING ) + return true; + if( sd->sc.data[SC_ALL_RIDING] ) script_pushint(st,1); else script_pushint(st,0); - return 0; + return true; } /** @@ -16883,47 +16544,46 @@ BUILDIN_FUNC(ismounting) { * - Will fail if the player is mounting a non-new mount, e.g. dragon, peco, wug, etc. * - Will unmount the player is he is already mounting **/ -BUILDIN_FUNC(setmounting) { +BUILDIN(setmounting) { TBL_PC* sd; if( (sd = script_rid2sd(st)) == NULL ) - return 0; + return true; if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) script_pushint(st,0);//can't mount with one of these else { - if( sd->sc.option&OPTION_MOUNTING ) - pc_setoption(sd, sd->sc.option&~OPTION_MOUNTING);//release mount + if( sd->sc.data[SC_ALL_RIDING] ) + status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER); else - pc_setoption(sd, sd->sc.option|OPTION_MOUNTING);//mount + sc_start(&sd->bl, SC_ALL_RIDING, 100, 0, -1); script_pushint(st,1);//in both cases, return 1. } - return 0; + return true; } /** * Retrieves quantity of arguments provided to callfunc/callsub. * getargcount() -> amount of arguments received in a function **/ -BUILDIN_FUNC(getargcount) { +BUILDIN(getargcount) { struct script_retinfo* ri; - + if( st->stack->defsp < 1 || st->stack->stack_data[st->stack->defsp - 1].type != C_RETINFO ) { ShowError("script:getargcount: used out of function or callsub label!\n"); st->state = END; - return 1; + return false; } ri = st->stack->stack_data[st->stack->defsp - 1].u.ri; - + script_pushint(st, ri->nargs); - - return 0; + + return true; } /** * getcharip(<account ID>/<character ID>/<character name>) **/ -BUILDIN_FUNC(getcharip) +BUILDIN(getcharip) { struct map_session_data* sd = NULL; - int id = 0; - + /* check if a character name is specified */ if( script_hasdata(st, 2) ) { @@ -16931,175 +16591,181 @@ BUILDIN_FUNC(getcharip) sd = map_nick2sd(script_getstr(st, 2)); else if (script_isint(st, 2) || script_getnum(st, 2)) { + int id; id = script_getnum(st, 2); sd = (map_id2sd(id) ? map_id2sd(id) : map_charid2sd(id)); } } else sd = script_rid2sd(st); - + /* check for sd and IP */ if (!sd || !session[sd->fd]->client_addr) { script_pushconststr(st, ""); - return 0; + return true; } - + /* return the client ip_addr converted for output */ if (sd && sd->fd && session[sd->fd]) { /* initiliaze */ const char *ip_addr = NULL; uint32 ip; - + /* set ip, ip_addr and convert to ip and push str */ ip = session[sd->fd]->client_addr; ip_addr = ip2str(ip, NULL); script_pushstrcopy(st, ip_addr); } - - return 0; + + return true; } /** * is_function(<function name>) -> 1 if function exists, 0 otherwise **/ -BUILDIN_FUNC(is_function) { +BUILDIN(is_function) { const char* str = script_getstr(st,2); - + if( strdb_exists(userfunc_db, str) ) script_pushint(st,1); else script_pushint(st,0); - - return 0; + + return true; } /** * get_revision() -> retrieves the current svn revision (if available) **/ -BUILDIN_FUNC(get_revision) { - const char * revision; - - if ( (revision = get_svn_revision()) != 0 ) - script_pushint(st,atoi(revision)); +BUILDIN(get_revision) { + const char *svn = get_svn_revision(); + + if ( svn[0] != HERC_UNKNOWN_VER ) + script_pushint(st,atoi(svn)); else script_pushint(st,-1);//unknown - - return 0; + + return true; } /** * freeloop(<toggle>) -> toggles this script instance's looping-check ability **/ -BUILDIN_FUNC(freeloop) { - +BUILDIN(freeloop) { + if( script_getnum(st,2) ) st->freeloop = 1; else st->freeloop = 0; - + script_pushint(st, st->freeloop); - - return 0; + + return true; } /** * @commands (script based) **/ -BUILDIN_FUNC(bindatcmd) { +BUILDIN(bindatcmd) { const char* atcmd; const char* eventName; - int i, level = 0, level2 = 0; + int i, group_lv = 0, group_lv_char = 99; + bool log = false; bool create = false; - + atcmd = script_getstr(st,2); eventName = script_getstr(st,3); - - if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol ) + + if( *atcmd == atcommand->at_symbol || *atcmd == atcommand->char_symbol ) atcmd++; - - if( script_hasdata(st,4) ) level = script_getnum(st,4); - if( script_hasdata(st,5) ) level2 = script_getnum(st,5); - - if( atcmd_binding_count == 0 ) { - CREATE(atcmd_binding,struct atcmd_binding_data*,1); - + + if( script_hasdata(st,4) ) group_lv = script_getnum(st,4); + if( script_hasdata(st,5) ) group_lv_char = script_getnum(st,5); + if( script_hasdata(st,6) ) log = script_getnum(st,6) ? true : false; + + + if( atcommand->binding_count == 0 ) { + CREATE(atcommand->binding,struct atcmd_binding_data*,1); + create = true; } else { - ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command,atcmd) == 0); - if( i < atcmd_binding_count ) {/* update existent entry */ - safestrncpy(atcmd_binding[i]->npc_event, eventName, 50); - atcmd_binding[i]->level = level; - atcmd_binding[i]->level2 = level2; + ARR_FIND(0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command,atcmd) == 0); + if( i < atcommand->binding_count ) {/* update existent entry */ + safestrncpy(atcommand->binding[i]->npc_event, eventName, ATCOMMAND_LENGTH); + atcommand->binding[i]->group_lv = group_lv; + atcommand->binding[i]->group_lv_char = group_lv_char; + atcommand->binding[i]->log = log; } else create = true; } - + if( create ) { - i = atcmd_binding_count; - - if( atcmd_binding_count++ != 0 ) - RECREATE(atcmd_binding,struct atcmd_binding_data*,atcmd_binding_count); - - CREATE(atcmd_binding[i],struct atcmd_binding_data,1); - - safestrncpy(atcmd_binding[i]->command, atcmd, 50); - safestrncpy(atcmd_binding[i]->npc_event, eventName, 50); - atcmd_binding[i]->level = level; - atcmd_binding[i]->level2 = level2; - } - - return 0; + i = atcommand->binding_count; + + if( atcommand->binding_count++ != 0 ) + RECREATE(atcommand->binding,struct atcmd_binding_data*,atcommand->binding_count); + + CREATE(atcommand->binding[i],struct atcmd_binding_data,1); + + safestrncpy(atcommand->binding[i]->command, atcmd, 50); + safestrncpy(atcommand->binding[i]->npc_event, eventName, 50); + atcommand->binding[i]->group_lv = group_lv; + atcommand->binding[i]->group_lv_char = group_lv_char; + atcommand->binding[i]->log = log; + } + + return true; } -BUILDIN_FUNC(unbindatcmd) { +BUILDIN(unbindatcmd) { const char* atcmd; int i = 0; - + atcmd = script_getstr(st, 2); - - if( *atcmd == atcommand_symbol || *atcmd == charcommand_symbol ) + + if( *atcmd == atcommand->at_symbol || *atcmd == atcommand->char_symbol ) atcmd++; - - if( atcmd_binding_count == 0 ) { + + if( atcommand->binding_count == 0 ) { script_pushint(st, 0); - return 0; + return true; } - - ARR_FIND(0, atcmd_binding_count, i, strcmp(atcmd_binding[i]->command, atcmd) == 0); - if( i < atcmd_binding_count ) { + + ARR_FIND(0, atcommand->binding_count, i, strcmp(atcommand->binding[i]->command, atcmd) == 0); + if( i < atcommand->binding_count ) { int cursor = 0; - aFree(atcmd_binding[i]); - atcmd_binding[i] = NULL; + aFree(atcommand->binding[i]); + atcommand->binding[i] = NULL; /* compact the list now that we freed a slot somewhere */ - for( i = 0, cursor = 0; i < atcmd_binding_count; i++ ) { - if( atcmd_binding[i] == NULL ) + for( i = 0, cursor = 0; i < atcommand->binding_count; i++ ) { + if( atcommand->binding[i] == NULL ) continue; - + if( cursor != i ) { - memmove(&atcmd_binding[cursor], &atcmd_binding[i], sizeof(struct atcmd_binding_data*)); + memmove(&atcommand->binding[cursor], &atcommand->binding[i], sizeof(struct atcmd_binding_data*)); } - + cursor++; } - - if( (atcmd_binding_count = cursor) == 0 ) - aFree(atcmd_binding); - + + if( (atcommand->binding_count = cursor) == 0 ) + aFree(atcommand->binding); + script_pushint(st, 1); } else script_pushint(st, 0);/* not found */ - - return 0; + + return true; } -BUILDIN_FUNC(useatcmd) +BUILDIN(useatcmd) { TBL_PC dummy_sd; TBL_PC* sd; int fd; const char* cmd; - + cmd = script_getstr(st,2); - + if( st->rid ) { sd = script_rid2sd(st); @@ -17109,7 +16775,7 @@ BUILDIN_FUNC(useatcmd) { // Use a dummy character. sd = &dummy_sd; fd = 0; - + memset(&dummy_sd, 0, sizeof(TBL_PC)); if( st->oid ) { @@ -17119,121 +16785,127 @@ BUILDIN_FUNC(useatcmd) safestrncpy(dummy_sd.status.name, ((TBL_NPC*)bl)->name, NAME_LENGTH); } } - + // compatibility with previous implementation (deprecated!) - if( cmd[0] != atcommand_symbol ) - { + if( cmd[0] != atcommand->at_symbol ) { cmd += strlen(sd->status.name); - while( *cmd != atcommand_symbol && *cmd != 0 ) + while( *cmd != atcommand->at_symbol && *cmd != 0 ) cmd++; } - - is_atcommand(fd, sd, cmd, 1); - return 0; + + atcommand->parse(fd, sd, cmd, 1); + return true; } -BUILDIN_FUNC(checkre) +BUILDIN(checkre) { int num; - + num=script_getnum(st,2); switch(num){ case 0: - #ifdef RENEWAL - script_pushint(st, 1); - #else - script_pushint(st, 0); - #endif +#ifdef RENEWAL + script_pushint(st, 1); +#else + script_pushint(st, 0); +#endif break; case 1: - #ifdef RENEWAL_CAST - script_pushint(st, 1); - #else - script_pushint(st, 0); - #endif +#ifdef RENEWAL_CAST + script_pushint(st, 1); +#else + script_pushint(st, 0); +#endif break; case 2: - #ifdef RENEWAL_DROP - script_pushint(st, 1); - #else - script_pushint(st, 0); - #endif +#ifdef RENEWAL_DROP + script_pushint(st, 1); +#else + script_pushint(st, 0); +#endif break; case 3: - #ifdef RENEWAL_EXP - script_pushint(st, 1); - #else - script_pushint(st, 0); - #endif +#ifdef RENEWAL_EXP + script_pushint(st, 1); +#else + script_pushint(st, 0); +#endif break; case 4: - #ifdef RENEWAL_LVDMG - script_pushint(st, 1); - #else - script_pushint(st, 0); - #endif +#ifdef RENEWAL_LVDMG + script_pushint(st, 1); +#else + script_pushint(st, 0); +#endif break; case 5: - #ifdef RENEWAL_EDP - script_pushint(st, 1); - #else - script_pushint(st, 0); - #endif +#ifdef RENEWAL_EDP + script_pushint(st, 1); +#else + script_pushint(st, 0); +#endif break; case 6: - #ifdef RENEWAL_ASPD - script_pushint(st, 1); - #else - script_pushint(st, 0); - #endif +#ifdef RENEWAL_ASPD + script_pushint(st, 1); +#else + script_pushint(st, 0); +#endif break; default: ShowWarning("buildin_checkre: unknown parameter.\n"); break; } - return 0; + return true; } /* getrandgroupitem <group_id>,<quantity> */ -BUILDIN_FUNC(getrandgroupitem) { +BUILDIN(getrandgroupitem) { TBL_PC* sd; int i, get_count = 0, flag, nameid, group = script_getnum(st, 2), qty = script_getnum(st,3); struct item item_tmp; - + if( !( sd = script_rid2sd(st) ) ) - return 0; - + return true; + if( qty <= 0 ) { ShowError("getrandgroupitem: qty is <= 0!\n"); - return 1; + return false; } - if( (nameid = itemdb_searchrandomid(group)) == UNKNOWN_ITEM_ID ) { - return 1;/* itemdb_searchrandomid will already scream a error */ + + if(group < 1 || group >= MAX_ITEMGROUP) { + ShowError("getrandgroupitem: Invalid group id %d\n", group); + return false; } - + if (!itemgroup_db[group].qty) { + ShowError("getrandgroupitem: group id %d is empty!\n", group); + return false; + } + + nameid = itemdb_searchrandomid(group); memset(&item_tmp,0,sizeof(item_tmp)); - + item_tmp.nameid = nameid; item_tmp.identify = itemdb_isidentified(nameid); - + //Check if it's stackable. if (!itemdb_isstackable(nameid)) get_count = 1; else get_count = qty; - + for (i = 0; i < qty; i += get_count) { // if not pet egg if (!pet_create_egg(sd, nameid)) { if ((flag = pc_additem(sd, &item_tmp, get_count, LOG_TYPE_SCRIPT))) { - clif_additem(sd, 0, 0, flag); + clif->additem(sd, 0, 0, flag); if( pc_candrop(sd,&item_tmp) ) map_addflooritem(&item_tmp,get_count,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } } - - return 0; + + return true; } /* cleanmap <map_name>; @@ -17242,21 +16914,21 @@ static int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) { nullpo_ret(bl); map_clearflooritem(bl); - + return 0; } -BUILDIN_FUNC(cleanmap) +BUILDIN(cleanmap) { const char *map; int16 m = -1; int16 x0 = 0, y0 = 0, x1 = 0, y1 = 0; - + map = script_getstr(st, 2); m = map_mapname2mapid(map); if (!m) - return 1; - + return false; + if ((script_lastdata(st) - 2) < 4) { map_foreachinmap(atcommand_cleanfloor_sub, m, BL_ITEM); } else { @@ -17268,16 +16940,16 @@ BUILDIN_FUNC(cleanmap) map_foreachinarea(atcommand_cleanfloor_sub, m, x0, y0, x1, y1, BL_ITEM); } else { ShowError("cleanarea: invalid coordinate defined!\n"); - return 1; + return false; } } - - return 0; + + return true; } /* Cast a skill on the attached player. * npcskill <skill id>, <skill lvl>, <stat point>, <NPC level>; * npcskill "<skill name>", <skill lvl>, <stat point>, <NPC level>; */ -BUILDIN_FUNC(npcskill) +BUILDIN(npcskill) { uint16 skill_id; unsigned short skill_level; @@ -17285,500 +16957,602 @@ BUILDIN_FUNC(npcskill) unsigned int npc_level; struct npc_data *nd; struct map_session_data *sd; - - skill_id = script_isstring(st, 2) ? skill_name2id(script_getstr(st, 2)) : script_getnum(st, 2); + + skill_id = script_isstring(st, 2) ? skill->name2id(script_getstr(st, 2)) : script_getnum(st, 2); skill_level = script_getnum(st, 3); stat_point = script_getnum(st, 4); npc_level = script_getnum(st, 5); sd = script_rid2sd(st); nd = (struct npc_data *)map_id2bl(sd->npc_id); - + if (stat_point > battle_config.max_third_parameter) { ShowError("npcskill: stat point exceeded maximum of %d.\n",battle_config.max_third_parameter ); - return 1; + return false; } if (npc_level > MAX_LEVEL) { ShowError("npcskill: level exceeded maximum of %d.\n", MAX_LEVEL); - return 1; + return false; } if (sd == NULL || nd == NULL) { //ain't possible, but I don't trust people. - return 1; + return false; } - + nd->level = npc_level; nd->stat_point = stat_point; - + if (!nd->status.hp) { status_calc_npc(nd, true); } else { status_calc_npc(nd, false); } - - if (skill_get_inf(skill_id)&INF_GROUND_SKILL) { + + if (skill->get_inf(skill_id)&INF_GROUND_SKILL) { unit_skilluse_pos(&nd->bl, sd->bl.x, sd->bl.y, skill_id, skill_level); } else { unit_skilluse_id(&nd->bl, sd->bl.id, skill_id, skill_level); } - - return 0; + + return true; } - // declarations that were supposed to be exported from npc_chat.c #ifdef PCRE_SUPPORT -BUILDIN_FUNC(defpattern); -BUILDIN_FUNC(activatepset); -BUILDIN_FUNC(deactivatepset); -BUILDIN_FUNC(deletepset); + BUILDIN(defpattern); + BUILDIN(activatepset); + BUILDIN(deactivatepset); + BUILDIN(deletepset); #endif -/// script command definitions -/// for an explanation on args, see add_buildin_func -struct script_function buildin_func[] = { - // NPC interaction - BUILDIN_DEF(mes,"s*"), - BUILDIN_DEF(next,""), - BUILDIN_DEF(close,""), - BUILDIN_DEF(close2,""), - BUILDIN_DEF(menu,"sl*"), - BUILDIN_DEF(select,"s*"), //for future jA script compatibility - BUILDIN_DEF(prompt,"s*"), - // - BUILDIN_DEF(goto,"l"), - BUILDIN_DEF(callsub,"l*"), - BUILDIN_DEF(callfunc,"s*"), - BUILDIN_DEF(return,"?"), - BUILDIN_DEF(getarg,"i?"), - BUILDIN_DEF(jobchange,"i?"), - BUILDIN_DEF(jobname,"i"), - BUILDIN_DEF(input,"r??"), - BUILDIN_DEF(warp,"sii"), - BUILDIN_DEF(areawarp,"siiiisii??"), - BUILDIN_DEF(warpchar,"siii"), // [LuzZza] - BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] - BUILDIN_DEF(warpguild,"siii"), // [Fredzilla] - BUILDIN_DEF(setlook,"ii"), - BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it - BUILDIN_DEF(set,"rv"), - BUILDIN_DEF(setarray,"rv*"), - BUILDIN_DEF(cleararray,"rvi"), - BUILDIN_DEF(copyarray,"rri"), - BUILDIN_DEF(getarraysize,"r"), - BUILDIN_DEF(deletearray,"r?"), - BUILDIN_DEF(getelementofarray,"ri"), - BUILDIN_DEF(getitem,"vi?"), - BUILDIN_DEF(rentitem,"vi"), - BUILDIN_DEF(getitem2,"viiiiiiii?"), - BUILDIN_DEF(getnameditem,"vv"), - BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), - BUILDIN_DEF(makeitem,"visii"), - BUILDIN_DEF(delitem,"vi?"), - BUILDIN_DEF(delitem2,"viiiiiiii?"), - BUILDIN_DEF2(enableitemuse,"enable_items",""), - BUILDIN_DEF2(disableitemuse,"disable_items",""), - BUILDIN_DEF(cutin,"si"), - BUILDIN_DEF(viewpoint,"iiiii"), - BUILDIN_DEF(heal,"ii"), - BUILDIN_DEF(itemheal,"ii"), - BUILDIN_DEF(percentheal,"ii"), - BUILDIN_DEF(rand,"i?"), - BUILDIN_DEF(countitem,"v"), - BUILDIN_DEF(countitem2,"viiiiiii"), - BUILDIN_DEF(checkweight,"vi*"), - BUILDIN_DEF(checkweight2,"rr"), - BUILDIN_DEF(readparam,"i?"), - BUILDIN_DEF(getcharid,"i?"), - BUILDIN_DEF(getnpcid,"i?"), - BUILDIN_DEF(getpartyname,"i"), - BUILDIN_DEF(getpartymember,"i?"), - BUILDIN_DEF(getpartyleader,"i?"), - BUILDIN_DEF(getguildname,"i"), - BUILDIN_DEF(getguildmaster,"i"), - BUILDIN_DEF(getguildmasterid,"i"), - BUILDIN_DEF(strcharinfo,"i"), - BUILDIN_DEF(strnpcinfo,"i"), - BUILDIN_DEF(getequipid,"i"), - BUILDIN_DEF(getequipname,"i"), - BUILDIN_DEF(getbrokenid,"i"), // [Valaris] - BUILDIN_DEF(repair,"i"), // [Valaris] - BUILDIN_DEF(repairall,""), - BUILDIN_DEF(getequipisequiped,"i"), - BUILDIN_DEF(getequipisenableref,"i"), - BUILDIN_DEF(getequipisidentify,"i"), - BUILDIN_DEF(getequiprefinerycnt,"i"), - BUILDIN_DEF(getequipweaponlv,"i"), - BUILDIN_DEF(getequippercentrefinery,"i"), - BUILDIN_DEF(successrefitem,"i"), - BUILDIN_DEF(failedrefitem,"i"), - BUILDIN_DEF(downrefitem,"i"), - BUILDIN_DEF(statusup,"i"), - BUILDIN_DEF(statusup2,"ii"), - BUILDIN_DEF(bonus,"iv"), - BUILDIN_DEF2(bonus,"bonus2","ivi"), - BUILDIN_DEF2(bonus,"bonus3","ivii"), - BUILDIN_DEF2(bonus,"bonus4","ivvii"), - BUILDIN_DEF2(bonus,"bonus5","ivviii"), - BUILDIN_DEF(autobonus,"sii??"), - BUILDIN_DEF(autobonus2,"sii??"), - BUILDIN_DEF(autobonus3,"siiv?"), - BUILDIN_DEF(skill,"vi?"), - BUILDIN_DEF(addtoskill,"vi?"), // [Valaris] - BUILDIN_DEF(guildskill,"vi"), - BUILDIN_DEF(getskilllv,"v"), - BUILDIN_DEF(getgdskilllv,"iv"), - BUILDIN_DEF(basicskillcheck,""), - BUILDIN_DEF(getgmlevel,""), - BUILDIN_DEF(getgroupid,""), - BUILDIN_DEF(end,""), - BUILDIN_DEF(checkoption,"i"), - BUILDIN_DEF(setoption,"i?"), - BUILDIN_DEF(setcart,"?"), - BUILDIN_DEF(checkcart,""), - BUILDIN_DEF(setfalcon,"?"), - BUILDIN_DEF(checkfalcon,""), - BUILDIN_DEF(setriding,"?"), - BUILDIN_DEF(checkriding,""), - BUILDIN_DEF(checkwug,""), - BUILDIN_DEF(checkmadogear,""), - BUILDIN_DEF(setmadogear,"?"), - BUILDIN_DEF2(savepoint,"save","sii"), - BUILDIN_DEF(savepoint,"sii"), - BUILDIN_DEF(gettimetick,"i"), - BUILDIN_DEF(gettime,"i"), - BUILDIN_DEF(gettimestr,"si"), - BUILDIN_DEF(openstorage,""), - BUILDIN_DEF(guildopenstorage,""), - BUILDIN_DEF(itemskill,"vi"), - BUILDIN_DEF(produce,"i"), - BUILDIN_DEF(cooking,"i"), - BUILDIN_DEF(monster,"siisii???"), - BUILDIN_DEF(getmobdrops,"i"), - BUILDIN_DEF(areamonster,"siiiisii???"), - BUILDIN_DEF(killmonster,"ss?"), - BUILDIN_DEF(killmonsterall,"s?"), - BUILDIN_DEF(clone,"siisi????"), - BUILDIN_DEF(doevent,"s"), - BUILDIN_DEF(donpcevent,"s"), - BUILDIN_DEF(cmdothernpc,"ss"), - BUILDIN_DEF(addtimer,"is"), - BUILDIN_DEF(deltimer,"s"), - BUILDIN_DEF(addtimercount,"si"), - BUILDIN_DEF(initnpctimer,"??"), - BUILDIN_DEF(stopnpctimer,"??"), - BUILDIN_DEF(startnpctimer,"??"), - BUILDIN_DEF(setnpctimer,"i?"), - BUILDIN_DEF(getnpctimer,"i?"), - BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest] - BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest] - BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex] - BUILDIN_DEF(announce,"si?????"), - BUILDIN_DEF(mapannounce,"ssi?????"), - BUILDIN_DEF(areaannounce,"siiiisi?????"), - BUILDIN_DEF(getusers,"i"), - BUILDIN_DEF(getmapguildusers,"si"), - BUILDIN_DEF(getmapusers,"s"), - BUILDIN_DEF(getareausers,"siiii"), - BUILDIN_DEF(getareadropitem,"siiiiv"), - BUILDIN_DEF(enablenpc,"s"), - BUILDIN_DEF(disablenpc,"s"), - BUILDIN_DEF(hideoffnpc,"s"), - BUILDIN_DEF(hideonnpc,"s"), - BUILDIN_DEF(sc_start,"iii?"), - BUILDIN_DEF(sc_start2,"iiii?"), - BUILDIN_DEF(sc_start4,"iiiiii?"), - BUILDIN_DEF(sc_end,"i?"), - BUILDIN_DEF(getstatus, "i?"), - BUILDIN_DEF(getscrate,"ii?"), - BUILDIN_DEF(debugmes,"s"), - BUILDIN_DEF2(catchpet,"pet","i"), - BUILDIN_DEF2(birthpet,"bpet",""), - BUILDIN_DEF(resetlvl,"i"), - BUILDIN_DEF(resetstatus,""), - BUILDIN_DEF(resetskill,""), - BUILDIN_DEF(skillpointcount,""), - BUILDIN_DEF(changebase,"i?"), - BUILDIN_DEF(changesex,""), - BUILDIN_DEF(waitingroom,"si?????"), - BUILDIN_DEF(delwaitingroom,"?"), - BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), - BUILDIN_DEF(enablewaitingroomevent,"?"), - BUILDIN_DEF(disablewaitingroomevent,"?"), - BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT - BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT - BUILDIN_DEF(getwaitingroomstate,"i?"), - BUILDIN_DEF(warpwaitingpc,"sii?"), - BUILDIN_DEF(attachrid,"i"), - BUILDIN_DEF(detachrid,""), - BUILDIN_DEF(isloggedin,"i?"), - BUILDIN_DEF(setmapflagnosave,"ssii"), - BUILDIN_DEF(getmapflag,"si"), - BUILDIN_DEF(setmapflag,"si?"), - BUILDIN_DEF(removemapflag,"si?"), - BUILDIN_DEF(pvpon,"s"), - BUILDIN_DEF(pvpoff,"s"), - BUILDIN_DEF(gvgon,"s"), - BUILDIN_DEF(gvgoff,"s"), - BUILDIN_DEF(emotion,"i??"), - BUILDIN_DEF(maprespawnguildid,"sii"), - BUILDIN_DEF(agitstart,""), // <Agit> - BUILDIN_DEF(agitend,""), - BUILDIN_DEF(agitcheck,""), // <Agitcheck> - BUILDIN_DEF(flagemblem,"i"), // Flag Emblem - BUILDIN_DEF(getcastlename,"s"), - BUILDIN_DEF(getcastledata,"si"), - BUILDIN_DEF(setcastledata,"sii"), - BUILDIN_DEF(requestguildinfo,"i?"), - BUILDIN_DEF(getequipcardcnt,"i"), - BUILDIN_DEF(successremovecards,"i"), - BUILDIN_DEF(failedremovecards,"ii"), - BUILDIN_DEF(marriage,"s"), - BUILDIN_DEF2(wedding_effect,"wedding",""), - BUILDIN_DEF(divorce,""), - BUILDIN_DEF(ispartneron,""), - BUILDIN_DEF(getpartnerid,""), - BUILDIN_DEF(getchildid,""), - BUILDIN_DEF(getmotherid,""), - BUILDIN_DEF(getfatherid,""), - BUILDIN_DEF(warppartner,"sii"), - BUILDIN_DEF(getitemname,"v"), - BUILDIN_DEF(getitemslots,"i"), - BUILDIN_DEF(makepet,"i"), - BUILDIN_DEF(getexp,"ii"), - BUILDIN_DEF(getinventorylist,""), - BUILDIN_DEF(getskilllist,""), - BUILDIN_DEF(clearitem,""), - BUILDIN_DEF(classchange,"ii"), - BUILDIN_DEF(misceffect,"i"), - BUILDIN_DEF(playBGM,"s"), - BUILDIN_DEF(playBGMall,"s?????"), - BUILDIN_DEF(soundeffect,"si"), - BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster] - BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris] - BUILDIN_DEF(guardian,"siisi??"), // summon guardians - BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris] - BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris] - BUILDIN_DEF(petrecovery,"ii"), // [Valaris] - BUILDIN_DEF(petloot,"i"), // [Valaris] - BUILDIN_DEF(petheal,"iiii"), // [Valaris] - BUILDIN_DEF(petskillattack,"viii"), // [Skotlex] - BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris] - BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex] - BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest] - BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris] - BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris] - BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris] - BUILDIN_DEF(nude,""), // nude command [Valaris] - BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT - BUILDIN_DEF(atcommand,"s"), // [MouseJstr] - BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] - BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] - BUILDIN_DEF(message,"ss"), // [MouseJstr] - BUILDIN_DEF(npctalk,"s"), // [Valaris] - BUILDIN_DEF(mobcount,"ss"), - BUILDIN_DEF(getlook,"i"), - BUILDIN_DEF(getsavepoint,"i"), - BUILDIN_DEF(npcspeed,"i"), // [Valaris] - BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] - BUILDIN_DEF(npcstop,""), // [Valaris] - BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] - BUILDIN_DEF(checkoption1,"i"), - BUILDIN_DEF(checkoption2,"i"), - BUILDIN_DEF(guildgetexp,"i"), - BUILDIN_DEF(guildchangegm,"is"), - BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] - BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest] - BUILDIN_DEF(isnight,""), // check whether it is night time [Celest] - BUILDIN_DEF(isday,""), // check whether it is day time [Celest] - BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest] - BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest] - BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus] - BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest] - BUILDIN_DEF(night,""), // sets the server to night time - BUILDIN_DEF(day,""), // sets the server to day time +bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)) { + int n = add_str(name), i = 0; + + if( str_data[n].type == C_FUNC ) { + str_data[n].func = func; + i = str_data[n].val; + if( args ) { + int slen = strlen(args); + if( script->buildin[i] ) { + aFree(script->buildin[i]); + } + CREATE(script->buildin[i], char, slen + 1); + safestrncpy(script->buildin[i], args, slen + 1); + } else { + if( script->buildin[i] ) + aFree(script->buildin[i]); + script->buildin[i] = NULL; + } + + } else { + i = script->buildin_count; + str_data[n].type = C_FUNC; + str_data[n].val = i; + str_data[n].func = func; + + RECREATE(script->buildin, char *, ++script->buildin_count); + + /* we only store the arguments, its the only thing used out of this */ + if( args != NULL ) { + int slen = strlen(args); + CREATE(script->buildin[i], char, slen + 1); + safestrncpy(script->buildin[i], args, slen + 1); + } else + script->buildin[i] = NULL; + } + + return true; +} + +void script_parse_builtin(void) { + struct script_function BUILDIN[] = { + // NPC interaction + BUILDIN_DEF(mes,"s*"), + BUILDIN_DEF(next,""), + BUILDIN_DEF(close,""), + BUILDIN_DEF(close2,""), + BUILDIN_DEF(menu,"sl*"), + BUILDIN_DEF(select,"s*"), //for future jA script compatibility + BUILDIN_DEF(prompt,"s*"), + // + BUILDIN_DEF(goto,"l"), + BUILDIN_DEF(callsub,"l*"), + BUILDIN_DEF(callfunc,"s*"), + BUILDIN_DEF(return,"?"), + BUILDIN_DEF(getarg,"i?"), + BUILDIN_DEF(jobchange,"i?"), + BUILDIN_DEF(jobname,"i"), + BUILDIN_DEF(input,"r??"), + BUILDIN_DEF(warp,"sii"), + BUILDIN_DEF(areawarp,"siiiisii??"), + BUILDIN_DEF(warpchar,"siii"), // [LuzZza] + BUILDIN_DEF(warpparty,"siii?"), // [Fredzilla] [Paradox924X] + BUILDIN_DEF(warpguild,"siii"), // [Fredzilla] + BUILDIN_DEF(setlook,"ii"), + BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it + BUILDIN_DEF(set,"rv"), + BUILDIN_DEF(setarray,"rv*"), + BUILDIN_DEF(cleararray,"rvi"), + BUILDIN_DEF(copyarray,"rri"), + BUILDIN_DEF(getarraysize,"r"), + BUILDIN_DEF(deletearray,"r?"), + BUILDIN_DEF(getelementofarray,"ri"), + BUILDIN_DEF(getitem,"vi?"), + BUILDIN_DEF(rentitem,"vi"), + BUILDIN_DEF(getitem2,"viiiiiiii?"), + BUILDIN_DEF(getnameditem,"vv"), + BUILDIN_DEF2(grouprandomitem,"groupranditem","i"), + BUILDIN_DEF(makeitem,"visii"), + BUILDIN_DEF(delitem,"vi?"), + BUILDIN_DEF(delitem2,"viiiiiiii?"), + BUILDIN_DEF2(enableitemuse,"enable_items",""), + BUILDIN_DEF2(disableitemuse,"disable_items",""), + BUILDIN_DEF(cutin,"si"), + BUILDIN_DEF(viewpoint,"iiiii"), + BUILDIN_DEF(heal,"ii"), + BUILDIN_DEF(itemheal,"ii"), + BUILDIN_DEF(percentheal,"ii"), + BUILDIN_DEF(rand,"i?"), + BUILDIN_DEF(countitem,"v"), + BUILDIN_DEF(countitem2,"viiiiiii"), + BUILDIN_DEF(checkweight,"vi*"), + BUILDIN_DEF(checkweight2,"rr"), + BUILDIN_DEF(readparam,"i?"), + BUILDIN_DEF(getcharid,"i?"), + BUILDIN_DEF(getnpcid,"i?"), + BUILDIN_DEF(getpartyname,"i"), + BUILDIN_DEF(getpartymember,"i?"), + BUILDIN_DEF(getpartyleader,"i?"), + BUILDIN_DEF(getguildname,"i"), + BUILDIN_DEF(getguildmaster,"i"), + BUILDIN_DEF(getguildmasterid,"i"), + BUILDIN_DEF(strcharinfo,"i"), + BUILDIN_DEF(strnpcinfo,"i"), + BUILDIN_DEF(getequipid,"i"), + BUILDIN_DEF(getequipname,"i"), + BUILDIN_DEF(getbrokenid,"i"), // [Valaris] + BUILDIN_DEF(repair,"i"), // [Valaris] + BUILDIN_DEF(repairall,""), + BUILDIN_DEF(getequipisequiped,"i"), + BUILDIN_DEF(getequipisenableref,"i"), + BUILDIN_DEF(getequipisidentify,"i"), + BUILDIN_DEF(getequiprefinerycnt,"i"), + BUILDIN_DEF(getequipweaponlv,"i"), + BUILDIN_DEF(getequippercentrefinery,"i"), + BUILDIN_DEF(successrefitem,"i"), + BUILDIN_DEF(failedrefitem,"i"), + BUILDIN_DEF(downrefitem,"i"), + BUILDIN_DEF(statusup,"i"), + BUILDIN_DEF(statusup2,"ii"), + BUILDIN_DEF(bonus,"iv"), + BUILDIN_DEF2(bonus,"bonus2","ivi"), + BUILDIN_DEF2(bonus,"bonus3","ivii"), + BUILDIN_DEF2(bonus,"bonus4","ivvii"), + BUILDIN_DEF2(bonus,"bonus5","ivviii"), + BUILDIN_DEF(autobonus,"sii??"), + BUILDIN_DEF(autobonus2,"sii??"), + BUILDIN_DEF(autobonus3,"siiv?"), + BUILDIN_DEF(skill,"vi?"), + BUILDIN_DEF(addtoskill,"vi?"), // [Valaris] + BUILDIN_DEF(guildskill,"vi"), + BUILDIN_DEF(getskilllv,"v"), + BUILDIN_DEF(getgdskilllv,"iv"), + BUILDIN_DEF(basicskillcheck,""), + BUILDIN_DEF(getgmlevel,""), + BUILDIN_DEF(getgroupid,""), + BUILDIN_DEF(end,""), + BUILDIN_DEF(checkoption,"i"), + BUILDIN_DEF(setoption,"i?"), + BUILDIN_DEF(setcart,"?"), + BUILDIN_DEF(checkcart,""), + BUILDIN_DEF(setfalcon,"?"), + BUILDIN_DEF(checkfalcon,""), + BUILDIN_DEF(setriding,"?"), + BUILDIN_DEF(checkriding,""), + BUILDIN_DEF(checkwug,""), + BUILDIN_DEF(checkmadogear,""), + BUILDIN_DEF(setmadogear,"?"), + BUILDIN_DEF2(savepoint,"save","sii"), + BUILDIN_DEF(savepoint,"sii"), + BUILDIN_DEF(gettimetick,"i"), + BUILDIN_DEF(gettime,"i"), + BUILDIN_DEF(gettimestr,"si"), + BUILDIN_DEF(openstorage,""), + BUILDIN_DEF(guildopenstorage,""), + BUILDIN_DEF(itemskill,"vi?"), + BUILDIN_DEF(produce,"i"), + BUILDIN_DEF(cooking,"i"), + BUILDIN_DEF(monster,"siisii???"), + BUILDIN_DEF(getmobdrops,"i"), + BUILDIN_DEF(areamonster,"siiiisii???"), + BUILDIN_DEF(killmonster,"ss?"), + BUILDIN_DEF(killmonsterall,"s?"), + BUILDIN_DEF(clone,"siisi????"), + BUILDIN_DEF(doevent,"s"), + BUILDIN_DEF(donpcevent,"s"), + BUILDIN_DEF(cmdothernpc,"ss"), + BUILDIN_DEF(addtimer,"is"), + BUILDIN_DEF(deltimer,"s"), + BUILDIN_DEF(addtimercount,"si"), + BUILDIN_DEF(initnpctimer,"??"), + BUILDIN_DEF(stopnpctimer,"??"), + BUILDIN_DEF(startnpctimer,"??"), + BUILDIN_DEF(setnpctimer,"i?"), + BUILDIN_DEF(getnpctimer,"i?"), + BUILDIN_DEF(attachnpctimer,"?"), // attached the player id to the npc timer [Celest] + BUILDIN_DEF(detachnpctimer,"?"), // detached the player id from the npc timer [Celest] + BUILDIN_DEF(playerattached,""), // returns id of the current attached player. [Skotlex] + BUILDIN_DEF(announce,"si?????"), + BUILDIN_DEF(mapannounce,"ssi?????"), + BUILDIN_DEF(areaannounce,"siiiisi?????"), + BUILDIN_DEF(getusers,"i"), + BUILDIN_DEF(getmapguildusers,"si"), + BUILDIN_DEF(getmapusers,"s"), + BUILDIN_DEF(getareausers,"siiii"), + BUILDIN_DEF(getareadropitem,"siiiiv"), + BUILDIN_DEF(enablenpc,"s"), + BUILDIN_DEF(disablenpc,"s"), + BUILDIN_DEF(hideoffnpc,"s"), + BUILDIN_DEF(hideonnpc,"s"), + BUILDIN_DEF(sc_start,"iii?"), + BUILDIN_DEF(sc_start2,"iiii?"), + BUILDIN_DEF(sc_start4,"iiiiii?"), + BUILDIN_DEF(sc_end,"i?"), + BUILDIN_DEF(getstatus, "i?"), + BUILDIN_DEF(getscrate,"ii?"), + BUILDIN_DEF(debugmes,"s"), + BUILDIN_DEF2(catchpet,"pet","i"), + BUILDIN_DEF2(birthpet,"bpet",""), + BUILDIN_DEF(resetlvl,"i"), + BUILDIN_DEF(resetstatus,""), + BUILDIN_DEF(resetskill,""), + BUILDIN_DEF(skillpointcount,""), + BUILDIN_DEF(changebase,"i?"), + BUILDIN_DEF(changesex,""), + BUILDIN_DEF(waitingroom,"si?????"), + BUILDIN_DEF(delwaitingroom,"?"), + BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"), + BUILDIN_DEF(enablewaitingroomevent,"?"), + BUILDIN_DEF(disablewaitingroomevent,"?"), + BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT + BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT + BUILDIN_DEF(getwaitingroomstate,"i?"), + BUILDIN_DEF(warpwaitingpc,"sii?"), + BUILDIN_DEF(attachrid,"i"), + BUILDIN_DEF(detachrid,""), + BUILDIN_DEF(isloggedin,"i?"), + BUILDIN_DEF(setmapflagnosave,"ssii"), + BUILDIN_DEF(getmapflag,"si"), + BUILDIN_DEF(setmapflag,"si?"), + BUILDIN_DEF(removemapflag,"si?"), + BUILDIN_DEF(pvpon,"s"), + BUILDIN_DEF(pvpoff,"s"), + BUILDIN_DEF(gvgon,"s"), + BUILDIN_DEF(gvgoff,"s"), + BUILDIN_DEF(emotion,"i??"), + BUILDIN_DEF(maprespawnguildid,"sii"), + BUILDIN_DEF(agitstart,""), // <Agit> + BUILDIN_DEF(agitend,""), + BUILDIN_DEF(agitcheck,""), // <Agitcheck> + BUILDIN_DEF(flagemblem,"i"), // Flag Emblem + BUILDIN_DEF(getcastlename,"s"), + BUILDIN_DEF(getcastledata,"si"), + BUILDIN_DEF(setcastledata,"sii"), + BUILDIN_DEF(requestguildinfo,"i?"), + BUILDIN_DEF(getequipcardcnt,"i"), + BUILDIN_DEF(successremovecards,"i"), + BUILDIN_DEF(failedremovecards,"ii"), + BUILDIN_DEF(marriage,"s"), + BUILDIN_DEF2(wedding_effect,"wedding",""), + BUILDIN_DEF(divorce,""), + BUILDIN_DEF(ispartneron,""), + BUILDIN_DEF(getpartnerid,""), + BUILDIN_DEF(getchildid,""), + BUILDIN_DEF(getmotherid,""), + BUILDIN_DEF(getfatherid,""), + BUILDIN_DEF(warppartner,"sii"), + BUILDIN_DEF(getitemname,"v"), + BUILDIN_DEF(getitemslots,"i"), + BUILDIN_DEF(makepet,"i"), + BUILDIN_DEF(getexp,"ii"), + BUILDIN_DEF(getinventorylist,""), + BUILDIN_DEF(getskilllist,""), + BUILDIN_DEF(clearitem,""), + BUILDIN_DEF(classchange,"ii"), + BUILDIN_DEF(misceffect,"i"), + BUILDIN_DEF(playBGM,"s"), + BUILDIN_DEF(playBGMall,"s?????"), + BUILDIN_DEF(soundeffect,"si"), + BUILDIN_DEF(soundeffectall,"si?????"), // SoundEffectAll [Codemaster] + BUILDIN_DEF(strmobinfo,"ii"), // display mob data [Valaris] + BUILDIN_DEF(guardian,"siisi??"), // summon guardians + BUILDIN_DEF(guardianinfo,"sii"), // display guardian data [Valaris] + BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris] + BUILDIN_DEF(petrecovery,"ii"), // [Valaris] + BUILDIN_DEF(petloot,"i"), // [Valaris] + BUILDIN_DEF(petheal,"iiii"), // [Valaris] + BUILDIN_DEF(petskillattack,"viii"), // [Skotlex] + BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris] + BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex] + BUILDIN_DEF(skilleffect,"vi"), // skill effect [Celest] + BUILDIN_DEF(npcskilleffect,"viii"), // npc skill effect [Valaris] + BUILDIN_DEF(specialeffect,"i??"), // npc skill effect [Valaris] + BUILDIN_DEF(specialeffect2,"i??"), // skill effect on players[Valaris] + BUILDIN_DEF(nude,""), // nude command [Valaris] + BUILDIN_DEF(mapwarp,"ssii??"), // Added by RoVeRT + BUILDIN_DEF(atcommand,"s"), // [MouseJstr] + BUILDIN_DEF2(atcommand,"charcommand","s"), // [MouseJstr] + BUILDIN_DEF(movenpc,"sii?"), // [MouseJstr] + BUILDIN_DEF(message,"ss"), // [MouseJstr] + BUILDIN_DEF(npctalk,"s"), // [Valaris] + BUILDIN_DEF(mobcount,"ss"), + BUILDIN_DEF(getlook,"i"), + BUILDIN_DEF(getsavepoint,"i"), + BUILDIN_DEF(npcspeed,"i"), // [Valaris] + BUILDIN_DEF(npcwalkto,"ii"), // [Valaris] + BUILDIN_DEF(npcstop,""), // [Valaris] + BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus] + BUILDIN_DEF(checkoption1,"i"), + BUILDIN_DEF(checkoption2,"i"), + BUILDIN_DEF(guildgetexp,"i"), + BUILDIN_DEF(guildchangegm,"is"), + BUILDIN_DEF(logmes,"s"), //this command actls as MES but rints info into LOG file either SQL/TXT [Lupus] + BUILDIN_DEF(summon,"si??"), // summons a slave monster [Celest] + BUILDIN_DEF(isnight,""), // check whether it is night time [Celest] + BUILDIN_DEF(isday,""), // check whether it is day time [Celest] + BUILDIN_DEF(isequipped,"i*"), // check whether another item/card has been equipped [Celest] + BUILDIN_DEF(isequippedcnt,"i*"), // check how many items/cards are being equipped [Celest] + BUILDIN_DEF(cardscnt,"i*"), // check how many items/cards are being equipped in the same arm [Lupus] + BUILDIN_DEF(getrefine,""), // returns the refined number of the current item, or an item with index specified [celest] + BUILDIN_DEF(night,""), // sets the server to night time + BUILDIN_DEF(day,""), // sets the server to day time #ifdef PCRE_SUPPORT - BUILDIN_DEF(defpattern,"iss"), // Define pattern to listen for [MouseJstr] - BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr] - BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr] - BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr] + BUILDIN_DEF(defpattern,"iss"), // Define pattern to listen for [MouseJstr] + BUILDIN_DEF(activatepset,"i"), // Activate a pattern set [MouseJstr] + BUILDIN_DEF(deactivatepset,"i"), // Deactive a pattern set [MouseJstr] + BUILDIN_DEF(deletepset,"i"), // Delete a pattern set [MouseJstr] #endif - BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus] - BUILDIN_DEF(getusersname,""), - BUILDIN_DEF(recovery,""), - BUILDIN_DEF(getpetinfo,"i"), - BUILDIN_DEF(gethominfo,"i"), - BUILDIN_DEF(getmercinfo,"i?"), - BUILDIN_DEF(checkequipedcard,"i"), - BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility - BUILDIN_DEF(globalmes,"s?"), //end jA addition - BUILDIN_DEF(unequip,"i"), // unequip command [Spectre] - BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris] - BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris] - BUILDIN_DEF(charat,"si"), - BUILDIN_DEF(setchar,"ssi"), - BUILDIN_DEF(insertchar,"ssi"), - BUILDIN_DEF(delchar,"si"), - BUILDIN_DEF(strtoupper,"s"), - BUILDIN_DEF(strtolower,"s"), - BUILDIN_DEF(charisupper, "si"), - BUILDIN_DEF(charislower, "si"), - BUILDIN_DEF(substr,"sii"), - BUILDIN_DEF(explode, "rss"), - BUILDIN_DEF(implode, "r?"), - BUILDIN_DEF(sprintf,"s*"), // [Mirei] - BUILDIN_DEF(sscanf,"ss*"), // [Mirei] - BUILDIN_DEF(strpos,"ss?"), - BUILDIN_DEF(replacestr,"sss??"), - BUILDIN_DEF(countstr,"ss?"), - BUILDIN_DEF(setnpcdisplay,"sv??"), - BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. - BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info - BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info - BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item - // [zBuffer] List of mathematics commands ---> - BUILDIN_DEF(sqrt,"i"), - BUILDIN_DEF(pow,"ii"), - BUILDIN_DEF(distance,"iiii"), - // <--- [zBuffer] List of mathematics commands - BUILDIN_DEF(md5,"s"), - // [zBuffer] List of dynamic var commands ---> - BUILDIN_DEF(getd,"s"), - BUILDIN_DEF(setd,"sv"), - // <--- [zBuffer] List of dynamic var commands - BUILDIN_DEF(petstat,"i"), - BUILDIN_DEF(callshop,"s?"), // [Skotlex] - BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] - BUILDIN_DEF(npcshopadditem,"sii*"), - BUILDIN_DEF(npcshopdelitem,"si*"), - BUILDIN_DEF(npcshopattach,"s?"), - BUILDIN_DEF(equip,"i"), - BUILDIN_DEF(autoequip,"ii"), - BUILDIN_DEF(setbattleflag,"si"), - BUILDIN_DEF(getbattleflag,"s"), - BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus - BUILDIN_DEF(disguise,"i"), //disguise player. Lupus - BUILDIN_DEF(undisguise,""), //undisguise player. Lupus - BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus - BUILDIN_DEF(axtoi,"s"), - BUILDIN_DEF(query_sql,"s*"), - BUILDIN_DEF(query_logsql,"s*"), - BUILDIN_DEF(escape_sql,"v"), - BUILDIN_DEF(atoi,"s"), - // [zBuffer] List of player cont commands ---> - BUILDIN_DEF(rid2name,"i"), - BUILDIN_DEF(pcfollow,"ii"), - BUILDIN_DEF(pcstopfollow,"i"), - BUILDIN_DEF(pcblockmove,"ii"), - // <--- [zBuffer] List of player cont commands - // [zBuffer] List of mob control commands ---> - BUILDIN_DEF(unitwalk,"ii?"), - BUILDIN_DEF(unitkill,"i"), - BUILDIN_DEF(unitwarp,"isii"), - BUILDIN_DEF(unitattack,"iv?"), - BUILDIN_DEF(unitstop,"i"), - BUILDIN_DEF(unittalk,"is"), - BUILDIN_DEF(unitemote,"ii"), - BUILDIN_DEF(unitskilluseid,"ivi?"), // originally by Qamera [Celest] - BUILDIN_DEF(unitskillusepos,"iviii"), // [Celest] -// <--- [zBuffer] List of mob control commands - BUILDIN_DEF(sleep,"i"), - BUILDIN_DEF(sleep2,"i"), - BUILDIN_DEF(awake,"s"), - BUILDIN_DEF(getvariableofnpc,"rs"), - BUILDIN_DEF(warpportal,"iisii"), - BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] - BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), - BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] - BUILDIN_DEF(eaclass,"?"), //[Skotlex] - BUILDIN_DEF(roclass,"i?"), //[Skotlex] - BUILDIN_DEF(checkvending,"?"), - BUILDIN_DEF(checkchatting,"?"), - BUILDIN_DEF(openmail,""), - BUILDIN_DEF(openauction,""), - BUILDIN_DEF(checkcell,"siii"), - BUILDIN_DEF(setcell,"siiiiii"), - BUILDIN_DEF(setwall,"siiiiis"), - BUILDIN_DEF(delwall,"s"), - BUILDIN_DEF(searchitem,"rs"), - BUILDIN_DEF(mercenary_create,"ii"), - BUILDIN_DEF(mercenary_heal,"ii"), - BUILDIN_DEF(mercenary_sc_start,"iii"), - BUILDIN_DEF(mercenary_get_calls,"i"), - BUILDIN_DEF(mercenary_get_faith,"i"), - BUILDIN_DEF(mercenary_set_calls,"ii"), - BUILDIN_DEF(mercenary_set_faith,"ii"), - BUILDIN_DEF(readbook,"ii"), - BUILDIN_DEF(setfont,"i"), - BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), - BUILDIN_DEF(progressbar,"si"), - BUILDIN_DEF(pushpc,"ii"), - BUILDIN_DEF(buyingstore,"i"), - BUILDIN_DEF(searchstores,"ii"), - BUILDIN_DEF(showdigit,"i?"), - // WoE SE - BUILDIN_DEF(agitstart2,""), - BUILDIN_DEF(agitend2,""), - BUILDIN_DEF(agitcheck2,""), - // BattleGround - BUILDIN_DEF(waitingroom2bg,"siiss?"), - BUILDIN_DEF(waitingroom2bg_single,"isiis"), - BUILDIN_DEF(bg_team_setxy,"iii"), - BUILDIN_DEF(bg_warp,"isii"), - BUILDIN_DEF(bg_monster,"isiisi?"), - BUILDIN_DEF(bg_monster_set_team,"ii"), - BUILDIN_DEF(bg_leave,""), - BUILDIN_DEF(bg_destroy,"i"), - BUILDIN_DEF(areapercentheal,"siiiiii"), - BUILDIN_DEF(bg_get_data,"ii"), - BUILDIN_DEF(bg_getareausers,"isiiii"), - BUILDIN_DEF(bg_updatescore,"sii"), - - // Instancing - BUILDIN_DEF(instance_create,"si"), - BUILDIN_DEF(instance_destroy,"?"), - BUILDIN_DEF(instance_attachmap,"si?"), - BUILDIN_DEF(instance_detachmap,"s?"), - BUILDIN_DEF(instance_attach,"i"), - BUILDIN_DEF(instance_id,"?"), - BUILDIN_DEF(instance_set_timeout,"ii?"), - BUILDIN_DEF(instance_init,"i"), - BUILDIN_DEF(instance_announce,"isi?????"), - BUILDIN_DEF(instance_npcname,"s?"), - BUILDIN_DEF(has_instance,"s?"), - BUILDIN_DEF(instance_warpall,"sii?"), - BUILDIN_DEF(instance_check_party,"i???"), - /** - * 3rd-related - **/ - BUILDIN_DEF(makerune,"i"), - BUILDIN_DEF(checkdragon,""),//[Ind] - BUILDIN_DEF(setdragon,"?"),//[Ind] - BUILDIN_DEF(ismounting,""),//[Ind] - BUILDIN_DEF(setmounting,""),//[Ind] - BUILDIN_DEF(checkre,"i"), - /** - * rAthena and beyond! - **/ - BUILDIN_DEF(getargcount,""), - BUILDIN_DEF(getcharip,"?"), - BUILDIN_DEF(is_function,"s"), - BUILDIN_DEF(get_revision,""), - BUILDIN_DEF(freeloop,"i"), - BUILDIN_DEF(getrandgroupitem,"ii"), - BUILDIN_DEF(cleanmap,"s"), - BUILDIN_DEF2(cleanmap,"cleanarea","siiii"), - BUILDIN_DEF(npcskill,"viii"), - /** - * @commands (script based) - **/ - BUILDIN_DEF(bindatcmd, "ss??"), - BUILDIN_DEF(unbindatcmd, "s"), - BUILDIN_DEF(useatcmd, "s"), - - //Quest Log System [Inkfish] - BUILDIN_DEF(setquest, "i"), - BUILDIN_DEF(erasequest, "i"), - BUILDIN_DEF(completequest, "i"), - BUILDIN_DEF(checkquest, "i?"), - BUILDIN_DEF(changequest, "ii"), - BUILDIN_DEF(showevent, "ii"), - {NULL,NULL,NULL}, -}; + BUILDIN_DEF(dispbottom,"s"), //added from jA [Lupus] + BUILDIN_DEF(getusersname,""), + BUILDIN_DEF(recovery,""), + BUILDIN_DEF(getpetinfo,"i"), + BUILDIN_DEF(gethominfo,"i"), + BUILDIN_DEF(getmercinfo,"i?"), + BUILDIN_DEF(checkequipedcard,"i"), + BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility + BUILDIN_DEF(globalmes,"s?"), //end jA addition + BUILDIN_DEF(unequip,"i"), // unequip command [Spectre] + BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris] + BUILDIN_DEF(charisalpha,"si"), //isalpha [Valaris] + BUILDIN_DEF(charat,"si"), + BUILDIN_DEF(setchar,"ssi"), + BUILDIN_DEF(insertchar,"ssi"), + BUILDIN_DEF(delchar,"si"), + BUILDIN_DEF(strtoupper,"s"), + BUILDIN_DEF(strtolower,"s"), + BUILDIN_DEF(charisupper, "si"), + BUILDIN_DEF(charislower, "si"), + BUILDIN_DEF(substr,"sii"), + BUILDIN_DEF(explode, "rss"), + BUILDIN_DEF(implode, "r?"), + BUILDIN_DEF(sprintf,"s*"), // [Mirei] + BUILDIN_DEF(sscanf,"ss*"), // [Mirei] + BUILDIN_DEF(strpos,"ss?"), + BUILDIN_DEF(replacestr,"sss??"), + BUILDIN_DEF(countstr,"ss?"), + BUILDIN_DEF(setnpcdisplay,"sv??"), + BUILDIN_DEF(compare,"ss"), // Lordalfa - To bring strstr to scripting Engine. + BUILDIN_DEF(getiteminfo,"ii"), //[Lupus] returns Items Buy / sell Price, etc info + BUILDIN_DEF(setiteminfo,"iii"), //[Lupus] set Items Buy / sell Price, etc info + BUILDIN_DEF(getequipcardid,"ii"), //[Lupus] returns CARD ID or other info from CARD slot N of equipped item + // [zBuffer] List of mathematics commands ---> + BUILDIN_DEF(sqrt,"i"), + BUILDIN_DEF(pow,"ii"), + BUILDIN_DEF(distance,"iiii"), + // <--- [zBuffer] List of mathematics commands + BUILDIN_DEF(md5,"s"), + // [zBuffer] List of dynamic var commands ---> + BUILDIN_DEF(getd,"s"), + BUILDIN_DEF(setd,"sv"), + // <--- [zBuffer] List of dynamic var commands + BUILDIN_DEF(petstat,"i"), + BUILDIN_DEF(callshop,"s?"), // [Skotlex] + BUILDIN_DEF(npcshopitem,"sii*"), // [Lance] + BUILDIN_DEF(npcshopadditem,"sii*"), + BUILDIN_DEF(npcshopdelitem,"si*"), + BUILDIN_DEF(npcshopattach,"s?"), + BUILDIN_DEF(equip,"i"), + BUILDIN_DEF(autoequip,"ii"), + BUILDIN_DEF(setbattleflag,"si"), + BUILDIN_DEF(getbattleflag,"s"), + BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus + BUILDIN_DEF(disguise,"i"), //disguise player. Lupus + BUILDIN_DEF(undisguise,""), //undisguise player. Lupus + BUILDIN_DEF(getmonsterinfo,"ii"), //Lupus + BUILDIN_DEF(axtoi,"s"), + BUILDIN_DEF(query_sql,"s*"), + BUILDIN_DEF(query_logsql,"s*"), + BUILDIN_DEF(escape_sql,"v"), + BUILDIN_DEF(atoi,"s"), + // [zBuffer] List of player cont commands ---> + BUILDIN_DEF(rid2name,"i"), + BUILDIN_DEF(pcfollow,"ii"), + BUILDIN_DEF(pcstopfollow,"i"), + BUILDIN_DEF(pcblockmove,"ii"), + // <--- [zBuffer] List of player cont commands + // [zBuffer] List of mob control commands ---> + BUILDIN_DEF(unitwalk,"ii?"), + BUILDIN_DEF(unitkill,"i"), + BUILDIN_DEF(unitwarp,"isii"), + BUILDIN_DEF(unitattack,"iv?"), + BUILDIN_DEF(unitstop,"i"), + BUILDIN_DEF(unittalk,"is"), + BUILDIN_DEF(unitemote,"ii"), + BUILDIN_DEF(unitskilluseid,"ivi?"), // originally by Qamera [Celest] + BUILDIN_DEF(unitskillusepos,"iviii"), // [Celest] + // <--- [zBuffer] List of mob control commands + BUILDIN_DEF(sleep,"i"), + BUILDIN_DEF(sleep2,"i"), + BUILDIN_DEF(awake,"s"), + BUILDIN_DEF(getvariableofnpc,"rs"), + BUILDIN_DEF(warpportal,"iisii"), + BUILDIN_DEF2(homunculus_evolution,"homevolution",""), //[orn] + BUILDIN_DEF2(homunculus_mutate,"hommutate","?"), + BUILDIN_DEF2(homunculus_shuffle,"homshuffle",""), //[Zephyrus] + BUILDIN_DEF(eaclass,"?"), //[Skotlex] + BUILDIN_DEF(roclass,"i?"), //[Skotlex] + BUILDIN_DEF(checkvending,"?"), + BUILDIN_DEF(checkchatting,"?"), + BUILDIN_DEF(checkidle,"?"), + BUILDIN_DEF(openmail,""), + BUILDIN_DEF(openauction,""), + BUILDIN_DEF(checkcell,"siii"), + BUILDIN_DEF(setcell,"siiiiii"), + BUILDIN_DEF(setwall,"siiiiis"), + BUILDIN_DEF(delwall,"s"), + BUILDIN_DEF(searchitem,"rs"), + BUILDIN_DEF(mercenary_create,"ii"), + BUILDIN_DEF(mercenary_heal,"ii"), + BUILDIN_DEF(mercenary_sc_start,"iii"), + BUILDIN_DEF(mercenary_get_calls,"i"), + BUILDIN_DEF(mercenary_get_faith,"i"), + BUILDIN_DEF(mercenary_set_calls,"ii"), + BUILDIN_DEF(mercenary_set_faith,"ii"), + BUILDIN_DEF(readbook,"ii"), + BUILDIN_DEF(setfont,"i"), + BUILDIN_DEF(areamobuseskill,"siiiiviiiii"), + BUILDIN_DEF(progressbar,"si"), + BUILDIN_DEF(pushpc,"ii"), + BUILDIN_DEF(buyingstore,"i"), + BUILDIN_DEF(searchstores,"ii"), + BUILDIN_DEF(showdigit,"i?"), + // WoE SE + BUILDIN_DEF(agitstart2,""), + BUILDIN_DEF(agitend2,""), + BUILDIN_DEF(agitcheck2,""), + // BattleGround + BUILDIN_DEF(waitingroom2bg,"siiss?"), + BUILDIN_DEF(waitingroom2bg_single,"isiis"), + BUILDIN_DEF(bg_team_setxy,"iii"), + BUILDIN_DEF(bg_warp,"isii"), + BUILDIN_DEF(bg_monster,"isiisi?"), + BUILDIN_DEF(bg_monster_set_team,"ii"), + BUILDIN_DEF(bg_leave,""), + BUILDIN_DEF(bg_destroy,"i"), + BUILDIN_DEF(areapercentheal,"siiiiii"), + BUILDIN_DEF(bg_get_data,"ii"), + BUILDIN_DEF(bg_getareausers,"isiiii"), + BUILDIN_DEF(bg_updatescore,"sii"), + + // Instancing + BUILDIN_DEF(instance_create,"si"), + BUILDIN_DEF(instance_destroy,"?"), + BUILDIN_DEF(instance_attachmap,"si?"), + BUILDIN_DEF(instance_detachmap,"s?"), + BUILDIN_DEF(instance_attach,"i"), + BUILDIN_DEF(instance_id,"?"), + BUILDIN_DEF(instance_set_timeout,"ii?"), + BUILDIN_DEF(instance_init,"i"), + BUILDIN_DEF(instance_announce,"isi?????"), + BUILDIN_DEF(instance_npcname,"s?"), + BUILDIN_DEF(has_instance,"s?"), + BUILDIN_DEF(instance_warpall,"sii?"), + BUILDIN_DEF(instance_check_party,"i???"), + /** + * 3rd-related + **/ + BUILDIN_DEF(makerune,"i"), + BUILDIN_DEF(checkdragon,""),//[Ind] + BUILDIN_DEF(setdragon,"?"),//[Ind] + BUILDIN_DEF(ismounting,""),//[Ind] + BUILDIN_DEF(setmounting,""),//[Ind] + BUILDIN_DEF(checkre,"i"), + /** + * rAthena and beyond! + **/ + BUILDIN_DEF(getargcount,""), + BUILDIN_DEF(getcharip,"?"), + BUILDIN_DEF(is_function,"s"), + BUILDIN_DEF(get_revision,""), + BUILDIN_DEF(freeloop,"i"), + BUILDIN_DEF(getrandgroupitem,"ii"), + BUILDIN_DEF(cleanmap,"s"), + BUILDIN_DEF2(cleanmap,"cleanarea","siiii"), + BUILDIN_DEF(npcskill,"viii"), + BUILDIN_DEF(itemeffect,"v"), + BUILDIN_DEF(delequip,"i"), + /** + * @commands (script based) + **/ + BUILDIN_DEF(bindatcmd, "ss???"), + BUILDIN_DEF(unbindatcmd, "s"), + BUILDIN_DEF(useatcmd, "s"), + + //Quest Log System [Inkfish] + BUILDIN_DEF(setquest, "i"), + BUILDIN_DEF(erasequest, "i"), + BUILDIN_DEF(completequest, "i"), + BUILDIN_DEF(checkquest, "i?"), + BUILDIN_DEF(changequest, "ii"), + BUILDIN_DEF(showevent, "ii"), + }; + int i,n, len = ARRAYLENGTH(BUILDIN), start = script->buildin_count; + char* p; + RECREATE(script->buildin, char *, start + len); + for( i = 0; i < len; i++ ) { + // arg must follow the pattern: (v|s|i|r|l)*\?*\*? + // 'v' - value (either string or int or reference) + // 's' - string + // 'i' - int + // 'r' - reference (of a variable) + // 'l' - label + // '?' - one optional parameter + // '*' - unknown number of optional parameters + p = BUILDIN[i].arg; + while( *p == 'v' || *p == 's' || *p == 'i' || *p == 'r' || *p == 'l' ) ++p; + while( *p == '?' ) ++p; + if( *p == '*' ) ++p; + if( *p != 0 ){ + ShowWarning("script_parse_builtin: ignoring function \"%s\" with invalid arg \"%s\".\n", BUILDIN[i].name, BUILDIN[i].arg); + } else if( *skip_word(BUILDIN[i].name) != 0 ){ + ShowWarning("script_parse_builtin: ignoring function with invalid name \"%s\" (must be a word).\n", BUILDIN[i].name); + } else { + int slen = strlen(BUILDIN[i].arg), offset = start + i; + n = add_str(BUILDIN[i].name); + + if (!strcmp(BUILDIN[i].name, "set")) buildin_set_ref = n; + else if (!strcmp(BUILDIN[i].name, "callsub")) buildin_callsub_ref = n; + else if (!strcmp(BUILDIN[i].name, "callfunc")) buildin_callfunc_ref = n; + else if (!strcmp(BUILDIN[i].name, "getelementofarray") ) buildin_getelementofarray_ref = n; + + if( str_data[n].func && str_data[n].func != BUILDIN[i].func ) + continue;/* something replaced it, skip. */ + + str_data[n].type = C_FUNC; + str_data[n].val = offset; + str_data[n].func = BUILDIN[i].func; + + /* we only store the arguments, its the only thing used out of this */ + if( slen ) { + CREATE(script->buildin[offset], char, slen + 1); + safestrncpy(script->buildin[offset], BUILDIN[i].arg, slen + 1); + } else + script->buildin[offset] = NULL; + + script->buildin_count++; + + } + } +} + +void script_defaults(void) { + script = &script_s; + + script->buildin_count = 0; + script->buildin = NULL; + + script->init = do_init_script; + script->final = do_final_script; + + script->parse_builtin = script_parse_builtin; + script->addScript = script_hp_add; + script->conv_num = conv_num; + script->conv_str = conv_str; +} diff --git a/src/map/script.h b/src/map/script.h index ed56b8ebe..a0d282bfe 100644 --- a/src/map/script.h +++ b/src/map/script.h @@ -114,7 +114,7 @@ struct script_stack { // // Script state // -enum e_script_state { RUN,STOP,END,RERUNLINE,GOTO,RETFUNC }; +enum e_script_state { RUN,STOP,END,RERUNLINE,GOTO,RETFUNC,CLOSE }; struct script_state { struct script_stack* stack; @@ -132,6 +132,7 @@ struct script_state { int bk_npcid; unsigned freeloop : 1;// used by buildin_freeloop unsigned op2ref : 1;// used by op_2 + unsigned npc_item_flag : 1; }; struct script_reg { @@ -158,8 +159,6 @@ void run_script_sub(struct script_code *rootscript,int pos,int rid,int oid, char void run_script(struct script_code*,int,int,int); int set_var(struct map_session_data *sd, char *name, void *val); -int conv_num(struct script_state *st,struct script_data *data); -const char* conv_str(struct script_state *st,struct script_data *data); int run_script_timer(int tid, unsigned int tick, int id, intptr_t data); void run_script_main(struct script_state *st); @@ -181,17 +180,134 @@ void script_cleararray_pc(struct map_session_data* sd, const char* varname, void void script_setarray_pc(struct map_session_data* sd, const char* varname, uint8 idx, void* value, int* refcache); int script_config_read(char *cfgName); -int do_init_script(void); -int do_final_script(void); int add_str(const char* p); const char* get_str(int id); int script_reload(void); // @commands (script based) -void setd_sub(struct script_state *st, TBL_PC *sd, const char *varname, int elem, void *value, struct DBMap **ref); +void setd_sub(struct script_state *st, struct map_session_data *sd, const char *varname, int elem, void *value, struct DBMap **ref); -#ifdef BETA_THREAD_TEST -void queryThread_log(char * entry, int length); -#endif +/////////////////////////////////////////////////////////////////////////////// +//## TODO possible enhancements: [FlavioJS] +// - 'callfunc' supporting labels in the current npc "::LabelName" +// - 'callfunc' supporting labels in other npcs "NpcName::LabelName" +// - 'function FuncName;' function declarations reverting to global functions +// if local label isn't found +// - join callfunc and callsub's functionality +// - remove dynamic allocation in add_word() +// - remove GETVALUE / SETVALUE +// - clean up the set_reg / set_val / setd_sub mess +// - detect invalid label references at parse-time + +// +// struct script_state* st; +// + +/// Returns the script_data at the target index +#define script_getdata(st,i) ( &((st)->stack->stack_data[(st)->start + (i)]) ) +/// Returns if the stack contains data at the target index +#define script_hasdata(st,i) ( (st)->end > (st)->start + (i) ) +/// Returns the index of the last data in the stack +#define script_lastdata(st) ( (st)->end - (st)->start - 1 ) +/// Pushes an int into the stack +#define script_pushint(st,val) push_val((st)->stack, C_INT, (val)) +/// Pushes a string into the stack (script engine frees it automatically) +#define script_pushstr(st,val) push_str((st)->stack, C_STR, (val)) +/// Pushes a copy of a string into the stack +#define script_pushstrcopy(st,val) push_str((st)->stack, C_STR, aStrdup(val)) +/// Pushes a constant string into the stack (must never change or be freed) +#define script_pushconststr(st,val) push_str((st)->stack, C_CONSTSTR, (val)) +/// Pushes a nil into the stack +#define script_pushnil(st) push_val((st)->stack, C_NOP, 0) +/// Pushes a copy of the data in the target index +#define script_pushcopy(st,i) push_copy((st)->stack, (st)->start + (i)) + +#define script_isstring(st,i) data_isstring(script_getdata(st,i)) +#define script_isint(st,i) data_isint(script_getdata(st,i)) + +#define script_getnum(st,val) script->conv_num(st, script_getdata(st,val)) +#define script_getstr(st,val) script->conv_str(st, script_getdata(st,val)) +#define script_getref(st,val) ( script_getdata(st,val)->ref ) + +// Note: "top" functions/defines use indexes relative to the top of the stack +// -1 is the index of the data at the top + +/// Returns the script_data at the target index relative to the top of the stack +#define script_getdatatop(st,i) ( &((st)->stack->stack_data[(st)->stack->sp + (i)]) ) +/// Pushes a copy of the data in the target index relative to the top of the stack +#define script_pushcopytop(st,i) push_copy((st)->stack, (st)->stack->sp + (i)) +/// Removes the range of values [start,end[ relative to the top of the stack +#define script_removetop(st,start,end) ( pop_stack((st), ((st)->stack->sp + (start)), (st)->stack->sp + (end)) ) + +// +// struct script_data* data; +// + +/// Returns if the script data is a string +#define data_isstring(data) ( (data)->type == C_STR || (data)->type == C_CONSTSTR ) +/// Returns if the script data is an int +#define data_isint(data) ( (data)->type == C_INT ) +/// Returns if the script data is a reference +#define data_isreference(data) ( (data)->type == C_NAME ) +/// Returns if the script data is a label +#define data_islabel(data) ( (data)->type == C_POS ) +/// Returns if the script data is an internal script function label +#define data_isfunclabel(data) ( (data)->type == C_USERFUNC_POS ) + +/// Returns if this is a reference to a constant +#define reference_toconstant(data) ( str_data[reference_getid(data)].type == C_INT ) +/// Returns if this a reference to a param +#define reference_toparam(data) ( str_data[reference_getid(data)].type == C_PARAM ) +/// Returns if this a reference to a variable +//##TODO confirm it's C_NAME [FlavioJS] +#define reference_tovariable(data) ( str_data[reference_getid(data)].type == C_NAME ) +/// Returns the unique id of the reference (id and index) +#define reference_getuid(data) ( (data)->u.num ) +/// Returns the id of the reference +#define reference_getid(data) ( (int32)(reference_getuid(data) & 0x00ffffff) ) +/// Returns the array index of the reference +#define reference_getindex(data) ( (int32)(((uint32)(reference_getuid(data) & 0xff000000)) >> 24) ) +/// Returns the name of the reference +#define reference_getname(data) ( str_buf + str_data[reference_getid(data)].str ) +/// Returns the linked list of uid-value pairs of the reference (can be NULL) +#define reference_getref(data) ( (data)->ref ) +/// Returns the value of the constant +#define reference_getconstant(data) ( str_data[reference_getid(data)].val ) +/// Returns the type of param +#define reference_getparamtype(data) ( str_data[reference_getid(data)].val ) + +/// Composes the uid of a reference from the id and the index +#define reference_uid(id,idx) ( (int32)((((uint32)(id)) & 0x00ffffff) | (((uint32)(idx)) << 24)) ) + +#define not_server_variable(prefix) ( (prefix) != '$' && (prefix) != '.' && (prefix) != '\'') +#define not_array_variable(prefix) ( (prefix) != '$' && (prefix) != '@' && (prefix) != '.' && (prefix) != '\'' ) +#define is_string_variable(name) ( (name)[strlen(name) - 1] == '$' ) + +#define BUILDIN(x) bool buildin_ ## x (struct script_state* st) +#define BUILDIN_A(x) buildin_ ## x + +struct script_function { + bool (*func)(struct script_state *st); + char *name; + char *arg; +}; +/* script.c interface (incomplete) */ +struct script_interface { + /* */ + char **buildin; + unsigned int buildin_count; + /* */ + void (*init) (void); + void (*final) (void); + /* */ + void (*parse_builtin) (void); + bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st)); + int (*conv_num) (struct script_state *st,struct script_data *data); + const char* (*conv_str) (struct script_state *st,struct script_data *data); +} script_s; + +struct script_interface *script; + +void script_defaults(void); #endif /* _SCRIPT_H_ */ diff --git a/src/map/searchstore.c b/src/map/searchstore.c index c59c13bed..7e1ee3e84 100644 --- a/src/map/searchstore.c +++ b/src/map/searchstore.c @@ -1,19 +1,19 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/malloc.h" // aMalloc, aRealloc, aFree #include "../common/showmsg.h" // ShowError, ShowWarning #include "../common/strlib.h" // safestrncpy #include "battle.h" // battle_config.* -#include "clif.h" // clif_open_search_store_info, clif_search_store_info_* +#include "clif.h" // clif->open_search_store_info, clif->search_store_info_* #include "pc.h" // struct map_session_data #include "searchstore.h" // struct s_search_store_info /// failure constants for clif functions -enum e_searchstore_failure -{ +enum e_searchstore_failure { SSI_FAILED_NOTHING_SEARCH_ITEM = 0, // "No matching stores were found." SSI_FAILED_OVER_MAXCOUNT = 1, // "There are too many results. Please enter more detailed search term." SSI_FAILED_SEARCH_CNT = 2, // "You cannot search anymore." @@ -22,15 +22,13 @@ enum e_searchstore_failure }; -enum e_searchstore_searchtype -{ +enum e_searchstore_searchtype { SEARCHTYPE_VENDING = 0, SEARCHTYPE_BUYING_STORE = 1, }; -enum e_searchstore_effecttype -{ +enum e_searchstore_effecttype { EFFECTTYPE_NORMAL = 0, EFFECTTYPE_CASH = 1, EFFECTTYPE_MAX @@ -43,34 +41,28 @@ typedef bool (*searchstore_searchall_t)(struct map_session_data* sd, const struc /// retrieves search function by type -static searchstore_search_t searchstore_getsearchfunc(unsigned char type) -{ - switch( type ) - { - case SEARCHTYPE_VENDING: return &vending_search; - case SEARCHTYPE_BUYING_STORE: return &buyingstore_search; +static inline searchstore_search_t searchstore_getsearchfunc(unsigned char type) { + switch( type ) { + case SEARCHTYPE_VENDING: return vending->search; + case SEARCHTYPE_BUYING_STORE: return buyingstore->search; } return NULL; } /// retrieves search-all function by type -static searchstore_searchall_t searchstore_getsearchallfunc(unsigned char type) -{ - switch( type ) - { - case SEARCHTYPE_VENDING: return &vending_searchall; - case SEARCHTYPE_BUYING_STORE: return &buyingstore_searchall; +static inline searchstore_searchall_t searchstore_getsearchallfunc(unsigned char type) { + switch( type ) { + case SEARCHTYPE_VENDING: return vending->searchall; + case SEARCHTYPE_BUYING_STORE: return buyingstore->searchall; } return NULL; } /// checks if the player has a store by type -static bool searchstore_hasstore(struct map_session_data* sd, unsigned char type) -{ - switch( type ) - { +static inline bool searchstore_hasstore(struct map_session_data* sd, unsigned char type) { + switch( type ) { case SEARCHTYPE_VENDING: return sd->state.vending; case SEARCHTYPE_BUYING_STORE: return sd->state.buyingstore; } @@ -79,10 +71,8 @@ static bool searchstore_hasstore(struct map_session_data* sd, unsigned char type /// returns player's store id by type -static int searchstore_getstoreid(struct map_session_data* sd, unsigned char type) -{ - switch( type ) - { +static inline unsigned int searchstore_getstoreid(struct map_session_data* sd, unsigned char type) { + switch( type ) { case SEARCHTYPE_VENDING: return sd->vender_id; case SEARCHTYPE_BUYING_STORE: return sd->buyer_id; } @@ -90,15 +80,12 @@ static int searchstore_getstoreid(struct map_session_data* sd, unsigned char typ } -bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect) -{ - if( !battle_config.feature_search_stores || sd->searchstore.open ) - { +bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect) { + if( !battle_config.feature_search_stores || sd->searchstore.open ) { return false; } - if( !uses || effect >= EFFECTTYPE_MAX ) - {// invalid input + if( !uses || effect >= EFFECTTYPE_MAX ) {// invalid input return false; } @@ -106,7 +93,7 @@ bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned s sd->searchstore.uses = uses; sd->searchstore.effect = effect; - clif_open_search_store_info(sd); + clif->open_search_store_info(sd); return true; } @@ -116,63 +103,53 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned { unsigned int i; struct map_session_data* pl_sd; - struct s_mapiterator* iter; + struct DBIterator *iter; struct s_search_store_search s; searchstore_searchall_t store_searchall; time_t querytime; - if( !battle_config.feature_search_stores ) - { + if( !battle_config.feature_search_stores ) { return; } - if( !sd->searchstore.open ) - { + if( !sd->searchstore.open ) { return; } - if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) - { + if( ( store_searchall = searchstore_getsearchallfunc(type) ) == NULL ) { ShowError("searchstore_query: Unknown search type %u (account_id=%d).\n", (unsigned int)type, sd->bl.id); return; } time(&querytime); - if( sd->searchstore.nextquerytime > querytime ) - { - clif_search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME); + if( sd->searchstore.nextquerytime > querytime ) { + clif->search_store_info_failed(sd, SSI_FAILED_LIMIT_SEARCH_TIME); return; } - if( !sd->searchstore.uses ) - { - clif_search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT); + if( !sd->searchstore.uses ) { + clif->search_store_info_failed(sd, SSI_FAILED_SEARCH_CNT); return; } // validate lists - for( i = 0; i < item_count; i++ ) - { - if( !itemdb_exists(itemlist[i]) ) - { + for( i = 0; i < item_count; i++ ) { + if( !itemdb_exists(itemlist[i]) ) { ShowWarning("searchstore_query: Client resolved item %hu is not known.\n", itemlist[i]); - clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); + clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); return; } } - for( i = 0; i < card_count; i++ ) - { - if( !itemdb_exists(cardlist[i]) ) - { + for( i = 0; i < card_count; i++ ) { + if( !itemdb_exists(cardlist[i]) ) { ShowWarning("searchstore_query: Client resolved card %hu is not known.\n", cardlist[i]); - clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); + clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); return; } } - if( max_price < min_price ) - { + if( max_price < min_price ) { swap(min_price, max_price); } @@ -181,7 +158,7 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned sd->searchstore.nextquerytime = querytime+battle_config.searchstore_querydelay; // drop previous results - searchstore_clear(sd); + searchstore->clear(sd); // allocate max. amount of results sd->searchstore.items = (struct s_search_store_info_item*)aMalloc(sizeof(struct s_search_store_info_item)*battle_config.searchstore_maxresults); @@ -194,54 +171,46 @@ void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned s.card_count = card_count; s.min_price = min_price; s.max_price = max_price; - iter = mapit_geteachpc(); + iter = db_iterator(vending->db); - for( pl_sd = (struct map_session_data*)mapit_first(iter); mapit_exists(iter); pl_sd = (struct map_session_data*)mapit_next(iter) ) - { - if( sd == pl_sd ) - {// skip own shop, if any + for( pl_sd = dbi_first(iter); dbi_exists(iter); pl_sd = dbi_next(iter) ) { + if( sd == pl_sd ) {// skip own shop, if any continue; } - if( !store_searchall(pl_sd, &s) ) - {// exceeded result size - clif_search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT); + if( !store_searchall(pl_sd, &s) ) {// exceeded result size + clif->search_store_info_failed(sd, SSI_FAILED_OVER_MAXCOUNT); break; } } - mapit_free(iter); + dbi_destroy(iter); - if( sd->searchstore.count ) - { + if( sd->searchstore.count ) { // reclaim unused memory sd->searchstore.items = (struct s_search_store_info_item*)aRealloc(sd->searchstore.items, sizeof(struct s_search_store_info_item)*sd->searchstore.count); // present results - clif_search_store_info_ack(sd); + clif->search_store_info_ack(sd); // one page displayed sd->searchstore.pages++; - } - else - { + } else { // cleanup - searchstore_clear(sd); + searchstore->clear(sd); // update uses - clif_search_store_info_ack(sd); + clif->search_store_info_ack(sd); // notify of failure - clif_search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); + clif->search_store_info_failed(sd, SSI_FAILED_NOTHING_SEARCH_ITEM); } } /// checks whether or not more results are available for the client -bool searchstore_querynext(struct map_session_data* sd) -{ - if( sd->searchstore.count && ( sd->searchstore.count-1 )/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages ) - { +bool searchstore_querynext(struct map_session_data* sd) { + if( sd->searchstore.count && ( sd->searchstore.count-1 )/SEARCHSTORE_RESULTS_PER_PAGE < sd->searchstore.pages ) { return true; } @@ -249,27 +218,24 @@ bool searchstore_querynext(struct map_session_data* sd) } -void searchstore_next(struct map_session_data* sd) -{ +void searchstore_next(struct map_session_data* sd) { if( !battle_config.feature_search_stores || !sd->searchstore.open || sd->searchstore.count <= sd->searchstore.pages*SEARCHSTORE_RESULTS_PER_PAGE ) {// nothing (more) to display return; } // present results - clif_search_store_info_ack(sd); + clif->search_store_info_ack(sd); // one more page displayed sd->searchstore.pages++; } -void searchstore_clear(struct map_session_data* sd) -{ - searchstore_clearremote(sd); +void searchstore_clear(struct map_session_data* sd) { + searchstore->clearremote(sd); - if( sd->searchstore.items ) - {// release results + if( sd->searchstore.items ) {// release results aFree(sd->searchstore.items); sd->searchstore.items = NULL; } @@ -279,11 +245,9 @@ void searchstore_clear(struct map_session_data* sd) } -void searchstore_close(struct map_session_data* sd) -{ - if( sd->searchstore.open ) - { - searchstore_clear(sd); +void searchstore_close(struct map_session_data* sd) { + if( sd->searchstore.open ) { + searchstore->clear(sd); sd->searchstore.uses = 0; sd->searchstore.open = false; @@ -291,59 +255,50 @@ void searchstore_close(struct map_session_data* sd) } -void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid) -{ +void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid) { unsigned int i; struct map_session_data* pl_sd; searchstore_search_t store_search; - if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count ) - { + if( !battle_config.feature_search_stores || !sd->searchstore.open || !sd->searchstore.count ) { return; } - searchstore_clearremote(sd); + searchstore->clearremote(sd); ARR_FIND( 0, sd->searchstore.count, i, sd->searchstore.items[i].store_id == store_id && sd->searchstore.items[i].account_id == account_id && sd->searchstore.items[i].nameid == nameid ); - if( i == sd->searchstore.count ) - {// no such result, crafted + if( i == sd->searchstore.count ) {// no such result, crafted ShowWarning("searchstore_click: Received request with item %hu of account %d, which is not part of current result set (account_id=%d, char_id=%d).\n", nameid, account_id, sd->bl.id, sd->status.char_id); - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } - if( ( pl_sd = map_id2sd(account_id) ) == NULL ) - {// no longer online - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + if( ( pl_sd = map_id2sd(account_id) ) == NULL ) {// no longer online + clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } - if( !searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id ) - {// no longer vending/buying or not same shop - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + if( !searchstore_hasstore(pl_sd, sd->searchstore.type) || searchstore_getstoreid(pl_sd, sd->searchstore.type) != store_id ) { + // no longer vending/buying or not same shop + clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } store_search = searchstore_getsearchfunc(sd->searchstore.type); - if( !store_search(pl_sd, nameid) ) - {// item no longer being sold/bought - clif_search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); + if( !store_search(pl_sd, nameid) ) {// item no longer being sold/bought + clif->search_store_info_failed(sd, SSI_FAILED_SSILIST_CLICK_TO_OPEN_STORE); return; } - switch( sd->searchstore.effect ) - { + switch( sd->searchstore.effect ) { case EFFECTTYPE_NORMAL: // display coords - if( sd->bl.m != pl_sd->bl.m ) - {// not on same map, wipe previous marker - clif_search_store_info_click_ack(sd, -1, -1); - } - else - { - clif_search_store_info_click_ack(sd, pl_sd->bl.x, pl_sd->bl.y); + if( sd->bl.m != pl_sd->bl.m ) {// not on same map, wipe previous marker + clif->search_store_info_click_ack(sd, -1, -1); + } else { + clif->search_store_info_click_ack(sd, pl_sd->bl.x, pl_sd->bl.y); } break; @@ -353,10 +308,9 @@ void searchstore_click(struct map_session_data* sd, int account_id, int store_id // to bypass range checks sd->searchstore.remote_id = account_id; - switch( sd->searchstore.type ) - { - case SEARCHTYPE_VENDING: vending_vendinglistreq(sd, account_id); break; - case SEARCHTYPE_BUYING_STORE: buyingstore_open(sd, account_id); break; + switch( sd->searchstore.type ) { + case SEARCHTYPE_VENDING: vending->list(sd, account_id); break; + case SEARCHTYPE_BUYING_STORE: buyingstore->open(sd, account_id); break; } break; @@ -368,26 +322,23 @@ void searchstore_click(struct map_session_data* sd, int account_id, int store_id /// checks whether or not sd has opened account_id's shop remotely -bool searchstore_queryremote(struct map_session_data* sd, int account_id) -{ +bool searchstore_queryremote(struct map_session_data* sd, int account_id) { return (bool)( sd->searchstore.open && sd->searchstore.count && sd->searchstore.remote_id == account_id ); } /// removes range-check bypassing for remotely opened stores -void searchstore_clearremote(struct map_session_data* sd) -{ +void searchstore_clearremote(struct map_session_data* sd) { sd->searchstore.remote_id = 0; } /// receives results from a store-specific callback -bool searchstore_result(struct map_session_data* sd, int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine) +bool searchstore_result(struct map_session_data* sd, unsigned int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine) { struct s_search_store_info_item* ssitem; - if( sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults ) - {// no more + if( sd->searchstore.count >= (unsigned int)battle_config.searchstore_maxresults ) {// no more return false; } @@ -403,3 +354,19 @@ bool searchstore_result(struct map_session_data* sd, int store_id, int account_i return true; } + +void searchstore_defaults (void) { + searchstore = &searchstore_s; + + searchstore->open = searchstore_open; + searchstore->query = searchstore_query; + searchstore->querynext = searchstore_querynext; + searchstore->next = searchstore_next; + searchstore->clear = searchstore_clear; + searchstore->close = searchstore_close; + searchstore->click = searchstore_click; + searchstore->queryremote = searchstore_queryremote; + searchstore->clearremote = searchstore_clearremote; + searchstore->result = searchstore_result; + +} diff --git a/src/map/searchstore.h b/src/map/searchstore.h index ffa8e9784..61e65c7d2 100644 --- a/src/map/searchstore.h +++ b/src/map/searchstore.h @@ -1,5 +1,6 @@ -// 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 _SEARCHSTORE_H_ #define _SEARCHSTORE_H_ @@ -7,8 +8,7 @@ #define SEARCHSTORE_RESULTS_PER_PAGE 10 /// information about the search being performed -struct s_search_store_search -{ +struct s_search_store_search { struct map_session_data* search_sd; // sd of the searching player const unsigned short* itemlist; const unsigned short* cardlist; @@ -18,9 +18,8 @@ struct s_search_store_search unsigned int max_price; }; -struct s_search_store_info_item -{ - int store_id; +struct s_search_store_info_item { + unsigned int store_id; int account_id; char store_name[MESSAGE_SIZE]; unsigned short nameid; @@ -30,8 +29,7 @@ struct s_search_store_info_item unsigned char refine; }; -struct s_search_store_info -{ +struct s_search_store_info { unsigned int count; struct s_search_store_info_item* items; unsigned int pages; // amount of pages already sent to client @@ -43,15 +41,21 @@ struct s_search_store_info bool open; }; -bool searchstore_open(struct map_session_data* sd, unsigned int uses, unsigned short effect); -void searchstore_query(struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count); -bool searchstore_querynext(struct map_session_data* sd); -void searchstore_next(struct map_session_data* sd); -void searchstore_clear(struct map_session_data* sd); -void searchstore_close(struct map_session_data* sd); -void searchstore_click(struct map_session_data* sd, int account_id, int store_id, unsigned short nameid); -bool searchstore_queryremote(struct map_session_data* sd, int account_id); -void searchstore_clearremote(struct map_session_data* sd); -bool searchstore_result(struct map_session_data* sd, int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine); +struct searchstore_interface { + bool (*open) (struct map_session_data* sd, unsigned int uses, unsigned short effect); + void (*query) (struct map_session_data* sd, unsigned char type, unsigned int min_price, unsigned int max_price, const unsigned short* itemlist, unsigned int item_count, const unsigned short* cardlist, unsigned int card_count); + bool (*querynext) (struct map_session_data* sd); + void (*next) (struct map_session_data* sd); + void (*clear) (struct map_session_data* sd); + void (*close) (struct map_session_data* sd); + void (*click) (struct map_session_data* sd, int account_id, int store_id, unsigned short nameid); + bool (*queryremote) (struct map_session_data* sd, int account_id); + void (*clearremote) (struct map_session_data* sd); + bool (*result) (struct map_session_data* sd, unsigned int store_id, int account_id, const char* store_name, unsigned short nameid, unsigned short amount, unsigned int price, const short* card, unsigned char refine); +} searchstore_s; + +struct searchstore_interface *searchstore; + +void searchstore_defaults (void); #endif // _SEARCHSTORE_H_ diff --git a/src/map/skill.c b/src/map/skill.c index a465410b2..06bfca5f8 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -62,8 +63,6 @@ static struct eri *skill_timer_ers = NULL; //For handling skill_timerskills [Sko DBMap* skillunit_db = NULL; // int id -> struct skill_unit* -DBMap* skilldb_name2id = NULL; - /** * Skill Cool Down Delay Saving * Struct skill_cd is not a member of struct map_session_data @@ -119,14 +118,8 @@ struct s_skill_unit_layout skill_unit_layout[MAX_SKILL_UNIT_LAYOUT]; int firewall_unit_pos; int icewall_unit_pos; int earthstrain_unit_pos; -//early declaration -int skill_block_check(struct block_list *bl, enum sc_type type, uint16 skill_id); -static int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); -static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); -static int skill_destroy_trap( struct block_list *bl, va_list ap ); //Since only mob-casted splash skills can hit ice-walls -static inline int splash_target(struct block_list* bl) -{ +static inline int splash_target(struct block_list* bl) { #ifndef RENEWAL return ( bl->type == BL_MOB ) ? BL_SKILL|BL_CHAR : BL_CHAR; #else // Some skills can now hit ground skills(traps, ice wall & etc.) @@ -135,8 +128,7 @@ static inline int splash_target(struct block_list* bl) } /// Returns the id of the skill, or 0 if not found. -int skill_name2id(const char* name) -{ +int skill_name2id(const char* name) { if( name == NULL ) return 0; @@ -145,8 +137,7 @@ int skill_name2id(const char* name) /// Maps skill ids to skill db offsets. /// Returns the skill's array index, or 0 (Unknown Skill). -int skill_get_index( uint16 skill_id ) -{ +int skill_get_index( uint16 skill_id ) { // avoid ranges reserved for mapping guild/homun/mercenary skills if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX) || (skill_id >= HM_SKILLRANGEMIN && skill_id <= HM_SKILLRANGEMAX) @@ -163,7 +154,20 @@ int skill_get_index( uint16 skill_id ) skill_id = MC_SKILLRANGEMIN + skill_id - MC_SKILLBASE; else if( skill_id >= HM_SKILLBASE ) skill_id = HM_SKILLRANGEMIN + skill_id - HM_SKILLBASE; - + //[Ind/Hercules] GO GO GO LESS! - http://hercules.ws/board/topic/512-skill-id-processing-overhaul/ + else if( skill_id > 1019 && skill_id < 8001 ) { + if( skill_id < 2058 ) // 1020 - 2000 are empty + skill_id = 1020 + skill_id - 2001; + else if( skill_id < 2549 ) // 2058 - 2200 are empty - 1020+57 + skill_id = (1077) + skill_id - 2201; + else if ( skill_id < 3036 ) // 2549 - 3000 are empty - 1020+57+348 + skill_id = (1425) + skill_id - 3001; + else if ( skill_id < 5019 ) // 3036 - 5000 are empty - 1020+57+348+35 + skill_id = (1460) + skill_id - 5001; + else + ShowWarning("skill_get_index: skill id '%d' is not being handled!\n",skill_id); + } + // validate result if( !skill_id || skill_id >= MAX_SKILL_DB ) return 0; @@ -171,71 +175,66 @@ int skill_get_index( uint16 skill_id ) return skill_id; } -const char* skill_get_name( uint16 skill_id ) -{ - return skill_db[skill_get_index(skill_id)].name; +const char* skill_get_name( uint16 skill_id ) { + return skill_db[skill->get_index(skill_id)].name; } -const char* skill_get_desc( uint16 skill_id ) -{ - return skill_db[skill_get_index(skill_id)].desc; +const char* skill_get_desc( uint16 skill_id ) { + return skill_db[skill->get_index(skill_id)].desc; } // out of bounds error checking [celest] -static void skill_chk(int16* skill_id, uint16 skill_lv) -{ - *skill_id = skill_get_index(*skill_id); // checks/adjusts id - if( skill_lv > MAX_SKILL_LEVEL ) *skill_id = 0; +void skill_chk(int16* skill_id) { + *skill_id = skill->get_index(*skill_id); // checks/adjusts id } -#define skill_get(var,id,lv) { skill_chk(&id,lv); if(!id) return 0; return var; } - +#define skill_get(var,id) { skill->chk(&id); if(!id) return 0; return var; } +#define skill_get2(var,id,lv) { skill->chk(&id); if(!id) return 0; if( lv > MAX_SKILL_LEVEL ) { int lv2 = lv; lv = skill_db[id].max; return (var) + (lv2-lv); } return var; } // Skill DB -int skill_get_hit( uint16 skill_id ) { skill_get (skill_db[skill_id].hit, skill_id, 1); } -int skill_get_inf( uint16 skill_id ) { skill_get (skill_db[skill_id].inf, skill_id, 1); } -int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get (skill_db[skill_id].element[skill_lv-1], skill_id, skill_lv); } -int skill_get_nk( uint16 skill_id ) { skill_get (skill_db[skill_id].nk, skill_id, 1); } -int skill_get_max( uint16 skill_id ) { skill_get (skill_db[skill_id].max, skill_id, 1); } -int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get (skill_db[skill_id].range[skill_lv-1], skill_id, skill_lv); } -int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get ( (skill_db[skill_id].splash[skill_lv-1]>=0?skill_db[skill_id].splash[skill_lv-1]:AREA_SIZE), skill_id, skill_lv); } -int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].hp[skill_lv-1], skill_id, skill_lv); } -int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].sp[skill_lv-1], skill_id, skill_lv); } -int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].hp_rate[skill_lv-1], skill_id, skill_lv); } -int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].sp_rate[skill_lv-1], skill_id, skill_lv); } -int skill_get_state(uint16 skill_id) { skill_get (skill_db[skill_id].state, skill_id, 1); } -int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get (skill_db[skill_id].spiritball[skill_lv-1], skill_id, skill_lv); } -int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].itemid[idx], skill_id, 1); } -int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].amount[idx], skill_id, 1); } -int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].zeny[skill_lv-1], skill_id, skill_lv); } -int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].num[skill_lv-1], skill_id, skill_lv); } -int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].cast[skill_lv-1], skill_id, skill_lv); } -int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].delay[skill_lv-1], skill_id, skill_lv); } -int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].walkdelay[skill_lv-1], skill_id, skill_lv); } -int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].upkeep_time[skill_lv-1], skill_id, skill_lv); } -int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].upkeep_time2[skill_lv-1], skill_id, skill_lv); } -int skill_get_castdef( uint16 skill_id ) { skill_get (skill_db[skill_id].cast_def_rate, skill_id, 1); } -int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_db[skill_id].weapon, skill_id, 1); } -int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_db[skill_id].ammo, skill_id, 1); } -int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].ammo_qty[skill_lv-1], skill_id, skill_lv); } -int skill_get_inf2( uint16 skill_id ) { skill_get (skill_db[skill_id].inf2, skill_id, 1); } -int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_db[skill_id].castcancel, skill_id, 1); } -int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].maxcount[skill_lv-1], skill_id, skill_lv); } -int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].blewcount[skill_lv-1], skill_id, skill_lv); } -int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].mhp[skill_lv-1], skill_id, skill_lv); } -int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get (skill_db[skill_id].castnodex[skill_lv-1], skill_id, skill_lv); } -int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get (skill_db[skill_id].delaynodex[skill_lv-1], skill_id, skill_lv); } -int skill_get_nocast ( uint16 skill_id ) { skill_get (skill_db[skill_id].nocast, skill_id, 1); } -int skill_get_type( uint16 skill_id ) { skill_get (skill_db[skill_id].skill_type, skill_id, 1); } -int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill_db[skill_id].unit_id[flag], skill_id, 1); } -int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_interval, skill_id, 1); } -int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ){ skill_get (skill_db[skill_id].unit_range[skill_lv-1], skill_id, skill_lv); } -int skill_get_unit_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BCT_ALL, skill_id, 1); } -int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BL_ALL, skill_id, 1); } -int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_flag, skill_id, 1); } -int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get (skill_db[skill_id].unit_layout_type[skill_lv-1], skill_id, skill_lv); } -int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get (skill_db[skill_id].cooldown[skill_lv-1], skill_id, skill_lv); } +int skill_get_hit( uint16 skill_id ) { skill_get (skill_db[skill_id].hit, skill_id); } +int skill_get_inf( uint16 skill_id ) { skill_get (skill_db[skill_id].inf, skill_id); } +int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_db[skill_id].element[skill_lv-1], skill_id, skill_lv); } +int skill_get_nk( uint16 skill_id ) { skill_get (skill_db[skill_id].nk, skill_id); } +int skill_get_max( uint16 skill_id ) { skill_get (skill_db[skill_id].max, skill_id); } +int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill_db[skill_id].range[skill_lv-1], skill_id, skill_lv); } +int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill_db[skill_id].splash[skill_lv-1]>=0?skill_db[skill_id].splash[skill_lv-1]:AREA_SIZE), skill_id, skill_lv); } +int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].hp[skill_lv-1], skill_id, skill_lv); } +int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].sp[skill_lv-1], skill_id, skill_lv); } +int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].hp_rate[skill_lv-1], skill_id, skill_lv); } +int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].sp_rate[skill_lv-1], skill_id, skill_lv); } +int skill_get_state(uint16 skill_id) { skill_get (skill_db[skill_id].state, skill_id); } +int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get2 (skill_db[skill_id].spiritball[skill_lv-1], skill_id, skill_lv); } +int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].itemid[idx], skill_id); } +int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill_db[skill_id].amount[idx], skill_id); } +int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].zeny[skill_lv-1], skill_id, skill_lv); } +int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].num[skill_lv-1], skill_id, skill_lv); } +int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cast[skill_lv-1], skill_id, skill_lv); } +int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].delay[skill_lv-1], skill_id, skill_lv); } +int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].walkdelay[skill_lv-1], skill_id, skill_lv); } +int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time[skill_lv-1], skill_id, skill_lv); } +int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].upkeep_time2[skill_lv-1], skill_id, skill_lv); } +int skill_get_castdef( uint16 skill_id ) { skill_get (skill_db[skill_id].cast_def_rate, skill_id); } +int skill_get_weapontype( uint16 skill_id ) { skill_get (skill_db[skill_id].weapon, skill_id); } +int skill_get_ammotype( uint16 skill_id ) { skill_get (skill_db[skill_id].ammo, skill_id); } +int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].ammo_qty[skill_lv-1], skill_id, skill_lv); } +int skill_get_inf2( uint16 skill_id ) { skill_get (skill_db[skill_id].inf2, skill_id); } +int skill_get_castcancel( uint16 skill_id ) { skill_get (skill_db[skill_id].castcancel, skill_id); } +int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].maxcount[skill_lv-1], skill_id, skill_lv); } +int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].blewcount[skill_lv-1], skill_id, skill_lv); } +int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].mhp[skill_lv-1], skill_id, skill_lv); } +int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill_db[skill_id].castnodex[skill_lv-1], skill_id, skill_lv); } +int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].delaynodex[skill_lv-1], skill_id, skill_lv); } +int skill_get_type( uint16 skill_id ) { skill_get (skill_db[skill_id].skill_type, skill_id); } +int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill_db[skill_id].unit_id[flag], skill_id); } +int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_interval, skill_id); } +int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].unit_range[skill_lv-1], skill_id, skill_lv); } +int skill_get_unit_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BCT_ALL, skill_id); } +int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_target&BL_ALL, skill_id); } +int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill_db[skill_id].unit_flag, skill_id); } +int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].unit_layout_type[skill_lv-1], skill_id, skill_lv); } +int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill_db[skill_id].cooldown[skill_lv-1], skill_id, skill_lv); } #ifdef RENEWAL_CAST -int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ){ skill_get (skill_db[skill_id].fixed_cast[skill_lv-1], skill_id, skill_lv); } +int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill_db[skill_id].fixed_cast[skill_lv-1], skill_id, skill_lv); } #endif int skill_tree_get_max(uint16 skill_id, int b_class) { @@ -246,124 +245,123 @@ int skill_tree_get_max(uint16 skill_id, int b_class) if( i < MAX_SKILL_TREE && skill_tree[b_class][i].id == skill_id ) return skill_tree[b_class][i].max; else - return skill_get_max(skill_id); + return skill->get_max(skill_id); } -int skill_frostjoke_scream(struct block_list *bl,va_list ap); -int skill_attack_area(struct block_list *bl,va_list ap); -struct skill_unit_group *skill_locate_element_field(struct block_list *bl); // [Skotlex] -int skill_graffitiremover(struct block_list *bl, va_list ap); // [Valaris] -int skill_greed(struct block_list *bl, va_list ap); -static void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id); -static int skill_cell_overlap(struct block_list *bl, va_list ap); -static int skill_trap_splash(struct block_list *bl, va_list ap); -struct skill_unit_group_tickset *skill_unitgrouptickset_search(struct block_list *bl,struct skill_unit_group *sg,int tick); -static int skill_unit_onplace(struct skill_unit *src,struct block_list *bl,unsigned int tick); -static int skill_unit_onleft(uint16 skill_id, struct block_list *bl,unsigned int tick); -static int skill_unit_effect(struct block_list *bl,va_list ap); - int enchant_eff[5] = { 10, 14, 17, 19, 20 }; int deluge_eff[5] = { 5, 9, 12, 14, 15 }; -int skill_get_casttype (uint16 skill_id) -{ - int inf = skill_get_inf(skill_id); +int skill_get_casttype (uint16 skill_id) { + int inf = skill->get_inf(skill_id); + if (inf&(INF_GROUND_SKILL)) + return CAST_GROUND; + if (inf&INF_SUPPORT_SKILL) + return CAST_NODAMAGE; + if (inf&INF_SELF_SKILL) { + if(skill->get_inf2(skill_id)&INF2_NO_TARGET_SELF) + return CAST_DAMAGE; //Combo skill. + return CAST_NODAMAGE; + } + if (skill->get_nk(skill_id)&NK_NO_DAMAGE) + return CAST_NODAMAGE; + return CAST_DAMAGE; +} + +int skill_get_casttype2 (uint16 index) { + int inf = skill_db[index].inf; if (inf&(INF_GROUND_SKILL)) return CAST_GROUND; if (inf&INF_SUPPORT_SKILL) return CAST_NODAMAGE; if (inf&INF_SELF_SKILL) { - if(skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF) + if(skill_db[index].inf2&INF2_NO_TARGET_SELF) return CAST_DAMAGE; //Combo skill. return CAST_NODAMAGE; } - if (skill_get_nk(skill_id)&NK_NO_DAMAGE) + if (skill_db[index].nk&NK_NO_DAMAGE) return CAST_NODAMAGE; return CAST_DAMAGE; } //Returns actual skill range taking into account attack range and AC_OWL [Skotlex] -int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) -{ +int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { int range; if( bl->type == BL_MOB && battle_config.mob_ai&0x400 ) return 9; //Mobs have a range of 9 regardless of skill used. - range = skill_get_range(skill_id, skill_lv); + range = skill->get_range(skill_id, skill_lv); - if( range < 0 ) - { + if( range < 0 ) { if( battle_config.use_weapon_skill_range&bl->type ) return status_get_range(bl); range *=-1; } //TODO: Find a way better than hardcoding the list of skills affected by AC_VULTURE - switch( skill_id ) - { - case AC_SHOWER: case MA_SHOWER: - case AC_DOUBLE: case MA_DOUBLE: - case HT_BLITZBEAT: - case AC_CHARGEARROW: - case MA_CHARGEARROW: - case SN_FALCONASSAULT: - case HT_POWER: - /** - * Ranger - **/ - case RA_ARROWSTORM: - case RA_AIMEDBOLT: - case RA_WUGBITE: - if( bl->type == BL_PC ) - range += pc_checkskill((TBL_PC*)bl, AC_VULTURE); - else - range += 10; //Assume level 10? - break; - // added to allow GS skills to be effected by the range of Snake Eyes [Reddozen] - case GS_RAPIDSHOWER: - case GS_PIERCINGSHOT: - case GS_FULLBUSTER: - case GS_SPREADATTACK: - case GS_GROUNDDRIFT: - if (bl->type == BL_PC) - range += pc_checkskill((TBL_PC*)bl, GS_SNAKEEYE); - else - range += 10; //Assume level 10? - break; - case NJ_KIRIKAGE: - if (bl->type == BL_PC) - range = skill_get_range(NJ_SHADOWJUMP,pc_checkskill((TBL_PC*)bl,NJ_SHADOWJUMP)); - break; - /** - * Warlock - **/ - case WL_WHITEIMPRISON: - case WL_SOULEXPANSION: - case WL_FROSTMISTY: - case WL_MARSHOFABYSS: - case WL_SIENNAEXECRATE: - case WL_DRAINLIFE: - case WL_CRIMSONROCK: - case WL_HELLINFERNO: - case WL_COMET: - case WL_CHAINLIGHTNING: - case WL_TETRAVORTEX: - case WL_RELEASE: + switch( skill_id ) { + case AC_SHOWER: case MA_SHOWER: + case AC_DOUBLE: case MA_DOUBLE: + case HT_BLITZBEAT: + case AC_CHARGEARROW: + case MA_CHARGEARROW: + case SN_FALCONASSAULT: + case HT_POWER: + /** + * Ranger + **/ + case RA_ARROWSTORM: + case RA_AIMEDBOLT: + case RA_WUGBITE: if( bl->type == BL_PC ) - range += pc_checkskill((TBL_PC*)bl, WL_RADIUS); + range += pc_checkskill((TBL_PC*)bl, AC_VULTURE); + else + range += 10; //Assume level 10? break; - /** - * Ranger Bonus - **/ - case HT_LANDMINE: - case HT_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case RA_CLUSTERBOMB: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - if( bl->type == BL_PC ) - range += (1 + pc_checkskill((TBL_PC*)bl, RA_RESEARCHTRAP))/2; + // added to allow GS skills to be effected by the range of Snake Eyes [Reddozen] + case GS_RAPIDSHOWER: + case GS_PIERCINGSHOT: + case GS_FULLBUSTER: + case GS_SPREADATTACK: + case GS_GROUNDDRIFT: + if (bl->type == BL_PC) + range += pc_checkskill((TBL_PC*)bl, GS_SNAKEEYE); + else + range += 10; //Assume level 10? + break; + case NJ_KIRIKAGE: + if (bl->type == BL_PC) + range = skill->get_range(NJ_SHADOWJUMP,pc_checkskill((TBL_PC*)bl,NJ_SHADOWJUMP)); + break; + /** + * Warlock + **/ + case WL_WHITEIMPRISON: + case WL_SOULEXPANSION: + case WL_FROSTMISTY: + case WL_MARSHOFABYSS: + case WL_SIENNAEXECRATE: + case WL_DRAINLIFE: + case WL_CRIMSONROCK: + case WL_HELLINFERNO: + case WL_COMET: + case WL_CHAINLIGHTNING: + case WL_TETRAVORTEX: + case WL_RELEASE: + if( bl->type == BL_PC ) + range += pc_checkskill((TBL_PC*)bl, WL_RADIUS); + break; + /** + * Ranger Bonus + **/ + case HT_LANDMINE: + case HT_FREEZINGTRAP: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case RA_CLUSTERBOMB: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + if( bl->type == BL_PC ) + range += (1 + pc_checkskill((TBL_PC*)bl, RA_RESEARCHTRAP))/2; } if( !range && bl->type != BL_PC ) @@ -399,7 +397,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk #ifdef RENEWAL /** * Renewal Heal Formula - * Formula: ( [(Base Level + INT) / 5] × 30 ) × (Heal Level / 10) × (Modifiers) + MATK + * Formula: ( [(Base Level + INT) / 5] × 30 ) × (Heal Level / 10) × (Modifiers) + MATK **/ hp = (status_get_lv(src) + status_get_int(src)) / 5 * 30 * skill_lv / 10; #else @@ -407,7 +405,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk #endif if( sd && ((skill = pc_checkskill(sd, HP_MEDITATIO)) > 0) ) hp += hp * skill * 2 / 100; - else if( src->type == BL_HOM && (skill = merc_hom_checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 ) + else if( src->type == BL_HOM && (skill = homun->checkskill(((TBL_HOM*)src), HLIF_BRAIN)) > 0 ) hp += hp * skill * 2 / 100; break; } @@ -442,10 +440,11 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk default: { struct status_data *status = status_get_status_data(src); - int min, max, wMatk, variance; + int min, max; min = max = status_base_matk(status, status_get_lv(src)); if( status->rhw.matk > 0 ){ + int wMatk, variance; wMatk = status->rhw.matk; variance = wMatk * status->rhw.wlv / 10; min += wMatk - variance; @@ -474,7 +473,7 @@ int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 sk int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* bl) { // Never copy NPC/Wedding Skills - if (skill_get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL)) + if (skill->get_inf2(skill_id)&(INF2_NPC_SKILL|INF2_WEDDING_SKILL)) return 0; // High-class skills @@ -496,7 +495,7 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b if( !(sd->sc.data[SC__REPRODUCE]) && (skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) ) return 0; // Reproduce will only copy skills according on the list. [Jobbie] - else if( sd->sc.data[SC__REPRODUCE] && !skill_reproduce_db[skill_id] ) + else if( sd->sc.data[SC__REPRODUCE] && !skill_reproduce_db[skill->get_index(skill_id)] ) return 0; return 1; @@ -508,7 +507,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) int16 idx,m; nullpo_retr (1, sd); m = sd->bl.m; - idx = skill_get_index(skill_id); + idx = skill->get_index(skill_id); if (idx == 0) return 1; // invalid skill id @@ -529,27 +528,19 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) return 1; } - if (sd->blockskill[idx] > 0){ - clif_skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); + if (sd->blockskill[idx] > 0) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return 1; } + /** - * It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions above + * It has been confirmed on a official server (thanks to Yommy) that item-cast skills bypass all the restrictions below * Also, without this check, an exploit where an item casting + healing (or any other kind buff) isn't deleted after used on a restricted map **/ if( sd->skillitem == skill_id ) return 0; - // Check skill restrictions [Celest] - if( (!map_flag_vs(m) && skill_get_nocast (skill_id) & 1) || - (map[m].flag.pvp && skill_get_nocast (skill_id) & 2) || - (map_flag_gvg(m) && skill_get_nocast (skill_id) & 4) || - (map[m].flag.battleground && skill_get_nocast (skill_id) & 8) || - (map[m].flag.restricted && map[m].zone && skill_get_nocast (skill_id) & (8*map[m].zone)) ){ - clif_msg(sd, 0x536); // This skill cannot be used within this area - return 1; - } - - if( sd->sc.option&OPTION_MOUNTING ) + + if( sd->sc.data[SC_ALL_RIDING] ) return 1;//You can't use skills while in the new mounts (The client doesn't let you, this is to make cheat-safe) switch (skill_id) { @@ -557,7 +548,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) case RETURN_TO_ELDICASTES: case ALL_GUARDIAN_RECALL: if(map[m].flag.nowarp) { - clif_skill_teleportmessage(sd,0); + clif->skill_teleportmessage(sd,0); return 1; } return 0; @@ -565,32 +556,40 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) case SC_FATALMENACE: case SC_DIMENSIONDOOR: if(map[m].flag.noteleport) { - clif_skill_teleportmessage(sd,0); + clif->skill_teleportmessage(sd,0); return 1; } - return 0; // gonna be checked in 'skill_castend_nodamage_id' + return 0; // gonna be checked in 'skill->castend_nodamage_id' case WE_CALLPARTNER: case WE_CALLPARENT: case WE_CALLBABY: if (map[m].flag.nomemo) { - clif_skill_teleportmessage(sd,1); + clif->skill_teleportmessage(sd,1); return 1; } break; case MC_VENDING: - case MC_IDENTIFY: case ALL_BUYING_STORE: + if( npc_isnear(&sd->bl) ) { + // uncomment for more verbose message. + //char output[150]; + //sprintf(output, msg_txt(662), battle_config.min_npc_vendchat_distance); + //clif->message(sd->fd, output); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_THERE_ARE_NPC_AROUND,0); + return 1; + } + case MC_IDENTIFY: return 0; // always allowed case WZ_ICEWALL: // noicewall flag [Valaris] if (map[m].flag.noicewall) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; } break; case GC_DARKILLUSION: if( map_flag_gvg(m) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; } break; @@ -600,7 +599,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) !(battle_config.emergency_call&(map[m].flag.gvg || map[m].flag.gvg_castle?8:4)) || (battle_config.emergency_call&16 && map[m].flag.nowarpto && !map[m].flag.gvg_castle) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; } break; @@ -617,7 +616,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) * These skills cannot be used while in mado gear (credits to Xantara) **/ if( pc_ismadogear(sd) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; } break; @@ -628,7 +627,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) case WM_LULLABY_DEEPSLEEP: case WM_SATURDAY_NIGHT_FEVER: if( !map_flag_vs(m) ) { - clif_skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. + clif->skill_teleportmessage(sd,2); // This skill uses this msg instead of skill fails. return 1; } break; @@ -639,7 +638,7 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd) int skillnotok_hom(uint16 skill_id, struct homun_data *hd) { - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); nullpo_retr(1,hd); if (idx == 0) @@ -665,12 +664,12 @@ int skillnotok_hom(uint16 skill_id, struct homun_data *hd) } //Use master's criteria. - return skillnotok(skill_id, hd->master); + return skill->not_ok(skill_id, hd->master); } int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md) { - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); nullpo_retr(1,md); if( idx == 0 ) @@ -678,12 +677,11 @@ int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md) if( md->blockskill[idx] > 0 ) return 1; - return skillnotok(skill_id, md->master); + return skill->not_ok(skill_id, md->master); } -struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill_lv, struct block_list* src, int x, int y) -{ - int pos = skill_get_unit_layout_type(skill_id,skill_lv); +struct s_skill_unit_layout* skill_get_unit_layout (uint16 skill_id, uint16 skill_lv, struct block_list* src, int x, int y) { + int pos = skill->get_unit_layout_type(skill_id,skill_lv); uint8 dir; if (pos < -1 || pos >= MAX_SKILL_UNIT_LAYOUT) { @@ -718,7 +716,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint struct status_change *sc, *tsc; enum sc_type status; - int skill; + int temp; int rate; nullpo_ret(src); @@ -742,21 +740,19 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint //So if the target can't be inflicted with statuses, this is pointless. return 0; - if( sd ) - { // These statuses would be applied anyway even if the damage was blocked by some skills. [Inkfish] - if( skill_id != WS_CARTTERMINATION && skill_id != AM_DEMONSTRATION && skill_id != CR_REFLECTSHIELD && skill_id != MS_REFLECTSHIELD && skill_id != ASC_BREAKER ) - { // Trigger status effects + if( sd ) { // These statuses would be applied anyway even if the damage was blocked by some skills. [Inkfish] + if( skill_id != WS_CARTTERMINATION && skill_id != AM_DEMONSTRATION && skill_id != CR_REFLECTSHIELD && skill_id != MS_REFLECTSHIELD && skill_id != ASC_BREAKER ) { + // Trigger status effects enum sc_type type; int i; - for( i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++ ) - { + for( i = 0; i < ARRAYLENGTH(sd->addeff) && sd->addeff[i].flag; i++ ) { rate = sd->addeff[i].rate; if( attack_type&BF_LONG ) // Any ranged physical attack takes status arrows into account (Grimtooth...) [DracoRPG] rate += sd->addeff[i].arrow_rate; if( !rate ) continue; - if( (sd->addeff[i].flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)) != (ATF_WEAPON|ATF_MAGIC|ATF_MISC) ) - { // Trigger has attack type consideration. + if( (sd->addeff[i].flag&(ATF_WEAPON|ATF_MAGIC|ATF_MISC)) != (ATF_WEAPON|ATF_MAGIC|ATF_MISC) ) { + // Trigger has attack type consideration. if( (sd->addeff[i].flag&ATF_WEAPON && attack_type&BF_WEAPON) || (sd->addeff[i].flag&ATF_MAGIC && attack_type&BF_MAGIC) || (sd->addeff[i].flag&ATF_MISC && attack_type&BF_MISC) ) ; @@ -764,39 +760,38 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint continue; } - if( (sd->addeff[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT) ) - { // Trigger has range consideration. + if( (sd->addeff[i].flag&(ATF_LONG|ATF_SHORT)) != (ATF_LONG|ATF_SHORT) ) { + // Trigger has range consideration. if((sd->addeff[i].flag&ATF_LONG && !(attack_type&BF_LONG)) || (sd->addeff[i].flag&ATF_SHORT && !(attack_type&BF_SHORT))) continue; //Range Failed. } type = sd->addeff[i].id; - skill = skill_get_time2(status_sc2skill(type),7); + temp = skill->get_time2(status_sc2skill(type),7); if (sd->addeff[i].flag&ATF_TARGET) - status_change_start(bl,type,rate,7,0,0,0,skill,0); + status_change_start(bl,type,rate,7,0,0,0,temp,0); if (sd->addeff[i].flag&ATF_SELF) - status_change_start(src,type,rate,7,0,0,0,skill,0); + status_change_start(src,type,rate,7,0,0,0,temp,0); } } - if( skill_id ) - { // Trigger status effects on skills + if( skill_id ) { + // Trigger status effects on skills enum sc_type type; int i; - for( i = 0; i < ARRAYLENGTH(sd->addeff3) && sd->addeff3[i].skill; i++ ) - { + for( i = 0; i < ARRAYLENGTH(sd->addeff3) && sd->addeff3[i].skill; i++ ) { if( skill_id != sd->addeff3[i].skill || !sd->addeff3[i].rate ) continue; type = sd->addeff3[i].id; - skill = skill_get_time2(status_sc2skill(type),7); + temp = skill->get_time2(status_sc2skill(type),7); if( sd->addeff3[i].target&ATF_TARGET ) - status_change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,skill,0); + status_change_start(bl,type,sd->addeff3[i].rate,7,0,0,0,temp,0); if( sd->addeff3[i].target&ATF_SELF ) - status_change_start(src,type,sd->addeff3[i].rate,7,0,0,0,skill,0); + status_change_start(src,type,sd->addeff3[i].rate,7,0,0,0,temp,0); } } } @@ -804,615 +799,613 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if( dmg_lv < ATK_DEF ) // no damage, return; return 0; - switch(skill_id) - { - case 0: // Normal attacks (no skill used) - { - if( attack_type&BF_SKILL ) - break; // If a normal attack is a skill, it's splash damage. [Inkfish] - if(sd) { - // Automatic trigger of Blitz Beat - if (pc_isfalcon(sd) && sd->status.weapon == W_BOW && (skill=pc_checkskill(sd,HT_BLITZBEAT))>0 && - rnd()%1000 <= sstatus->luk*10/3+1 ) { - rate=(sd->status.job_level+9)/10; - skill_castend_damage_id(src,bl,HT_BLITZBEAT,(skill<rate)?skill:rate,tick,SD_LEVEL); - } - // Automatic trigger of Warg Strike [Jobbie] - if( pc_iswug(sd) && (sd->status.weapon == W_BOW || sd->status.weapon == W_FIST) && (skill=pc_checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*10/3+1 ) - skill_castend_damage_id(src,bl,RA_WUGSTRIKE,skill,tick,0); - // Gank - if(dstmd && sd->status.weapon != W_BOW && - (skill=pc_checkskill(sd,RG_SNATCHER)) > 0 && - (skill*15 + 55) + pc_checkskill(sd,TF_STEAL)*10 > rnd()%1000) { - if(pc_steal_item(sd,bl,pc_checkskill(sd,TF_STEAL))) - clif_skill_nodamage(src,bl,TF_STEAL,skill,1); - else - clif_skill_fail(sd,RG_SNATCHER,USESKILL_FAIL_LEVEL,0); - } - // Chance to trigger Taekwon kicks [Dralnu] - if(sc && !sc->data[SC_COMBO]) { - if(sc->data[SC_READYSTORM] && - sc_start(src,SC_COMBO, 15, TK_STORMKICK, - (2000 - 4*sstatus->agi - 2*sstatus->dex))) - ; //Stance triggered - else if(sc->data[SC_READYDOWN] && - sc_start(src,SC_COMBO, 15, TK_DOWNKICK, - (2000 - 4*sstatus->agi - 2*sstatus->dex))) - ; //Stance triggered - else if(sc->data[SC_READYTURN] && - sc_start(src,SC_COMBO, 15, TK_TURNKICK, - (2000 - 4*sstatus->agi - 2*sstatus->dex))) - ; //Stance triggered - else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka] - rate = 20; - if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) { - rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; - status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); + switch(skill_id) { + case 0: { // Normal attacks (no skill used) + if( attack_type&BF_SKILL ) + break; // If a normal attack is a skill, it's splash damage. [Inkfish] + if(sd) { + // Automatic trigger of Blitz Beat + if (pc_isfalcon(sd) && sd->status.weapon == W_BOW && (temp=pc_checkskill(sd,HT_BLITZBEAT))>0 && + rnd()%1000 <= sstatus->luk*10/3+1 ) { + rate=(sd->status.job_level+9)/10; + skill->castend_damage_id(src,bl,HT_BLITZBEAT,(temp<rate)?temp:rate,tick,SD_LEVEL); + } + // Automatic trigger of Warg Strike [Jobbie] + if( pc_iswug(sd) && (sd->status.weapon == W_BOW || sd->status.weapon == W_FIST) && (temp=pc_checkskill(sd,RA_WUGSTRIKE)) > 0 && rnd()%1000 <= sstatus->luk*10/3+1 ) + skill->castend_damage_id(src,bl,RA_WUGSTRIKE,temp,tick,0); + // Gank + if(dstmd && sd->status.weapon != W_BOW && + (temp=pc_checkskill(sd,RG_SNATCHER)) > 0 && + (temp*15 + 55) + pc_checkskill(sd,TF_STEAL)*10 > rnd()%1000) { + if(pc_steal_item(sd,bl,pc_checkskill(sd,TF_STEAL))) + clif->skill_nodamage(src,bl,TF_STEAL,temp,1); + else + clif->skill_fail(sd,RG_SNATCHER,USESKILL_FAIL_LEVEL,0); + } + // Chance to trigger Taekwon kicks [Dralnu] + if(sc && !sc->data[SC_COMBO]) { + if(sc->data[SC_READYSTORM] && + sc_start(src,SC_COMBO, 15, TK_STORMKICK, + (2000 - 4*sstatus->agi - 2*sstatus->dex))) + ; //Stance triggered + else if(sc->data[SC_READYDOWN] && + sc_start(src,SC_COMBO, 15, TK_DOWNKICK, + (2000 - 4*sstatus->agi - 2*sstatus->dex))) + ; //Stance triggered + else if(sc->data[SC_READYTURN] && + sc_start(src,SC_COMBO, 15, TK_TURNKICK, + (2000 - 4*sstatus->agi - 2*sstatus->dex))) + ; //Stance triggered + else if (sc->data[SC_READYCOUNTER]) { //additional chance from SG_FRIEND [Komurka] + rate = 20; + if (sc->data[SC_SKILLRATE_UP] && sc->data[SC_SKILLRATE_UP]->val1 == TK_COUNTER) { + rate += rate*sc->data[SC_SKILLRATE_UP]->val2/100; + status_change_end(src, SC_SKILLRATE_UP, INVALID_TIMER); + } + sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id, + (2000 - 4*sstatus->agi - 2*sstatus->dex)); } - sc_start2(src, SC_COMBO, rate, TK_COUNTER, bl->id, - (2000 - 4*sstatus->agi - 2*sstatus->dex)); } + if(sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1) ) + skill->castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0); } - if(sc && sc->data[SC_PYROCLASTIC] && (rnd() % 1000 <= sstatus->luk * 10 / 3 + 1) ) - skill_castend_pos2(src, bl->x, bl->y, BS_HAMMERFALL,sc->data[SC_PYROCLASTIC]->val1, tick, 0); - } - - if (sc) { - struct status_change_entry *sce; - // Enchant Poison gives a chance to poison attacked enemies - if((sce=sc->data[SC_ENCPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. - status_change_start(bl,SC_POISON,sce->val2, sce->val1,src->id,0,0, - skill_get_time2(AS_ENCHANTPOISON,sce->val1),0); - // Enchant Deadly Poison gives a chance to deadly poison attacked enemies - if((sce=sc->data[SC_EDP])) - sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0, - skill_get_time2(ASC_EDP,sce->val1)); - } - } - break; - case SM_BASH: - if( sd && skill_lv > 5 && pc_checkskill(sd,SM_FATALBLOW)>0 ){ - //TODO: How much % per base level it actually is? - sc_start(bl,SC_STUN,(5*(skill_lv-5)+(int)sd->status.base_level/10), - skill_lv,skill_get_time2(SM_FATALBLOW,skill_lv)); + if (sc) { + struct status_change_entry *sce; + // Enchant Poison gives a chance to poison attacked enemies + if((sce=sc->data[SC_ENCPOISON])) //Don't use sc_start since chance comes in 1/10000 rate. + status_change_start(bl,SC_POISON,sce->val2, sce->val1,src->id,0,0, + skill->get_time2(AS_ENCHANTPOISON,sce->val1),0); + // Enchant Deadly Poison gives a chance to deadly poison attacked enemies + if((sce=sc->data[SC_EDP])) + sc_start4(bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0, + skill->get_time2(ASC_EDP,sce->val1)); + } } break; - case MER_CRASH: - sc_start(bl,SC_STUN,(6*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case SM_BASH: + if( sd && skill_lv > 5 && pc_checkskill(sd,SM_FATALBLOW)>0 ){ + //TODO: How much % per base level it actually is? + sc_start(bl,SC_STUN,(5*(skill_lv-5)+(int)sd->status.base_level/10), + skill_lv,skill->get_time2(SM_FATALBLOW,skill_lv)); + } + break; - case AS_VENOMKNIFE: - if (sd) //Poison chance must be that of Envenom. [Skotlex] - skill_lv = pc_checkskill(sd, TF_POISON); - case TF_POISON: - case AS_SPLASHER: - if(!sc_start2(bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill_get_time2(skill_id,skill_lv)) - && sd && skill_id==TF_POISON - ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case MER_CRASH: + sc_start(bl,SC_STUN,(6*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case AS_SONICBLOW: - sc_start(bl,SC_STUN,(2*skill_lv+10),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case AS_VENOMKNIFE: + if (sd) //Poison chance must be that of Envenom. [Skotlex] + skill_lv = pc_checkskill(sd, TF_POISON); + case TF_POISON: + case AS_SPLASHER: + if(!sc_start2(bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)) + && sd && skill_id==TF_POISON + ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; - case WZ_FIREPILLAR: - unit_set_walkdelay(bl, tick, skill_get_time2(skill_id, skill_lv), 1); - break; + case AS_SONICBLOW: + sc_start(bl,SC_STUN,(2*skill_lv+10),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case MG_FROSTDIVER: -#ifndef RENEWAL - case WZ_FROSTNOVA: -#endif - sc_start(bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case WZ_FIREPILLAR: + unit_set_walkdelay(bl, tick, skill->get_time2(skill_id, skill_lv), 1); + break; -#ifdef RENEWAL - case WZ_FROSTNOVA: - sc_start(bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; -#endif + case MG_FROSTDIVER: + #ifndef RENEWAL + case WZ_FROSTNOVA: + #endif + sc_start(bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case WZ_STORMGUST: - /** - * Storm Gust counter was dropped in renewal - **/ #ifdef RENEWAL - sc_start(bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv)); - #else - //Tharis pointed out that this is normal freeze chance with a base of 300% - if(tsc->sg_counter >= 3 && - sc_start(bl,SC_FREEZE,300,skill_lv,skill_get_time2(skill_id,skill_lv))) - tsc->sg_counter = 0; + case WZ_FROSTNOVA: + sc_start(bl,SC_FREEZE,skill_lv*5+33,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + #endif + + case WZ_STORMGUST: /** - * being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value + * Storm Gust counter was dropped in renewal **/ - else if( tsc->sg_counter > 250 ) - tsc->sg_counter = 0; - #endif - break; + #ifdef RENEWAL + sc_start(bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + #else + //Tharis pointed out that this is normal freeze chance with a base of 300% + if(tsc->sg_counter >= 3 && + sc_start(bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv))) + tsc->sg_counter = 0; + /** + * being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value + **/ + else if( tsc->sg_counter > 250 ) + tsc->sg_counter = 0; + #endif + break; - case WZ_METEOR: - sc_start(bl,SC_STUN,3*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case WZ_METEOR: + sc_start(bl,SC_STUN,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case WZ_VERMILION: - sc_start(bl,SC_BLIND,4*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case WZ_VERMILION: + sc_start(bl,SC_BLIND,4*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - sc_start(bl,SC_FREEZE,(3*skill_lv+35),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + sc_start(bl,SC_FREEZE,(3*skill_lv+35),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case HT_FLASHER: - sc_start(bl,SC_BLIND,(10*skill_lv+30),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case HT_FLASHER: + sc_start(bl,SC_BLIND,(10*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case HT_LANDMINE: - case MA_LANDMINE: - sc_start(bl,SC_STUN,(5*skill_lv+30),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case HT_LANDMINE: + case MA_LANDMINE: + sc_start(bl,SC_STUN,(5*skill_lv+30),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case HT_SHOCKWAVE: - status_percent_damage(src, bl, 0, 15*skill_lv+5, false); - break; + case HT_SHOCKWAVE: + status_percent_damage(src, bl, 0, 15*skill_lv+5, false); + break; - case HT_SANDMAN: - case MA_SANDMAN: - sc_start(bl,SC_SLEEP,(10*skill_lv+40),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case HT_SANDMAN: + case MA_SANDMAN: + sc_start(bl,SC_SLEEP,(10*skill_lv+40),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case TF_SPRINKLESAND: - sc_start(bl,SC_BLIND,20,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case TF_SPRINKLESAND: + sc_start(bl,SC_BLIND,20,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case TF_THROWSTONE: - sc_start(bl,SC_STUN,3,skill_lv,skill_get_time(skill_id,skill_lv)); - sc_start(bl,SC_BLIND,3,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case TF_THROWSTONE: + sc_start(bl,SC_STUN,3,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,SC_BLIND,3,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case NPC_DARKCROSS: - case CR_HOLYCROSS: - sc_start(bl,SC_BLIND,3*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case NPC_DARKCROSS: + case CR_HOLYCROSS: + sc_start(bl,SC_BLIND,3*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - //Chance to cause blind status vs demon and undead element, but not against players - if(!dstsd && (battle_check_undead(tstatus->race,tstatus->def_ele) || tstatus->race == RC_DEMON)) - sc_start(bl,SC_BLIND,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - attack_type |= BF_WEAPON; - break; + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + //Chance to cause blind status vs demon and undead element, but not against players + if(!dstsd && (battle->check_undead(tstatus->race,tstatus->def_ele) || tstatus->race == RC_DEMON)) + sc_start(bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + attack_type |= BF_WEAPON; + break; - case AM_ACIDTERROR: - sc_start2(bl,SC_BLEEDING,(skill_lv*3),skill_lv,src->id,skill_get_time2(skill_id,skill_lv)); - if (skill_break_equip(bl, EQP_ARMOR, 100*skill_get_time(skill_id,skill_lv), BCT_ENEMY)) - clif_emotion(bl,E_OMG); - break; + case AM_ACIDTERROR: + sc_start2(bl,SC_BLEEDING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + if (skill->break_equip(bl, EQP_ARMOR, 100*skill->get_time(skill_id,skill_lv), BCT_ENEMY)) + clif->emotion(bl,E_OMG); + break; - case AM_DEMONSTRATION: - skill_break_equip(bl, EQP_WEAPON, 100*skill_lv, BCT_ENEMY); - break; + case AM_DEMONSTRATION: + skill->break_equip(bl, EQP_WEAPON, 100*skill_lv, BCT_ENEMY); + break; - case CR_SHIELDCHARGE: - sc_start(bl,SC_STUN,(15+skill_lv*5),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case CR_SHIELDCHARGE: + sc_start(bl,SC_STUN,(15+skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case PA_PRESSURE: - status_percent_damage(src, bl, 0, 15+5*skill_lv, false); - break; + case PA_PRESSURE: + status_percent_damage(src, bl, 0, 15+5*skill_lv, false); + break; - case RG_RAID: - sc_start(bl,SC_STUN,(10+3*skill_lv),skill_lv,skill_get_time(skill_id,skill_lv)); - sc_start(bl,SC_BLIND,(10+3*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv)); + case RG_RAID: + sc_start(bl,SC_STUN,(10+3*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,SC_BLIND,(10+3*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); -#ifdef RENEWAL - sc_start(bl,SC_RAID,100,7,5000); - break; + #ifdef RENEWAL + sc_start(bl,SC_RAID,100,7,5000); + break; - case RG_BACKSTAP: - sc_start(bl,SC_STUN,(5+2*skill_lv),skill_lv,skill_get_time(skill_id,skill_lv)); -#endif - break; + case RG_BACKSTAP: + sc_start(bl,SC_STUN,(5+2*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); + #endif + break; - case BA_FROSTJOKER: - sc_start(bl,SC_FREEZE,(15+5*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case BA_FROSTJOKER: + sc_start(bl,SC_FREEZE,(15+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case DC_SCREAM: - sc_start(bl,SC_STUN,(25+5*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case DC_SCREAM: + sc_start(bl,SC_STUN,(25+5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case BD_LULLABY: - sc_start(bl,SC_SLEEP,15,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case BD_LULLABY: + sc_start(bl,SC_SLEEP,15,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case DC_UGLYDANCE: - rate = 5+5*skill_lv; - if(sd && (skill=pc_checkskill(sd,DC_DANCINGLESSON))) - rate += 5+skill; - status_zap(bl, 0, rate); - break; - case SL_STUN: - if (tstatus->size==SZ_MEDIUM) //Only stuns mid-sized mobs. - sc_start(bl,SC_STUN,(30+10*skill_lv),skill_lv,skill_get_time(skill_id,skill_lv)); - break; + case DC_UGLYDANCE: + rate = 5+5*skill_lv; + if(sd && (temp=pc_checkskill(sd,DC_DANCINGLESSON))) + rate += 5+temp; + status_zap(bl, 0, rate); + break; + case SL_STUN: + if (tstatus->size==SZ_MEDIUM) //Only stuns mid-sized mobs. + sc_start(bl,SC_STUN,(30+10*skill_lv),skill_lv,skill->get_time(skill_id,skill_lv)); + break; - case NPC_PETRIFYATTACK: - sc_start4(bl,status_skill2sc(skill_id),50+10*skill_lv, - skill_lv,0,0,skill_get_time(skill_id,skill_lv), - skill_get_time2(skill_id,skill_lv)); - break; - case NPC_CURSEATTACK: - case NPC_SLEEPATTACK: - case NPC_BLINDATTACK: - case NPC_POISON: - case NPC_SILENCEATTACK: - case NPC_STUNATTACK: - case NPC_HELLPOWER: - sc_start(bl,status_skill2sc(skill_id),50+10*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case NPC_ACIDBREATH: - case NPC_ICEBREATH: - sc_start(bl,status_skill2sc(skill_id),70,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case NPC_BLEEDING: - sc_start2(bl,SC_BLEEDING,(20*skill_lv),skill_lv,src->id,skill_get_time2(skill_id,skill_lv)); - break; - case NPC_MENTALBREAKER: - { //Based on observations by Tharis, Mental Breaker should do SP damage - //equal to Matk*skLevel. - rate = sstatus->matk_min; - if (rate < sstatus->matk_max) - rate += rnd()%(sstatus->matk_max - sstatus->matk_min); - rate*=skill_lv; - status_zap(bl, 0, rate); - break; - } - // Equipment breaking monster skills [Celest] - case NPC_WEAPONBRAKER: - skill_break_equip(bl, EQP_WEAPON, 150*skill_lv, BCT_ENEMY); - break; - case NPC_ARMORBRAKE: - skill_break_equip(bl, EQP_ARMOR, 150*skill_lv, BCT_ENEMY); - break; - case NPC_HELMBRAKE: - skill_break_equip(bl, EQP_HELM, 150*skill_lv, BCT_ENEMY); - break; - case NPC_SHIELDBRAKE: - skill_break_equip(bl, EQP_SHIELD, 150*skill_lv, BCT_ENEMY); - break; + case NPC_PETRIFYATTACK: + sc_start4(bl,status_skill2sc(skill_id),50+10*skill_lv, + skill_lv,0,0,skill->get_time(skill_id,skill_lv), + skill->get_time2(skill_id,skill_lv)); + break; + case NPC_CURSEATTACK: + case NPC_SLEEPATTACK: + case NPC_BLINDATTACK: + case NPC_POISON: + case NPC_SILENCEATTACK: + case NPC_STUNATTACK: + case NPC_HELLPOWER: + sc_start(bl,status_skill2sc(skill_id),50+10*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case NPC_ACIDBREATH: + case NPC_ICEBREATH: + sc_start(bl,status_skill2sc(skill_id),70,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case NPC_BLEEDING: + sc_start2(bl,SC_BLEEDING,(20*skill_lv),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + break; + case NPC_MENTALBREAKER: + { //Based on observations by Tharis, Mental Breaker should do SP damage + //equal to Matk*skLevel. + rate = sstatus->matk_min; + if (rate < sstatus->matk_max) + rate += rnd()%(sstatus->matk_max - sstatus->matk_min); + rate*=skill_lv; + status_zap(bl, 0, rate); + break; + } + // Equipment breaking monster skills [Celest] + case NPC_WEAPONBRAKER: + skill->break_equip(bl, EQP_WEAPON, 150*skill_lv, BCT_ENEMY); + break; + case NPC_ARMORBRAKE: + skill->break_equip(bl, EQP_ARMOR, 150*skill_lv, BCT_ENEMY); + break; + case NPC_HELMBRAKE: + skill->break_equip(bl, EQP_HELM, 150*skill_lv, BCT_ENEMY); + break; + case NPC_SHIELDBRAKE: + skill->break_equip(bl, EQP_SHIELD, 150*skill_lv, BCT_ENEMY); + break; - case CH_TIGERFIST: - sc_start(bl,SC_STOP,(10+skill_lv*10),0,skill_get_time2(skill_id,skill_lv)); - break; + case CH_TIGERFIST: + sc_start(bl,SC_STOP,(10+skill_lv*10),0,skill->get_time2(skill_id,skill_lv)); + break; - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - sc_start(bl,SC_STOP,(15+skill_lv*5),0,skill_get_time2(skill_id,skill_lv)); - break; + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + sc_start(bl,SC_STOP,(15+skill_lv*5),0,skill->get_time2(skill_id,skill_lv)); + break; - case ST_REJECTSWORD: - sc_start(bl,SC_AUTOCOUNTER,(skill_lv*15),skill_lv,skill_get_time(skill_id,skill_lv)); - break; + case ST_REJECTSWORD: + sc_start(bl,SC_AUTOCOUNTER,(skill_lv*15),skill_lv,skill->get_time(skill_id,skill_lv)); + break; - case PF_FOGWALL: - if (src != bl && !tsc->data[SC_DELUGE]) - sc_start(bl,SC_BLIND,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case PF_FOGWALL: + if (src != bl && !tsc->data[SC_DELUGE]) + sc_start(bl,SC_BLIND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element - if (!(battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) - sc_start2(bl, SC_BLEEDING,50, skill_lv, src->id, skill_get_time2(skill_id,skill_lv)); - break; + case LK_HEADCRUSH: //Headcrush has chance of causing Bleeding status, except on demon and undead element + if (!(battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) + sc_start2(bl, SC_BLEEDING,50, skill_lv, src->id, skill->get_time2(skill_id,skill_lv)); + break; - case LK_JOINTBEAT: - status = status_skill2sc(skill_id); - if (tsc->jb_flag) { - sc_start4(bl,status,(5*skill_lv+5),skill_lv,tsc->jb_flag&BREAK_FLAGS,src->id,0,skill_get_time2(skill_id,skill_lv)); - tsc->jb_flag = 0; - } - break; - case ASC_METEORASSAULT: - //Any enemies hit by this skill will receive Stun, Darkness, or external bleeding status ailment with a 5%+5*skill_lv% chance. - switch(rnd()%3) { - case 0: - sc_start(bl,SC_BLIND,(5+skill_lv*5),skill_lv,skill_get_time2(skill_id,1)); - break; - case 1: - sc_start(bl,SC_STUN,(5+skill_lv*5),skill_lv,skill_get_time2(skill_id,2)); - break; - default: - sc_start2(bl,SC_BLEEDING,(5+skill_lv*5),skill_lv,src->id,skill_get_time2(skill_id,3)); - } - break; + case LK_JOINTBEAT: + status = status_skill2sc(skill_id); + if (tsc->jb_flag) { + sc_start4(bl,status,(5*skill_lv+5),skill_lv,tsc->jb_flag&BREAK_FLAGS,src->id,0,skill->get_time2(skill_id,skill_lv)); + tsc->jb_flag = 0; + } + break; + case ASC_METEORASSAULT: + //Any enemies hit by this skill will receive Stun, Darkness, or external bleeding status ailment with a 5%+5*skill_lv% chance. + switch(rnd()%3) { + case 0: + sc_start(bl,SC_BLIND,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,1)); + break; + case 1: + sc_start(bl,SC_STUN,(5+skill_lv*5),skill_lv,skill->get_time2(skill_id,2)); + break; + default: + sc_start2(bl,SC_BLEEDING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3)); + } + break; - case HW_NAPALMVULCAN: - sc_start(bl,SC_CURSE,5*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case HW_NAPALMVULCAN: + sc_start(bl,SC_CURSE,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case WS_CARTTERMINATION: // Cart termination - sc_start(bl,SC_STUN,5*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case WS_CARTTERMINATION: // Cart termination + sc_start(bl,SC_STUN,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case CR_ACIDDEMONSTRATION: - skill_break_equip(bl, EQP_WEAPON|EQP_ARMOR, 100*skill_lv, BCT_ENEMY); - break; + case CR_ACIDDEMONSTRATION: + skill->break_equip(bl, EQP_WEAPON|EQP_ARMOR, 100*skill_lv, BCT_ENEMY); + break; - case TK_DOWNKICK: - sc_start(bl,SC_STUN,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case TK_DOWNKICK: + sc_start(bl,SC_STUN,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case TK_JUMPKICK: - if( dstsd && dstsd->class_ != MAPID_SOUL_LINKER && !tsc->data[SC_PRESERVE] ) - {// debuff the following statuses - status_change_end(bl, SC_SPIRIT, INVALID_TIMER); - status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); - status_change_end(bl, SC_KAITE, INVALID_TIMER); - status_change_end(bl, SC_KAAHI, INVALID_TIMER); - status_change_end(bl, SC_ONEHAND, INVALID_TIMER); - status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); - } - break; - case TK_TURNKICK: - case MO_BALKYOUNG: //Note: attack_type is passed as BF_WEAPON for the actual target, BF_MISC for the splash-affected mobs. - if(attack_type&BF_MISC) //70% base stun chance... - sc_start(bl,SC_STUN,70,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case GS_BULLSEYE: //0.1% coma rate. - if(tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) - status_change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); - break; - case GS_PIERCINGSHOT: - sc_start2(bl,SC_BLEEDING,(skill_lv*3),skill_lv,src->id,skill_get_time2(skill_id,skill_lv)); - break; - case NJ_HYOUSYOURAKU: - sc_start(bl,SC_FREEZE,(10+10*skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case GS_FLING: - sc_start(bl,SC_FLING,100, sd?sd->spiritball_old:5,skill_get_time(skill_id,skill_lv)); - break; - case GS_DISARM: - rate = 3*skill_lv; - if (sstatus->dex > tstatus->dex) - rate += (sstatus->dex - tstatus->dex)/5; //TODO: Made up formula - skill_strip_equip(bl, EQP_WEAPON, rate, skill_lv, skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case NPC_EVILLAND: - sc_start(bl,SC_BLIND,5*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case NPC_HELLJUDGEMENT: - sc_start(bl,SC_CURSE,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case NPC_CRITICALWOUND: - sc_start(bl,SC_CRITICALWOUND,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case RK_HUNDREDSPEAR: - if( !sd || pc_checkskill(sd,KN_SPEARBOOMERANG) == 0 ) - break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang. - rate = 10 + 3 * skill_lv; - if( rnd()%100 < rate ) - skill_castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0); - break; - case RK_WINDCUTTER: - sc_start(bl,SC_FEAR,3+2*skill_lv,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case RK_DRAGONBREATH: - sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,1000,src->id,0,skill_get_time(skill_id,skill_lv)); - break; - case AB_ADORAMUS: - if( tsc && !tsc->data[SC_DECREASEAGI] ) //Prevent duplicate agi-down effect. - sc_start(bl, SC_ADORAMUS, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case WL_CRIMSONROCK: - sc_start(bl, SC_STUN, 40, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case WL_COMET: - sc_start4(bl,SC_BURNING,100,skill_lv,1000,src->id,0,skill_get_time(skill_id,skill_lv)); - break; - case WL_EARTHSTRAIN: - { - int rate = 0, i; - const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC }; - rate = 6 * skill_lv + sstatus->dex / 10 + (sd? sd->status.job_level / 4 : 0) - tstatus->dex /5;// The tstatus->dex / 5 part is unofficial, but players gotta have some kind of way to have resistance. [Rytech] - //rate -= rate * tstatus->dex / 200; // Disabled until official resistance is found. + case TK_JUMPKICK: + if( dstsd && dstsd->class_ != MAPID_SOUL_LINKER && !tsc->data[SC_PRESERVE] ) + {// debuff the following statuses + status_change_end(bl, SC_SPIRIT, INVALID_TIMER); + status_change_end(bl, SC_ADRENALINE2, INVALID_TIMER); + status_change_end(bl, SC_KAITE, INVALID_TIMER); + status_change_end(bl, SC_KAAHI, INVALID_TIMER); + status_change_end(bl, SC_ONEHAND, INVALID_TIMER); + status_change_end(bl, SC_ASPDPOTION2, INVALID_TIMER); + } + break; + case TK_TURNKICK: + case MO_BALKYOUNG: //Note: attack_type is passed as BF_WEAPON for the actual target, BF_MISC for the splash-affected mobs. + if(attack_type&BF_MISC) //70% base stun chance... + sc_start(bl,SC_STUN,70,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case GS_BULLSEYE: //0.1% coma rate. + if(tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN) + status_change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); + break; + case GS_PIERCINGSHOT: + sc_start2(bl,SC_BLEEDING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + break; + case NJ_HYOUSYOURAKU: + sc_start(bl,SC_FREEZE,(10+10*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case GS_FLING: + sc_start(bl,SC_FLING,100, sd?sd->spiritball_old:5,skill->get_time(skill_id,skill_lv)); + break; + case GS_DISARM: + rate = 3*skill_lv; + if (sstatus->dex > tstatus->dex) + rate += (sstatus->dex - tstatus->dex)/5; //TODO: Made up formula + skill->strip_equip(bl, EQP_WEAPON, rate, skill_lv, skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case NPC_EVILLAND: + sc_start(bl,SC_BLIND,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case NPC_HELLJUDGEMENT: + sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case NPC_CRITICALWOUND: + sc_start(bl,SC_CRITICALWOUND,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case RK_HUNDREDSPEAR: + if( !sd || pc_checkskill(sd,KN_SPEARBOOMERANG) == 0 ) + break; // Spear Boomerang auto cast chance only works if you have mastered Spear Boomerang. + rate = 10 + 3 * skill_lv; + if( rnd()%100 < rate ) + skill->castend_damage_id(src,bl,KN_SPEARBOOMERANG,1,tick,0); + break; + case RK_WINDCUTTER: + sc_start(bl,SC_FEAR,3+2*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case RK_DRAGONBREATH: + sc_start4(bl,SC_BURNING,5+5*skill_lv,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv)); + break; + case AB_ADORAMUS: + if( tsc && !tsc->data[SC_DECREASEAGI] ) //Prevent duplicate agi-down effect. + sc_start(bl, SC_ADORAMUS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case WL_CRIMSONROCK: + sc_start(bl, SC_STUN, 40, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case WL_COMET: + sc_start4(bl,SC_BURNING,100,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv)); + break; + case WL_EARTHSTRAIN: + { + int rate = 0, i; + const int pos[5] = { EQP_WEAPON, EQP_HELM, EQP_SHIELD, EQP_ARMOR, EQP_ACC }; + rate = 6 * skill_lv + sstatus->dex / 10 + (sd? sd->status.job_level / 4 : 0) - tstatus->dex /5;// The tstatus->dex / 5 part is unofficial, but players gotta have some kind of way to have resistance. [Rytech] + //rate -= rate * tstatus->dex / 200; // Disabled until official resistance is found. - for( i = 0; i < skill_lv; i++ ) - skill_strip_equip(bl,pos[i],rate,skill_lv,skill_get_time2(skill_id,skill_lv)); - } - break; - case WL_JACKFROST: - sc_start(bl,SC_FREEZE,100,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case RA_WUGBITE: - sc_start(bl, SC_BITE, (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skill_lv, (skill_get_time(skill_id,skill_lv) + (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) ); - break; - case RA_SENSITIVEKEEN: - if( rnd()%100 < 8 * skill_lv ) - skill_castend_damage_id(src, bl, RA_WUGBITE, sd ? pc_checkskill(sd, RA_WUGBITE):skill_lv, tick, SD_ANIMATION); - break; - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - sc_start(bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FREEZING, 40 + 10 * skill_lv, skill_lv, skill_get_time2(skill_id, skill_lv)); - break; - case NC_PILEBUNKER: - if( rnd()%100 < 5 + 15*skill_lv ) - { //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield - status_change_end(bl, SC_KYRIE, INVALID_TIMER); - status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); - status_change_end(bl, SC_STEELBODY, INVALID_TIMER); - status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); - status_change_end(bl, SC_MILLENNIUMSHIELD, INVALID_TIMER); - } - break; - case NC_FLAMELAUNCHER: - sc_start4(bl, SC_BURNING, 50 + 10 * skill_lv, skill_lv, 1000, src->id, 0, skill_get_time2(skill_id, skill_lv)); - break; - case NC_COLDSLOWER: - sc_start(bl, SC_FREEZE, 10 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv)); - sc_start(bl, SC_FREEZING, 20 + 10 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case NC_POWERSWING: - sc_start(bl, SC_STUN, 5*skill_lv, skill_lv, skill_get_time(skill_id, skill_lv)); - if( rnd()%100 < 5*skill_lv ) - skill_castend_damage_id(src, bl, NC_AXEBOOMERANG, pc_checkskill(sd, NC_AXEBOOMERANG), tick, 1); - break; - case GC_WEAPONCRUSH: - skill_castend_nodamage_id(src,bl,skill_id,skill_lv,tick,BCT_ENEMY); - break; - case LG_SHIELDPRESS: - sc_start(bl, SC_STUN, 30 + 8 * skill_lv, skill_lv, skill_get_time(skill_id,skill_lv)); - break; - case LG_PINPOINTATTACK: - rate = 30 + (((5 * (sd?pc_checkskill(sd,LG_PINPOINTATTACK):skill_lv)) + (sstatus->agi + status_get_lv(src))) / 10); - switch( skill_lv ) { - case 1: - sc_start2(bl,SC_BLEEDING,rate,skill_lv,src->id,skill_get_time(skill_id,skill_lv)); - break; - case 2: - if( dstsd && dstsd->spiritball && rnd()%100 < rate ) - pc_delspiritball(dstsd, dstsd->spiritball, 0); - break; - default: - skill_break_equip(bl,(skill_lv == 3) ? EQP_SHIELD : (skill_lv == 4) ? EQP_ARMOR : EQP_WEAPON,rate * 100,BCT_ENEMY); - break; - } - break; - case LG_MOONSLASHER: - rate = 32 + 8 * skill_lv; - if( rnd()%100 < rate && dstsd ) // Uses skill_addtimerskill to avoid damage and setsit packet overlaping. Officially clif_setsit is received about 500 ms after damage packet. - skill_addtimerskill(src,tick+500,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0); - else if( dstmd && !is_boss(bl) ) - sc_start(bl,SC_STOP,100,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters. - if ( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON ) - sc_start(bl, SC_BLIND,50, skill_lv, skill_get_time(skill_id,skill_lv)); - break; - case LG_EARTHDRIVE: - skill_break_equip(src, EQP_SHIELD, 500, BCT_SELF); - sc_start(bl, SC_EARTHDRIVE, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case SR_DRAGONCOMBO: - sc_start(bl, SC_STUN, 1 + skill_lv, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case SR_FALLENEMPIRE: - sc_start(bl, SC_STOP, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case SR_WINDMILL: - if( dstsd ) - skill_addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0); - else if( dstmd && !is_boss(bl) ) - sc_start(bl, SC_STUN, 100, skill_lv, 1000 + 1000 * (rnd() %3)); - break; - case SR_GENTLETOUCH_QUIET: // [(Skill Level x 5) + (Caster?s DEX + Caster?s Base Level) / 10] - sc_start(bl, SC_SILENCE, 5 * skill_lv + (sstatus->dex + status_get_lv(src)) / 10, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case SR_EARTHSHAKER: - sc_start(bl,SC_STUN, 25 + 5 * skill_lv,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case SR_HOWLINGOFLION: - sc_start(bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case WM_SOUND_OF_DESTRUCTION: - if( rnd()%100 < 5 + 5 * skill_lv ) { // Temporarly Check Until We Get the Official Formula - status_change_end(bl, SC_DANCING, INVALID_TIMER); - status_change_end(bl, SC_RICHMANKIM, INVALID_TIMER); - status_change_end(bl, SC_ETERNALCHAOS, INVALID_TIMER); - status_change_end(bl, SC_DRUMBATTLE, INVALID_TIMER); - status_change_end(bl, SC_NIBELUNGEN, INVALID_TIMER); - status_change_end(bl, SC_INTOABYSS, INVALID_TIMER); - status_change_end(bl, SC_SIEGFRIED, INVALID_TIMER); - status_change_end(bl, SC_WHISTLE, INVALID_TIMER); - status_change_end(bl, SC_ASSNCROS, INVALID_TIMER); - status_change_end(bl, SC_POEMBRAGI, INVALID_TIMER); - status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER); - status_change_end(bl, SC_HUMMING, INVALID_TIMER); - status_change_end(bl, SC_FORTUNE, INVALID_TIMER); - status_change_end(bl, SC_SERVICE4U, INVALID_TIMER); - status_change_end(bl, SC_LONGING, INVALID_TIMER); - status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); - status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); - status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); - status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); - status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); - status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - status_change_end(bl, SC_WINKCHARM, INVALID_TIMER); - status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); - status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); - status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); - status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); - status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); - } - break; - case SO_EARTHGRAVE: - sc_start2(bl, SC_BLEEDING, 5 * skill_lv, skill_lv, src->id, skill_get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine] - break; - case SO_DIAMONDDUST: - rate = 5 + 5 * skill_lv; - if( sc && sc->data[SC_COOLER_OPTION] ) - rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100; - sc_start(bl, SC_CRYSTALIZE, rate, skill_lv, skill_get_time2(skill_id, skill_lv)); - break; - case SO_VARETYR_SPEAR: - sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill_get_time2(skill_id, skill_lv)); - break; - case GN_SLINGITEM_RANGEMELEEATK: - if( sd ) { - switch( sd->itemid ) { // Starting SCs here instead of do it in skill_additional_effect to simplify the code. - case 13261: - sc_start(bl, SC_STUN, 100, skill_lv, skill_get_time2(GN_SLINGITEM, skill_lv)); - sc_start2(bl, SC_BLEEDING, 100, skill_lv, src->id, skill_get_time2(GN_SLINGITEM, skill_lv)); + for( i = 0; i < skill_lv; i++ ) + skill->strip_equip(bl,pos[i],rate,skill_lv,skill->get_time2(skill_id,skill_lv)); + } + break; + case WL_JACKFROST: + sc_start(bl,SC_FREEZE,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case RA_WUGBITE: + sc_start(bl, SC_BITE, (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*2 : 0), skill_lv, (skill->get_time(skill_id,skill_lv) + (sd ? pc_checkskill(sd,RA_TOOTHOFWUG)*500 : 0)) ); + break; + case RA_SENSITIVEKEEN: + if( rnd()%100 < 8 * skill_lv ) + skill->castend_damage_id(src, bl, RA_WUGBITE, sd ? pc_checkskill(sd, RA_WUGBITE):skill_lv, tick, SD_ANIMATION); + break; + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + sc_start(bl, (skill_id == RA_FIRINGTRAP) ? SC_BURNING:SC_FREEZING, 40 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv)); + break; + case NC_PILEBUNKER: + if( rnd()%100 < 5 + 15*skill_lv ) + { //Deactivatable Statuses: Kyrie Eleison, Auto Guard, Steel Body, Assumptio, and Millennium Shield + status_change_end(bl, SC_KYRIE, INVALID_TIMER); + status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); + status_change_end(bl, SC_STEELBODY, INVALID_TIMER); + status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER); + status_change_end(bl, SC_MILLENNIUMSHIELD, INVALID_TIMER); + } + break; + case NC_FLAMELAUNCHER: + sc_start4(bl, SC_BURNING, 50 + 10 * skill_lv, skill_lv, 1000, src->id, 0, skill->get_time2(skill_id, skill_lv)); + break; + case NC_COLDSLOWER: + sc_start(bl, SC_FREEZE, 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(bl, SC_FREEZING, 20 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case NC_POWERSWING: + sc_start(bl, SC_STUN, 5*skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + if( rnd()%100 < 5*skill_lv ) + skill->castend_damage_id(src, bl, NC_AXEBOOMERANG, pc_checkskill(sd, NC_AXEBOOMERANG), tick, 1); + break; + case GC_WEAPONCRUSH: + skill->castend_nodamage_id(src,bl,skill_id,skill_lv,tick,BCT_ENEMY); + break; + case LG_SHIELDPRESS: + sc_start(bl, SC_STUN, 30 + 8 * skill_lv, skill_lv, skill->get_time(skill_id,skill_lv)); + break; + case LG_PINPOINTATTACK: + rate = 30 + (((5 * (sd?pc_checkskill(sd,LG_PINPOINTATTACK):skill_lv)) + (sstatus->agi + status_get_lv(src))) / 10); + switch( skill_lv ) { + case 1: + sc_start2(bl,SC_BLEEDING,rate,skill_lv,src->id,skill->get_time(skill_id,skill_lv)); break; - case 13262: - sc_start(bl, SC_MELON_BOMB, 100, skill_lv, skill_get_time(GN_SLINGITEM, skill_lv)); // Reduces ASPD and moviment speed + case 2: + if( dstsd && dstsd->spiritball && rnd()%100 < rate ) + pc_delspiritball(dstsd, dstsd->spiritball, 0); break; - case 13264: - sc_start(bl, SC_BANANA_BOMB, 100, skill_lv, skill_get_time(GN_SLINGITEM, skill_lv)); // Reduces LUK ??Needed confirm it, may be it's bugged in kRORE? - sc_start(bl, SC_BANANA_BOMB_SITDOWN, 75, skill_lv, skill_get_time(GN_SLINGITEM_RANGEMELEEATK,skill_lv)); // Sitdown for 3 seconds. + default: + skill->break_equip(bl,(skill_lv == 3) ? EQP_SHIELD : (skill_lv == 4) ? EQP_ARMOR : EQP_WEAPON,rate * 100,BCT_ENEMY); break; } - sd->itemid = -1; - } - break; - case GN_HELLS_PLANT_ATK: - sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill_get_time2(skill_id, skill_lv)); - sc_start2(bl, SC_BLEEDING, 20 + 10 * skill_lv, skill_lv, src->id,skill_get_time2(skill_id, skill_lv)); - break; - case EL_WIND_SLASH: // Non confirmed rate. - sc_start2(bl, SC_BLEEDING, 25, skill_lv, src->id, skill_get_time(skill_id,skill_lv)); - break; - case EL_STONE_HAMMER: - rate = 10 * skill_lv; - sc_start(bl, SC_STUN, rate, skill_lv, skill_get_time(skill_id,skill_lv)); - break; - case EL_ROCK_CRUSHER: - case EL_ROCK_CRUSHER_ATK: - sc_start(bl,status_skill2sc(skill_id),50,skill_lv,skill_get_time(EL_ROCK_CRUSHER,skill_lv)); - break; - case EL_TYPOON_MIS: - sc_start(bl,SC_SILENCE,10*skill_lv,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case KO_JYUMONJIKIRI: // needs more info - sc_start(bl,SC_JYUMONJIKIRI,25,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case KO_MAKIBISHI: - sc_start(bl, SC_STUN, 100, skill_lv, skill_get_time2(skill_id,skill_lv)); - break; - case MH_LAVA_SLIDE: - if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 1000, src->id, 0, skill_get_time(skill_id, skill_lv)); - break; - case MH_STAHL_HORN: - sc_start(bl, SC_STUN, (20 + 4 * (skill_lv-1)), skill_lv, skill_get_time(skill_id, skill_lv)); - break; - case MH_NEEDLE_OF_PARALYZE: - sc_start(bl, SC_PARALYSIS, 40 + (5*skill_lv), skill_lv, skill_get_time(skill_id, skill_lv)); - break; + break; + case LG_MOONSLASHER: + rate = 32 + 8 * skill_lv; + if( rnd()%100 < rate && dstsd ) // Uses skill->addtimerskill to avoid damage and setsit packet overlaping. Officially clif->setsit is received about 500 ms after damage packet. + skill->addtimerskill(src,tick+500,bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0); + else if( dstmd && !is_boss(bl) ) + sc_start(bl,SC_STOP,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters. + if ( battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON ) + sc_start(bl, SC_BLIND,50, skill_lv, skill->get_time(skill_id,skill_lv)); + break; + case LG_EARTHDRIVE: + skill->break_equip(src, EQP_SHIELD, 500, BCT_SELF); + sc_start(bl, SC_EARTHDRIVE, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case SR_DRAGONCOMBO: + sc_start(bl, SC_STUN, 1 + skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case SR_FALLENEMPIRE: + sc_start(bl, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case SR_WINDMILL: + if( dstsd ) + skill->addtimerskill(src,tick+status_get_amotion(src),bl->id,0,0,skill_id,skill_lv,BF_WEAPON,0); + else if( dstmd && !is_boss(bl) ) + sc_start(bl, SC_STUN, 100, skill_lv, 1000 + 1000 * (rnd() %3)); + break; + case SR_GENTLETOUCH_QUIET: // [(Skill Level x 5) + (Caster?s DEX + Caster?s Base Level) / 10] + sc_start(bl, SC_SILENCE, 5 * skill_lv + (sstatus->dex + status_get_lv(src)) / 10, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case SR_EARTHSHAKER: + sc_start(bl,SC_STUN, 25 + 5 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case SR_HOWLINGOFLION: + sc_start(bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case WM_SOUND_OF_DESTRUCTION: + if( rnd()%100 < 5 + 5 * skill_lv ) { // Temporarly Check Until We Get the Official Formula + status_change_end(bl, SC_DANCING, INVALID_TIMER); + status_change_end(bl, SC_RICHMANKIM, INVALID_TIMER); + status_change_end(bl, SC_ETERNALCHAOS, INVALID_TIMER); + status_change_end(bl, SC_DRUMBATTLE, INVALID_TIMER); + status_change_end(bl, SC_NIBELUNGEN, INVALID_TIMER); + status_change_end(bl, SC_INTOABYSS, INVALID_TIMER); + status_change_end(bl, SC_SIEGFRIED, INVALID_TIMER); + status_change_end(bl, SC_WHISTLE, INVALID_TIMER); + status_change_end(bl, SC_ASSNCROS, INVALID_TIMER); + status_change_end(bl, SC_POEMBRAGI, INVALID_TIMER); + status_change_end(bl, SC_APPLEIDUN, INVALID_TIMER); + status_change_end(bl, SC_HUMMING, INVALID_TIMER); + status_change_end(bl, SC_FORTUNE, INVALID_TIMER); + status_change_end(bl, SC_SERVICE4U, INVALID_TIMER); + status_change_end(bl, SC_LONGING, INVALID_TIMER); + status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); + status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + status_change_end(bl, SC_WINKCHARM, INVALID_TIMER); + status_change_end(bl, SC_SONGOFMANA, INVALID_TIMER); + status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); + status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + } + break; + case SO_EARTHGRAVE: + sc_start2(bl, SC_BLEEDING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine] + break; + case SO_DIAMONDDUST: + rate = 5 + 5 * skill_lv; + if( sc && sc->data[SC_COOLER_OPTION] ) + rate += rate * sc->data[SC_COOLER_OPTION]->val2 / 100; + sc_start(bl, SC_CRYSTALIZE, rate, skill_lv, skill->get_time2(skill_id, skill_lv)); + break; + case SO_VARETYR_SPEAR: + sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv)); + break; + case GN_SLINGITEM_RANGEMELEEATK: + if( sd ) { + switch( sd->itemid ) { // Starting SCs here instead of do it in skill->additional_effect to simplify the code. + case 13261: + sc_start(bl, SC_STUN, 100, skill_lv, skill->get_time2(GN_SLINGITEM, skill_lv)); + sc_start2(bl, SC_BLEEDING, 100, skill_lv, src->id, skill->get_time2(GN_SLINGITEM, skill_lv)); + break; + case 13262: + sc_start(bl, SC_MELON_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces ASPD and moviment speed + break; + case 13264: + sc_start(bl, SC_BANANA_BOMB, 100, skill_lv, skill->get_time(GN_SLINGITEM, skill_lv)); // Reduces LUK ??Needed confirm it, may be it's bugged in kRORE? + sc_start(bl, SC_BANANA_BOMB_SITDOWN, 75, skill_lv, skill->get_time(GN_SLINGITEM_RANGEMELEEATK,skill_lv)); // Sitdown for 3 seconds. + break; + } + sd->itemid = -1; + } + break; + case GN_HELLS_PLANT_ATK: + sc_start(bl, SC_STUN, 5 + 5 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv)); + sc_start2(bl, SC_BLEEDING, 20 + 10 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv)); + break; + case EL_WIND_SLASH: // Non confirmed rate. + sc_start2(bl, SC_BLEEDING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); + break; + case EL_STONE_HAMMER: + rate = 10 * skill_lv; + sc_start(bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv)); + break; + case EL_ROCK_CRUSHER: + case EL_ROCK_CRUSHER_ATK: + sc_start(bl,status_skill2sc(skill_id),50,skill_lv,skill->get_time(EL_ROCK_CRUSHER,skill_lv)); + break; + case EL_TYPOON_MIS: + sc_start(bl,SC_SILENCE,10*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case KO_JYUMONJIKIRI: // needs more info + sc_start(bl,SC_JYUMONJIKIRI,25,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case KO_MAKIBISHI: + sc_start(bl, SC_STUN, 100, skill_lv, skill->get_time2(skill_id,skill_lv)); + break; + case MH_LAVA_SLIDE: + if (tsc && !tsc->data[SC_BURNING]) sc_start4(bl, SC_BURNING, 10 * skill_lv, skill_lv, 1000, src->id, 0, skill->get_time(skill_id, skill_lv)); + break; + case MH_STAHL_HORN: + sc_start(bl, SC_STUN, (20 + 4 * (skill_lv-1)), skill_lv, skill->get_time(skill_id, skill_lv)); + break; + case MH_NEEDLE_OF_PARALYZE: + sc_start(bl, SC_PARALYSIS, 40 + (5*skill_lv), skill_lv, skill->get_time(skill_id, skill_lv)); + break; } if (md && battle_config.summons_trigger_autospells && md->master_id && md->special_state.ai) @@ -1436,13 +1429,15 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint rate = battle_config.equip_natural_break_rate; if( sc ) { + if(sc->data[SC_GIANTGROWTH]) + rate += 10; if(sc->data[SC_OVERTHRUST]) rate += 10; if(sc->data[SC_MAXOVERTHRUST]) rate += 10; } if( rate ) - skill_break_equip(src, EQP_WEAPON, rate, BCT_SELF); + skill->break_equip(src, EQP_WEAPON, rate, BCT_SELF); } if( battle_config.equip_skill_break_rate && skill_id != WS_CARTTERMINATION && skill_id != ITM_TOMAHAWK ) { // Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity. @@ -1453,7 +1448,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if( sc && sc->data[SC_MELTDOWN] ) rate += sc->data[SC_MELTDOWN]->val2; if( rate ) - skill_break_equip(bl, EQP_WEAPON, rate, BCT_ENEMY); + skill->break_equip(bl, EQP_WEAPON, rate, BCT_ENEMY); // Target armor breaking rate = 0; @@ -1462,7 +1457,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint if( sc && sc->data[SC_MELTDOWN] ) rate += sc->data[SC_MELTDOWN]->val3; if( rate ) - skill_break_equip(bl, EQP_ARMOR, rate, BCT_ENEMY); + skill->break_equip(bl, EQP_ARMOR, rate, BCT_ENEMY); } } @@ -1470,25 +1465,25 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint struct unit_data *ud = unit_bl2ud(src); if( sc->data[SC_WILD_STORM_OPTION] ) - skill = sc->data[SC_WILD_STORM_OPTION]->val2; + temp = sc->data[SC_WILD_STORM_OPTION]->val2; else if( sc->data[SC_UPHEAVAL_OPTION] ) - skill = sc->data[SC_UPHEAVAL_OPTION]->val2; + temp = sc->data[SC_UPHEAVAL_OPTION]->val2; else if( sc->data[SC_TROPIC_OPTION] ) - skill = sc->data[SC_TROPIC_OPTION]->val3; + temp = sc->data[SC_TROPIC_OPTION]->val3; else if( sc->data[SC_CHILLY_AIR_OPTION] ) - skill = sc->data[SC_CHILLY_AIR_OPTION]->val3; + temp = sc->data[SC_CHILLY_AIR_OPTION]->val3; else - skill = 0; + temp = 0; - if ( rnd()%100 < 25 && skill ){ - skill_castend_damage_id(src, bl, skill, 5, tick, 0); + if ( rnd()%100 < 25 && temp ){ + skill->castend_damage_id(src, bl, temp, 5, tick, 0); if (ud) { - rate = skill_delayfix(src, skill, skill_lv); + rate = skill->delay_fix(src, temp, skill_lv); if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if ( battle_config.display_status_timers ) - clif_status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + clif->status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); } } } @@ -1508,10 +1503,10 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint sd->autospell[i].flag&attack_type&BF_SKILLMASK)) continue; // one or more trigger conditions were not fulfilled - skill = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id; + temp = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id; sd->state.autocast = 1; - notok = skillnotok(skill, sd); + notok = skill->not_ok(temp, sd); sd->state.autocast = 0; if ( notok ) @@ -1527,26 +1522,26 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint tbl = (sd->autospell[i].id < 0) ? src : bl; - if( (type = skill_get_casttype(skill)) == CAST_GROUND ) { + if( (type = skill->get_casttype(temp)) == CAST_GROUND ) { int maxcount = 0; if( !(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skill)&UF_NOREITERATION && - skill_check_unit_range(src,tbl->x,tbl->y,skill,skill_lv) + skill->get_unit_flag(temp)&UF_NOREITERATION && + skill->check_unit_range(src,tbl->x,tbl->y,temp,skill_lv) ) { continue; } if( BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skill)&UF_NOFOOTSET && - skill_check_unit_range2(src,tbl->x,tbl->y,skill,skill_lv) + skill->get_unit_flag(temp)&UF_NOFOOTSET && + skill->check_unit_range2(src,tbl->x,tbl->y,temp,skill_lv) ) { continue; } if( BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skill, skill_lv)) > 0 + (maxcount = skill->get_maxcount(temp, skill_lv)) > 0 ) { int v; for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) { - if(sd->ud.skillunit[v]->skill_id == skill) + if(sd->ud.skillunit[v]->skill_id == temp) maxcount--; } if( maxcount == 0 ) { @@ -1555,37 +1550,37 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint } } if( battle_config.autospell_check_range && - !battle_check_range(src, tbl, skill_get_range2(src, skill,skill_lv) + (skill == RG_CLOSECONFINE?0:1)) ) + !battle->check_range(src, tbl, skill->get_range2(src, temp,skill_lv) + (temp == RG_CLOSECONFINE?0:1)) ) continue; - if (skill == AS_SONICBLOW) + if (temp == AS_SONICBLOW) pc_stop_attack(sd); //Special case, Sonic Blow autospell should stop the player attacking. - if (skill == PF_SPIDERWEB) //Special case, due to its nature of coding. + else if (temp == PF_SPIDERWEB) //Special case, due to its nature of coding. type = CAST_GROUND; sd->state.autocast = 1; - skill_consume_requirement(sd,skill,skill_lv,1); - skill_toggle_magicpower(src, skill); + skill->consume_requirement(sd,temp,skill_lv,1); + skill->toggle_magicpower(src, temp); switch (type) { case CAST_GROUND: - skill_castend_pos2(src, tbl->x, tbl->y, skill, skill_lv, tick, 0); + skill->castend_pos2(src, tbl->x, tbl->y, temp, skill_lv, tick, 0); break; case CAST_NODAMAGE: - skill_castend_nodamage_id(src, tbl, skill, skill_lv, tick, 0); + skill->castend_nodamage_id(src, tbl, temp, skill_lv, tick, 0); break; case CAST_DAMAGE: - skill_castend_damage_id(src, tbl, skill, skill_lv, tick, 0); + skill->castend_damage_id(src, tbl, temp, skill_lv, tick, 0); break; } sd->state.autocast = 0; //Set canact delay. [Skotlex] ud = unit_bl2ud(src); if (ud) { - rate = skill_delayfix(src, skill, skill_lv); + rate = skill->delay_fix(src, temp, skill_lv); if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if ( battle_config.display_status_timers && sd ) - clif_status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + clif->status_change(src, SI_ACTIONDELAY, 1, rate, 0, 0, 0); } } } @@ -1616,7 +1611,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint { struct mob_db *mob; int class_; - skill = 0; + temp = 0; do { do { class_ = rnd() % MAX_MOB_DB; @@ -1626,8 +1621,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint mob = mob_db(class_); } while ( (mob->status.mode&(MD_BOSS|MD_PLANT) || mob->summonper[0] <= rate) && - (skill++) < 2000); - if (skill < 2000) + (temp++) < 2000); + if (temp < 2000) mob_class_change(dstmd,class_); } @@ -1635,7 +1630,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, uint } int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint16 skill_id, unsigned int tick) { - int skill, skill_lv, i, type, notok; + int temp, skill_lv, i, type, notok; struct block_list *tbl; if( sd == NULL || !skill_id ) @@ -1648,10 +1643,10 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 if( sd->autospell3[i].lock ) continue; // autospell already being executed - skill = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id; + temp = (sd->autospell3[i].id > 0) ? sd->autospell3[i].id : -sd->autospell3[i].id; sd->state.autocast = 1; - notok = skillnotok(skill, sd); + notok = skill->not_ok(temp, sd); sd->state.autocast = 0; if ( notok ) @@ -1667,26 +1662,26 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 tbl = (sd->autospell3[i].id < 0) ? &sd->bl : bl; - if( (type = skill_get_casttype(skill)) == CAST_GROUND ) { + if( (type = skill->get_casttype(temp)) == CAST_GROUND ) { int maxcount = 0; if( !(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skill)&UF_NOREITERATION && - skill_check_unit_range(&sd->bl,tbl->x,tbl->y,skill,skill_lv) + skill->get_unit_flag(temp)&UF_NOREITERATION && + skill->check_unit_range(&sd->bl,tbl->x,tbl->y,temp,skill_lv) ) { continue; } if( BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skill)&UF_NOFOOTSET && - skill_check_unit_range2(&sd->bl,tbl->x,tbl->y,skill,skill_lv) + skill->get_unit_flag(temp)&UF_NOFOOTSET && + skill->check_unit_range2(&sd->bl,tbl->x,tbl->y,temp,skill_lv) ) { continue; } if( BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skill, skill_lv)) > 0 + (maxcount = skill->get_maxcount(temp, skill_lv)) > 0 ) { int v; for(v=0;v<MAX_SKILLUNITGROUP && sd->ud.skillunit[v] && maxcount;v++) { - if(sd->ud.skillunit[v]->skill_id == skill) + if(sd->ud.skillunit[v]->skill_id == temp) maxcount--; } if( maxcount == 0 ) { @@ -1695,26 +1690,23 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 } } if( battle_config.autospell_check_range && - !battle_check_range(&sd->bl, tbl, skill_get_range2(&sd->bl, skill,skill_lv) + (skill == RG_CLOSECONFINE?0:1)) ) + !battle->check_range(&sd->bl, tbl, skill->get_range2(&sd->bl, temp,skill_lv) + (temp == RG_CLOSECONFINE?0:1)) ) continue; sd->state.autocast = 1; sd->autospell3[i].lock = true; - skill_consume_requirement(sd,skill,skill_lv,1); - switch( type ) - { - case CAST_GROUND: skill_castend_pos2(&sd->bl, tbl->x, tbl->y, skill, skill_lv, tick, 0); break; - case CAST_NODAMAGE: skill_castend_nodamage_id(&sd->bl, tbl, skill, skill_lv, tick, 0); break; - case CAST_DAMAGE: skill_castend_damage_id(&sd->bl, tbl, skill, skill_lv, tick, 0); break; + skill->consume_requirement(sd,temp,skill_lv,1); + switch( type ) { + case CAST_GROUND: skill->castend_pos2(&sd->bl, tbl->x, tbl->y, temp, skill_lv, tick, 0); break; + case CAST_NODAMAGE: skill->castend_nodamage_id(&sd->bl, tbl, temp, skill_lv, tick, 0); break; + case CAST_DAMAGE: skill->castend_damage_id(&sd->bl, tbl, temp, skill_lv, tick, 0); break; } sd->autospell3[i].lock = false; sd->state.autocast = 0; } - if( sd && sd->autobonus3[0].rate ) - { - for( i = 0; i < ARRAYLENGTH(sd->autobonus3); i++ ) - { + if( sd && sd->autobonus3[0].rate ) { + for( i = 0; i < ARRAYLENGTH(sd->autobonus3); i++ ) { if( rnd()%1000 >= sd->autobonus3[i].rate ) continue; if( sd->autobonus3[i].active != INVALID_TIMER ) @@ -1728,12 +1720,12 @@ int skill_onskillusage(struct map_session_data *sd, struct block_list *bl, uint1 return 1; } -/* Splitted off from skill_additional_effect, which is never called when the +/* Splitted off from skill->additional_effect, which is never called when the * attack skill kills the enemy. Place in this function counter status effects * when using skills (eg: Asura's sp regen penalty, or counter-status effects * from cards) that will take effect on the source, not the target. [Skotlex] * Note: Currently this function only applies to Extremity Fist and BF_WEAPON - * type of skills, so not every instance of skill_additional_effect needs a call + * type of skills, so not every instance of skill->additional_effect needs a call * to this one. */ int skill_counter_additional_effect (struct block_list* src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int attack_type, unsigned int tick) @@ -1768,7 +1760,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * continue; //Range Failed. } type = dstsd->addeff2[i].id; - time = skill_get_time2(status_sc2skill(type),7); + time = skill->get_time2(status_sc2skill(type),7); if (dstsd->addeff2[i].flag&ATF_TARGET) status_change_start(src,type,rate,7,0,0,0,time,0); @@ -1779,25 +1771,25 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * } switch(skill_id){ - case MO_EXTREMITYFIST: - sc_start(src,SC_EXTREMITYFIST,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case GS_FULLBUSTER: - sc_start(src,SC_BLIND,2*skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case HFLI_SBR44: //[orn] - case HVAN_EXPLOSION: - if(src->type == BL_HOM){ - TBL_HOM *hd = (TBL_HOM*)src; - hd->homunculus.intimacy = 200; - if (hd->master) - clif_send_homdata(hd->master,SP_INTIMATE,hd->homunculus.intimacy/100); - } - break; - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - attack_type |= BF_WEAPON; - break; + case MO_EXTREMITYFIST: + sc_start(src,SC_EXTREMITYFIST,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case GS_FULLBUSTER: + sc_start(src,SC_BLIND,2*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case HFLI_SBR44: //[orn] + case HVAN_EXPLOSION: + if(src->type == BL_HOM){ + TBL_HOM *hd = (TBL_HOM*)src; + hd->homunculus.intimacy = 200; + if (hd->master) + clif->send_homdata(hd->master,SP_INTIMATE,hd->homunculus.intimacy/100); + } + break; + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + attack_type |= BF_WEAPON; + break; } if(sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && @@ -1805,11 +1797,11 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * sc_start(src,SC_MIRACLE,100,1,battle_config.sg_miracle_skill_duration); if(sd && skill_id && attack_type&BF_MAGIC && status_isdead(bl) && - !(skill_get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) && + !(skill->get_inf(skill_id)&(INF_GROUND_SKILL|INF_SELF_SKILL)) && (rate=pc_checkskill(sd,HW_SOULDRAIN))>0 ){ //Soul Drain should only work on targetted spells [Skotlex] if (pc_issit(sd)) pc_setstand(sd); //Character stuck in attacking animation while 'sitting' fix. [Skotlex] - clif_skill_nodamage(src,bl,HW_SOULDRAIN,rate,1); + clif->skill_nodamage(src,bl,HW_SOULDRAIN,rate,1); status_heal(src, 0, status_get_lv(bl)*(95+15*rate)/100, 2); } @@ -1840,9 +1832,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * } // Trigger counter-spells to retaliate against damage causing skills. - if(dstsd && !status_isdead(bl) && dstsd->autospell2[0].id && - !(skill_id && skill_get_nk(skill_id)&NK_NO_DAMAGE)) - { + if(dstsd && !status_isdead(bl) && dstsd->autospell2[0].id && !(skill_id && skill->get_nk(skill_id)&NK_NO_DAMAGE)) { struct block_list *tbl; struct unit_data *ud; int i, skill_id, skill_lv, rate, type, notok; @@ -1863,7 +1853,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * rate>>=1; dstsd->state.autocast = 1; - notok = skillnotok(skill_id, dstsd); + notok = skill->not_ok(skill_id, dstsd); dstsd->state.autocast = 0; if ( notok ) @@ -1874,22 +1864,22 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * tbl = (dstsd->autospell2[i].id < 0) ? bl : src; - if( (type = skill_get_casttype(skill_id)) == CAST_GROUND ) { + if( (type = skill->get_casttype(skill_id)) == CAST_GROUND ) { int maxcount = 0; if( !(BL_PC&battle_config.skill_reiteration) && - skill_get_unit_flag(skill_id)&UF_NOREITERATION && - skill_check_unit_range(bl,tbl->x,tbl->y,skill_id,skill_lv) + skill->get_unit_flag(skill_id)&UF_NOREITERATION && + skill->check_unit_range(bl,tbl->x,tbl->y,skill_id,skill_lv) ) { continue; } if( BL_PC&battle_config.skill_nofootset && - skill_get_unit_flag(skill_id)&UF_NOFOOTSET && - skill_check_unit_range2(bl,tbl->x,tbl->y,skill_id,skill_lv) + skill->get_unit_flag(skill_id)&UF_NOFOOTSET && + skill->check_unit_range2(bl,tbl->x,tbl->y,skill_id,skill_lv) ) { continue; } if( BL_PC&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(skill_id, skill_lv)) > 0 + (maxcount = skill->get_maxcount(skill_id, skill_lv)) > 0 ) { int v; for(v=0;v<MAX_SKILLUNITGROUP && dstsd->ud.skillunit[v] && maxcount;v++) { @@ -1902,42 +1892,40 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * } } - if( !battle_check_range(src, tbl, skill_get_range2(src, skill_id,skill_lv) + (skill_id == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range ) + if( !battle->check_range(src, tbl, skill->get_range2(src, skill_id,skill_lv) + (skill_id == RG_CLOSECONFINE?0:1)) && battle_config.autospell_check_range ) continue; dstsd->state.autocast = 1; - skill_consume_requirement(dstsd,skill_id,skill_lv,1); + skill->consume_requirement(dstsd,skill_id,skill_lv,1); switch (type) { case CAST_GROUND: - skill_castend_pos2(bl, tbl->x, tbl->y, skill_id, skill_lv, tick, 0); + skill->castend_pos2(bl, tbl->x, tbl->y, skill_id, skill_lv, tick, 0); break; case CAST_NODAMAGE: - skill_castend_nodamage_id(bl, tbl, skill_id, skill_lv, tick, 0); + skill->castend_nodamage_id(bl, tbl, skill_id, skill_lv, tick, 0); break; case CAST_DAMAGE: - skill_castend_damage_id(bl, tbl, skill_id, skill_lv, tick, 0); + skill->castend_damage_id(bl, tbl, skill_id, skill_lv, tick, 0); break; } dstsd->state.autocast = 0; //Set canact delay. [Skotlex] ud = unit_bl2ud(bl); if (ud) { - rate = skill_delayfix(bl, skill_id, skill_lv); + rate = skill->delay_fix(bl, skill_id, skill_lv); if (DIFF_TICK(ud->canact_tick, tick + rate) < 0){ ud->canact_tick = tick+rate; if ( battle_config.display_status_timers && dstsd ) - clif_status_change(bl, SI_ACTIONDELAY, 1, rate, 0, 0, 0); + clif->status_change(bl, SI_ACTIONDELAY, 1, rate, 0, 0, 0); } } } } //Autobonus when attacked - if( dstsd && !status_isdead(bl) && dstsd->autobonus2[0].rate && !(skill_id && skill_get_nk(skill_id)&NK_NO_DAMAGE) ) - { + if( dstsd && !status_isdead(bl) && dstsd->autobonus2[0].rate && !(skill_id && skill->get_nk(skill_id)&NK_NO_DAMAGE) ) { int i; - for( i = 0; i < ARRAYLENGTH(dstsd->autobonus2); i++ ) - { + for( i = 0; i < ARRAYLENGTH(dstsd->autobonus2); i++ ) { if( rnd()%1000 >= dstsd->autobonus2[i].rate ) continue; if( dstsd->autobonus2[i].active != INVALID_TIMER ) @@ -1958,8 +1946,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * - flag is a BCT_ flag to indicate which type of adjustment should be used (BCT_ENEMY/BCT_PARTY/BCT_SELF) are the valid values. --------------------------------------------------------------------------*/ -int skill_break_equip (struct block_list *bl, unsigned short where, int rate, int flag) -{ +int skill_break_equip (struct block_list *bl, unsigned short where, int rate, int flag) { const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM}; const enum sc_type scatk[4] = {SC_STRIPWEAPON, SC_STRIPARMOR, SC_STRIPSHIELD, SC_STRIPHELM}; const enum sc_type scdef[4] = {SC_CP_WEAPON, SC_CP_ARMOR, SC_CP_SHIELD, SC_CP_HELM}; @@ -2005,7 +1992,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in else if (rnd()%10000 >= rate) where&=~where_list[i]; else if (!sd && !(status_get_mode(bl)&MD_BOSS)) //Cause Strip effect. - sc_start(bl,scatk[i],100,0,skill_get_time(status_sc2skill(scatk[i]),1)); + sc_start(bl,scatk[i],100,0,skill->get_time(status_sc2skill(scatk[i]),1)); } } if (!where) //Nothing to break. @@ -2043,14 +2030,13 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in pc_unequipitem(sd, j, 3); } } - clif_equiplist(sd); + clif->equiplist(sd); } return where; //Return list of pieces broken. } -int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time) -{ +int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time) { struct status_change *sc; const int pos[5] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HELM, EQP_ACC}; const enum sc_type sc_atk[5] = {SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC__STRIPACCESSORY}; @@ -2085,15 +2071,14 @@ static int skill_area_temp[8]; - if 'flag&0x1', position update packets must not be sent. - if 'flag&0x2', skill blown ignores players' special_state.no_knockback -------------------------------------------------------------------------*/ -int skill_blown(struct block_list* src, struct block_list* target, int count, int8 dir, int flag) -{ +int skill_blown(struct block_list* src, struct block_list* target, int count, int8 dir, int flag) { int dx = 0, dy = 0; struct skill_unit* su = NULL; nullpo_ret(src); - if (src != target && (map_flag_gvg(target->m) || map[target->m].flag.battleground)) - return 0; //No knocking back in WoE + if (src != target && map[src->m].flag.noknockback) + return 0; //No knocking if (count == 0) return 0; //Actual knockback distance is 0. @@ -2136,8 +2121,7 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in //Checks if 'bl' should reflect back a spell cast by 'src'. //type is the type of magic attack: 0: indirect (aoe), 1: direct (targetted) -static int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) -{ +int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type) { struct status_change *sc = status_get_sc(bl); struct map_session_data* sd = BL_CAST(BL_PC, bl); @@ -2160,7 +2144,7 @@ static int skill_magic_reflect(struct block_list* src, struct block_list* bl, in if( sc->data[SC_KAITE] && (src->type == BL_PC || status_get_lv(src) <= 80) ) {// Kaite only works against non-players if they are low-level. - clif_specialeffect(bl, 438, AREA); + clif->specialeffect(bl, 438, AREA); if( --sc->data[SC_KAITE]->val2 <= 0 ) status_change_end(bl, SC_KAITE, INVALID_TIMER); return 2; @@ -2191,6 +2175,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds struct map_session_data *sd, *tsd; int type,damage,rdamage=0; int8 rmdamage=0;//magic reflected + bool additional_effects = true; if(skill_id > 0 && !skill_lv) return 0; @@ -2202,7 +2187,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds //When caster is not the src of attack, this is a ground skill, and as such, do the relevant target checking. [Skotlex] if (!status_check_skilluse(battle_config.skill_caster_check?src:NULL, bl, skill_id, 2)) return 0; - } else if ((flag&SD_ANIMATION) && skill_get_nk(skill_id)&NK_SPLASH) { + } else if ((flag&SD_ANIMATION) && skill->get_nk(skill_id)&NK_SPLASH) { //Note that splash attacks often only check versus the targetted mob, those around the splash area normally don't get checked for being hidden/cloaked/etc. [Skotlex] if (!status_check_skilluse(src, bl, skill_id, 2)) return 0; @@ -2220,22 +2205,20 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if(skill_id == WZ_FROSTNOVA && dsrc->x == bl->x && dsrc->y == bl->y) return 0; //Trick Dead protects you from damage, but not from buffs and the like, hence it's placed here. - if (sc && sc->data[SC_TRICKDEAD] && !(sstatus->mode&MD_BOSS)) + if (sc && sc->data[SC_TRICKDEAD]) return 0; - dmg = battle_calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF); + dmg = battle->calc_attack(attack_type,src,bl,skill_id,skill_lv,flag&0xFFF); //Skotlex: Adjusted to the new system - if(src->type==BL_PET) - { // [Valaris] + if( src->type == BL_PET ) { // [Valaris] struct pet_data *pd = (TBL_PET*)src; - if (pd->a_skill && pd->a_skill->div_ && pd->a_skill->id == skill_id) - { - int element = skill_get_ele(skill_id, skill_lv); + if (pd->a_skill && pd->a_skill->div_ && pd->a_skill->id == skill_id) { + int element = skill->get_ele(skill_id, skill_lv); /*if (skill_id == -1) Does it ever worked? element = sstatus->rhw.ele;*/ if (element != ELE_NEUTRAL || !(battle_config.attack_attr_none&BL_PET)) - dmg.damage=battle_attr_fix(src, bl, skill_lv, element, tstatus->def_ele, tstatus->ele_lv); + dmg.damage = battle->attr_fix(src, bl, skill_lv, element, tstatus->def_ele, tstatus->ele_lv); else dmg.damage= skill_lv; dmg.damage2=0; @@ -2245,12 +2228,13 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if( dmg.flag&BF_MAGIC && ( skill_id != NPC_EARTHQUAKE || (battle_config.eq_single_target_reflectable && (flag&0xFFF) == 1) ) ) { // Earthquake on multiple targets is not counted as a target skill. [Inkfish] - if( (dmg.damage || dmg.damage2) && (type = skill_magic_reflect(src, bl, src==dsrc)) ) + if( (dmg.damage || dmg.damage2) && (type = skill->magic_reflect(src, bl, src==dsrc)) ) { //Magic reflection, switch caster/target struct block_list *tbl = bl; rmdamage = 1; bl = src; src = tbl; + dsrc = tbl; sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, bl); sc = status_get_sc(bl); @@ -2270,18 +2254,41 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds sc->data[SC_SPIRIT]->val3 = skill_id; sc->data[SC_SPIRIT]->val4 = dsrc->id; } - } + } else if( type != 2 ) /* Kaite bypasses */ + additional_effects = false; /** * Official Magic Reflection Behavior : damage reflected depends on gears caster wears, not target **/ #if MAGIC_REFLECTION_TYPE - if( dmg.dmg_lv != ATK_MISS )//Wiz SL cancelled and consumed fragment - dmg = battle_calc_attack(BF_MAGIC,bl,bl,skill_id,skill_lv,flag&0xFFF); + if( dmg.dmg_lv != ATK_MISS ){ //Wiz SL cancelled and consumed fragment + short s_ele = skill->get_ele(skill_id, skill_lv); + + if (s_ele == -1) // the skill takes the weapon's element + s_ele = sstatus->rhw.ele; + else if (s_ele == -2) //Use status element + s_ele = status_get_attack_sc_element(src,status_get_sc(src)); + else if( s_ele == -3 ) //Use random element + s_ele = rnd()%ELE_MAX; + + dmg.damage = battle->attr_fix(bl, bl, dmg.damage, s_ele, status_get_element(bl), status_get_element_level(bl)); + + if( sc && sc->data[SC_ENERGYCOAT] ) { + struct status_data *status = status_get_status_data(bl); + int per = 100*status->sp / status->max_sp -1; //100% should be counted as the 80~99% interval + per /=20; //Uses 20% SP intervals. + //SP Cost: 1% + 0.5% per every 20% SP + if (!status_charge(bl, 0, (10+5*per)*status->max_sp/1000)) + status_change_end(bl, SC_ENERGYCOAT, INVALID_TIMER); + //Reduction: 6% + 6% every 20% + dmg.damage -= dmg.damage * (6 * (1+per)) / 100; + } + + } #endif } if(sc && sc->data[SC_MAGICROD] && src == dsrc) { - int sp = skill_get_sp(skill_id,skill_lv); + int sp = skill->get_sp(skill_id,skill_lv); dmg.damage = dmg.damage2 = 0; dmg.dmg_lv = ATK_MISS; //This will prevent skill additional effect from taking effect. [Skotlex] sp = sp * sc->data[SC_MAGICROD]->val2 / 100; @@ -2300,19 +2307,19 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds if( damage > 0 && (( dmg.flag&BF_WEAPON && src != bl && ( src == dsrc || ( dsrc->type == BL_SKILL && ( skill_id == SG_SUN_WARM || skill_id == SG_MOON_WARM || skill_id == SG_STAR_WARM ) ) )) || (sc && sc->data[SC_REFLECTDAMAGE])) ) - rdamage = battle_calc_return_damage(bl,src, &damage, dmg.flag, skill_id); + rdamage = battle->calc_return_damage(bl,src, &damage, dmg.flag, skill_id); if( damage && sc && sc->data[SC_GENSOU] && dmg.flag&BF_MAGIC ){ - struct block_list *nbl = NULL; - nbl = battle_getenemyarea(bl,bl->x,bl->y,2,BL_CHAR,bl->id); + struct block_list *nbl; + nbl = battle->get_enemy_area(bl,bl->x,bl->y,2,BL_CHAR,bl->id); if( nbl ){ // Only one target is chosen. damage = damage / 2; // Deflect half of the damage to a target nearby - clif_skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); + clif->skill_damage(bl, nbl, tick, status_get_amotion(src), 0, status_fix_damage(bl,nbl,damage,0), dmg.div_, OB_OBOROGENSOU_TRANSITION_ATK, -1, 6); } } //Skill hit type - type=(skill_id==0)?5:skill_get_hit(skill_id); + type=(skill_id==0)?5:skill->get_hit(skill_id); if(damage < dmg.div_ //Only skills that knockback even when they miss. [Skotlex] @@ -2379,7 +2386,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds { //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] sc_start2(src,SC_COMBO,100,HT_POWER,bl->id,2000); - clif_combo_delay(src,2000); + clif->combo_delay(src,2000); } break; case TK_COUNTER: @@ -2392,7 +2399,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds case SL_STIN: case SL_STUN: if (skill_lv >= 7 && !sd->sc.data[SC_SMA]) - sc_start(src,SC_SMA,100,skill_lv,skill_get_time(SL_SMA, skill_lv)); + sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA, skill_lv)); break; case GS_FULLBUSTER: //Can't attack nor use items until skill's delay expires. [Skotlex] @@ -2408,116 +2415,114 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds break; } //Switch End if (flag) { //Possible to chain - flag = DIFF_TICK(sd->ud.canact_tick, tick); - if (flag < 1) flag = 1; + if ( (flag = DIFF_TICK(sd->ud.canact_tick, tick)) < 50 ) flag = 50;/* less is a waste. */ sc_start2(src,SC_COMBO,100,skill_id,bl->id,flag); - clif_combo_delay(src, flag); + clif->combo_delay(src, flag); } } //Display damage. - switch( skill_id ) - { - case PA_GOSPEL: //Should look like Holy Cross [Skotlex] - dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, 5); - break; - //Skills that need be passed as a normal attack for the client to display correctly. - case HVAN_EXPLOSION: - case NPC_SELFDESTRUCTION: - if(src->type==BL_PC) - dmg.blewcount = 10; - dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex] - // fall through - case KN_AUTOCOUNTER: - case NPC_CRITICALSLASH: - case TF_DOUBLE: - case GS_CHAINACTION: - dmg.dmotion = clif_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2); - break; + switch( skill_id ) { + case PA_GOSPEL: //Should look like Holy Cross [Skotlex] + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion, damage, dmg.div_, CR_HOLYCROSS, -1, 5); + break; + //Skills that need be passed as a normal attack for the client to display correctly. + case HVAN_EXPLOSION: + case NPC_SELFDESTRUCTION: + if(src->type==BL_PC) + dmg.blewcount = 10; + dmg.amotion = 0; //Disable delay or attack will do no damage since source is dead by the time it takes effect. [Skotlex] + // fall through + case KN_AUTOCOUNTER: + case NPC_CRITICALSLASH: + case TF_DOUBLE: + case GS_CHAINACTION: + dmg.dmotion = clif->damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,dmg.type,dmg.damage2); + break; - case AS_SPLASHER: - if( flag&SD_ANIMATION ) // the surrounding targets - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, 5); // needs -1 as skill level - else // the central target doesn't display an animation - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, 5); // needs -2(!) as skill level - break; - case WL_HELLINFERNO: - case SR_EARTHSHAKER: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,6); - break; - case WL_SOULEXPANSION: - case WL_COMET: - case KO_MUCHANAGE: - case NJ_HUUMA: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,8); - break; - case WL_CHAINLIGHTNING_ATK: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6); - break; - case LG_OVERBRAND_BRANDISH: - case LG_OVERBRAND_PLUSATK: - case EL_FIRE_BOMB: - case EL_FIRE_BOMB_ATK: - case EL_FIRE_WAVE: - case EL_FIRE_WAVE_ATK: - case EL_FIRE_MANTLE: - case EL_CIRCLE_OF_FIRE: - case EL_FIRE_ARROW: - case EL_ICE_NEEDLE: - case EL_WATER_SCREW: - case EL_WATER_SCREW_ATK: - case EL_WIND_SLASH: - case EL_TIDAL_WEAPON: - case EL_ROCK_CRUSHER: - case EL_ROCK_CRUSHER_ATK: - case EL_HURRICANE: - case EL_HURRICANE_ATK: - case KO_BAKURETSU: - case GN_CRAZYWEED_ATK: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5); - break; - case GN_SLINGITEM_RANGEMELEEATK: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6); - break; - case EL_STONE_RAIN: - dmg.dmotion = clif_skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5); - break; - case WM_SEVERE_RAINSTORM_MELEE: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skill_lv,5); - break; - case WM_REVERBERATION_MELEE: - case WM_REVERBERATION_MAGIC: - dmg.dmotion = clif_skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6); - break; - case HT_CLAYMORETRAP: - case HT_BLASTMINE: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case RA_CLUSTERBOMB: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id,flag&SD_LEVEL?-1:skill_lv, 5); - if( dsrc != src ) // avoid damage display redundancy - break; - case HT_LANDMINE: - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, type); - break; - case WZ_SIGHTBLASTER: - dmg.dmotion = clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5); + case AS_SPLASHER: + if( flag&SD_ANIMATION ) // the surrounding targets + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, 5); // needs -1 as skill level + else // the central target doesn't display an animation + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -2, 5); // needs -2(!) as skill level + break; + case WL_HELLINFERNO: + case SR_EARTHSHAKER: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,-2,6); + break; + case WL_SOULEXPANSION: + case WL_COMET: + case KO_MUCHANAGE: + case NJ_HUUMA: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,skill_lv,8); + break; + case WL_CHAINLIGHTNING_ATK: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,WL_CHAINLIGHTNING,-2,6); + break; + case LG_OVERBRAND_BRANDISH: + case LG_OVERBRAND_PLUSATK: + case EL_FIRE_BOMB: + case EL_FIRE_BOMB_ATK: + case EL_FIRE_WAVE: + case EL_FIRE_WAVE_ATK: + case EL_FIRE_MANTLE: + case EL_CIRCLE_OF_FIRE: + case EL_FIRE_ARROW: + case EL_ICE_NEEDLE: + case EL_WATER_SCREW: + case EL_WATER_SCREW_ATK: + case EL_WIND_SLASH: + case EL_TIDAL_WEAPON: + case EL_ROCK_CRUSHER: + case EL_ROCK_CRUSHER_ATK: + case EL_HURRICANE: + case EL_HURRICANE_ATK: + case KO_BAKURETSU: + case GN_CRAZYWEED_ATK: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5); + break; + case GN_SLINGITEM_RANGEMELEEATK: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,GN_SLINGITEM,-2,6); + break; + case EL_STONE_RAIN: + dmg.dmotion = clif->skill_damage(dsrc,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,(flag&1)?8:5); + break; + case WM_SEVERE_RAINSTORM_MELEE: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_SEVERE_RAINSTORM,skill_lv,5); + break; + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,WM_REVERBERATION,-2,6); + break; + case HT_CLAYMORETRAP: + case HT_BLASTMINE: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case RA_CLUSTERBOMB: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id,flag&SD_LEVEL?-1:skill_lv, 5); + if( dsrc != src ) // avoid damage display redundancy + break; + case HT_LANDMINE: + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, -1, type); + break; + case WZ_SIGHTBLASTER: + dmg.dmotion = clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5); + break; + case AB_DUPLELIGHT_MELEE: + case AB_DUPLELIGHT_MAGIC: + dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */ + default: + if( flag&SD_ANIMATION && dmg.div_ < 2 ) //Disabling skill animation doesn't works on multi-hit. + type = 5; + if( bl->type == BL_SKILL ){ + TBL_SKILL *su = (TBL_SKILL*)bl; + if( su->group && skill->get_inf2(su->group->skill_id)&INF2_TRAP )// show damage on trap targets + clif->skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5); + } + dmg.dmotion = clif->skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, type); break; - case AB_DUPLELIGHT_MELEE: - case AB_DUPLELIGHT_MAGIC: - dmg.amotion = 300;/* makes the damage value not overlap with previous damage (when displayed by the client) */ - default: - if( flag&SD_ANIMATION && dmg.div_ < 2 ) //Disabling skill animation doesn't works on multi-hit. - type = 5; - if( bl->type == BL_SKILL ){ - TBL_SKILL *su = (TBL_SKILL*)bl; - if( su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP )// show damage on trap targets - clif_skill_damage(src,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, 5); - } - dmg.dmotion = clif_skill_damage(dsrc,bl,tick, dmg.amotion, dmg.dmotion, damage, dmg.div_, skill_id, flag&SD_LEVEL?-1:skill_lv, type); - break; } map_freeblock_lock(); @@ -2527,7 +2532,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds && (!sc || !sc->data[SC_PRESERVE]) && damage < tsd->battle_status.hp) { //Updated to not be able to copy skills if the blow will kill you. [Skotlex] - int copy_skill = skill_id; + int copy_skill = skill_id, cidx = 0; /** * Copy Referal: dummy skills should point to their source upon copying **/ @@ -2557,36 +2562,43 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds copy_skill = LG_OVERBRAND; break; } - - if ((tsd->status.skill[copy_skill].id == 0 || tsd->status.skill[copy_skill].flag == SKILL_FLAG_PLAGIARIZED) && + cidx = skill->get_index(copy_skill); + if ((tsd->status.skill[cidx].id == 0 || tsd->status.skill[cidx].flag == SKILL_FLAG_PLAGIARIZED) && can_copy(tsd,copy_skill,bl)) // Split all the check into their own function [Aru] { - int lv; + int lv, idx = 0; if( sc && sc->data[SC__REPRODUCE] && (lv = sc->data[SC__REPRODUCE]->val1) ) { //Level dependent and limitation. - lv = min(lv,skill_get_max(copy_skill)); - if( tsd->reproduceskill_id && tsd->status.skill[tsd->reproduceskill_id].flag == SKILL_FLAG_PLAGIARIZED ) { - tsd->status.skill[tsd->reproduceskill_id].id = 0; - tsd->status.skill[tsd->reproduceskill_id].lv = 0; - tsd->status.skill[tsd->reproduceskill_id].flag = 0; - clif_deleteskill(tsd,tsd->reproduceskill_id); + lv = min(lv,skill->get_max(copy_skill)); + idx = skill->get_index(tsd->reproduceskill_id); + if( tsd->reproduceskill_id ) { + idx = skill->get_index(tsd->reproduceskill_id); + if(tsd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED ) { + tsd->status.skill[idx].id = 0; + tsd->status.skill[idx].lv = 0; + tsd->status.skill[idx].flag = 0; + clif->deleteskill(tsd,tsd->reproduceskill_id); + } } tsd->reproduceskill_id = copy_skill; pc_setglobalreg(tsd, "REPRODUCE_SKILL", copy_skill); pc_setglobalreg(tsd, "REPRODUCE_SKILL_LV", lv); - tsd->status.skill[copy_skill].id = copy_skill; - tsd->status.skill[copy_skill].lv = lv; - tsd->status.skill[copy_skill].flag = SKILL_FLAG_PLAGIARIZED; - clif_addskill(tsd,copy_skill); + tsd->status.skill[cidx].id = copy_skill; + tsd->status.skill[cidx].lv = lv; + tsd->status.skill[cidx].flag = SKILL_FLAG_PLAGIARIZED; + clif->addskill(tsd,copy_skill); } else { lv = skill_lv; - if (tsd->cloneskill_id && tsd->status.skill[tsd->cloneskill_id].flag == SKILL_FLAG_PLAGIARIZED){ - tsd->status.skill[tsd->cloneskill_id].id = 0; - tsd->status.skill[tsd->cloneskill_id].lv = 0; - tsd->status.skill[tsd->cloneskill_id].flag = 0; - clif_deleteskill(tsd,tsd->cloneskill_id); + if ( tsd->cloneskill_id ) { + idx = skill->get_index(tsd->cloneskill_id); + if ( tsd->status.skill[idx].flag == SKILL_FLAG_PLAGIARIZED){ + tsd->status.skill[idx].id = 0; + tsd->status.skill[idx].lv = 0; + tsd->status.skill[idx].flag = 0; + clif->deleteskill(tsd,tsd->cloneskill_id); + } } if ((type = pc_checkskill(tsd,RG_PLAGIARISM)) < lv) @@ -2596,34 +2608,34 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds pc_setglobalreg(tsd, "CLONE_SKILL", copy_skill); pc_setglobalreg(tsd, "CLONE_SKILL_LV", lv); - tsd->status.skill[skill_id].id = copy_skill; - tsd->status.skill[skill_id].lv = lv; - tsd->status.skill[skill_id].flag = SKILL_FLAG_PLAGIARIZED; - clif_addskill(tsd,skill_id); + tsd->status.skill[idx].id = copy_skill; + tsd->status.skill[idx].lv = lv; + tsd->status.skill[idx].flag = SKILL_FLAG_PLAGIARIZED; + clif->addskill(tsd,copy_skill); } } } - if (dmg.dmg_lv >= ATK_MISS && (type = skill_get_walkdelay(skill_id, skill_lv)) > 0) - { //Skills with can't walk delay also stop normal attacking for that + if (dmg.dmg_lv >= ATK_MISS && (type = skill->get_walkdelay(skill_id, skill_lv)) > 0) { + //Skills with can't walk delay also stop normal attacking for that //duration when the attack connects. [Skotlex] struct unit_data *ud = unit_bl2ud(src); if (ud && DIFF_TICK(ud->attackabletime, tick + type) < 0) ud->attackabletime = tick + type; } - if( !dmg.amotion ) - { //Instant damage + if( !dmg.amotion ) { + //Instant damage if( !sc || (!sc->data[SC_DEVOTION] && skill_id != CR_REFLECTSHIELD) ) status_fix_damage(src,bl,damage,dmg.dmotion); //Deal damage before knockback to allow stuff like firewall+storm gust combo. - if( !status_isdead(bl) ) - skill_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick); + if( !status_isdead(bl) && additional_effects ) + skill->additional_effect(src,bl,skill_id,skill_lv,dmg.flag,dmg.dmg_lv,tick); if( damage > 0 ) //Counter status effects [Skotlex] - skill_counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick); + skill->counter_additional_effect(src,bl,skill_id,skill_lv,dmg.flag,tick); } // Hell Inferno burning status only starts if Fire part hits. if( skill_id == WL_HELLINFERNO && dmg.damage > 0 ) - sc_start4(bl,SC_BURNING,55+5*skill_lv,skill_lv,1000,src->id,0,skill_get_time(skill_id,skill_lv)); + sc_start4(bl,SC_BURNING,55+5*skill_lv,skill_lv,1000,src->id,0,skill->get_time(skill_id,skill_lv)); // Apply knock back chance in SC_TRIANGLESHOT skill. else if( skill_id == SC_TRIANGLESHOT && rnd()%100 > (1 + skill_lv) ) dmg.blewcount = 0; @@ -2654,35 +2666,35 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds //blown-specific handling switch( skill_id ) { case LG_OVERBRAND: - if( skill_blown(dsrc,bl,dmg.blewcount,dir,0) ) { + if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) ) { short dir_x, dir_y; dir_x = dirx[(dir+4)%8]; dir_y = diry[(dir+4)%8]; if( map_getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 ) - skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag ); + skill->addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag ); } else - skill_addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag ); + skill->addtimerskill(src, tick + status_get_amotion(src), bl->id, 0, 0, LG_OVERBRAND_PLUSATK, skill_lv, BF_WEAPON, flag ); break; case SR_KNUCKLEARROW: - if( skill_blown(dsrc,bl,dmg.blewcount,dir,0) && !(flag&4) ) { + if( skill->blown(dsrc,bl,dmg.blewcount,dir,0) && !(flag&4) ) { short dir_x, dir_y; dir_x = dirx[(dir+4)%8]; dir_y = diry[(dir+4)%8]; if( map_getcell(bl->m, bl->x+dir_x, bl->y+dir_y, CELL_CHKNOPASS) != 0 ) - skill_addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4); + skill->addtimerskill(src, tick + 300 * ((flag&2) ? 1 : 2), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|4); } break; case GN_WALLOFTHORN: unit_stop_walking(bl,1); - skill_blown(dsrc,bl,dmg.blewcount,dir, 0x2 ); - clif_fixpos(bl); + skill->blown(dsrc,bl,dmg.blewcount,dir, 0x2 ); + clif->fixpos(bl); break; default: - skill_blown(dsrc,bl,dmg.blewcount,dir, 0x0 ); + skill->blown(dsrc,bl,dmg.blewcount,dir, 0x0 ); if ( !dmg.blewcount && bl->type == BL_SKILL && damage > 0 ){ TBL_SKILL *su = (TBL_SKILL*)bl; if( su->group && su->group->skill_id == HT_BLASTMINE) - skill_blown(src, bl, 3, -1, 0); + skill->blown(src, bl, 3, -1, 0); } break; } @@ -2690,10 +2702,9 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds //Delayed damage must be dealt after the knockback (it needs to know actual position of target) if (dmg.amotion) - battle_delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion); + battle->delay_damage(tick, dmg.amotion,src,bl,dmg.flag,skill_id,skill_lv,damage,dmg.dmg_lv,dmg.dmotion, additional_effects); - if( sc && sc->data[SC_DEVOTION] && skill_id != PA_PRESSURE ) - { + if( sc && sc->data[SC_DEVOTION] && skill_id != PA_PRESSURE ) { struct status_change_entry *sce = sc->data[SC_DEVOTION]; struct block_list *d_bl = map_id2bl(sce->val1); @@ -2703,13 +2714,12 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds ) && check_distance_bl(bl, d_bl, sce->val3) ) { if(!rmdamage){ - clif_damage(d_bl,d_bl, gettick(), 0, 0, damage, 0, 0, 0); + clif->damage(d_bl,d_bl, gettick(), 0, 0, damage, 0, 0, 0); status_fix_damage(NULL,d_bl, damage, 0); - } - else{//Reflected magics are done directly on the target not on paladin + } else{ //Reflected magics are done directly on the target not on paladin //This check is only for magical skill. //For BF_WEAPON skills types track var rdamage and function battle_calc_return_damage - clif_damage(bl,bl, gettick(), 0, 0, damage, 0, 0, 0); + clif->damage(bl,bl, gettick(), 0, 0, damage, 0, 0, 0); status_fix_damage(bl,bl, damage, 0); } } @@ -2725,9 +2735,9 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds int rate = 50 + skill_lv * 5; rate = rate + (status_get_lv(src) - status_get_lv(bl)); if(rnd()%100 < rate) - skill_addtimerskill(src,tick + 800,bl->id,0,0,skill_id,skill_lv,0,flag); + skill->addtimerskill(src,tick + 800,bl->id,0,0,skill_id,skill_lv,0,flag); } else if( skill_id == SC_FATALMENACE ) - skill_addtimerskill(src,tick + 800,bl->id,skill_area_temp[4],skill_area_temp[5],skill_id,skill_lv,0,flag); + skill->addtimerskill(src,tick + 800,bl->id,skill_area_temp[4],skill_area_temp[5],skill_id,skill_lv,0,flag); } if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) @@ -2737,25 +2747,33 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds (dmg.flag&BF_MISC && (skill_id == RA_CLUSTERBOMB || skill_id == RA_FIRINGTRAP || skill_id == RA_ICEBOUNDTRAP || skill_id == RK_DRAGONBREATH)) ) ) { if (battle_config.left_cardfix_to_right) - battle_drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->mode&MD_BOSS); + battle->drain(sd, bl, dmg.damage, dmg.damage, tstatus->race, tstatus->mode&MD_BOSS); else - battle_drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS); + battle->drain(sd, bl, dmg.damage, dmg.damage2, tstatus->race, tstatus->mode&MD_BOSS); } if( rdamage > 0 ) { if( sc && sc->data[SC_REFLECTDAMAGE] ) { - if( src != bl )// Don't reflect your own damage (Grand Cross) - map_foreachinshootrange(battle_damage_area,bl,skill_get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,bl,dmg.amotion,sstatus->dmotion,rdamage,tstatus->race); + if( src != bl ) {// Don't reflect your own damage (Grand Cross) + bool change = false; + if( sd && !sd->state.autocast ) + change = true; + if( change ) + sd->state.autocast = 1; + map_foreachinshootrange(battle->damage_area,bl,skill->get_splash(LG_REFLECTDAMAGE,1),BL_CHAR,tick,bl,dmg.amotion,sstatus->dmotion,rdamage,tstatus->race); + if( change ) + sd->state.autocast = 0; + } } else { if( dmg.amotion ) - battle_delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0); + battle->delay_damage(tick, dmg.amotion,bl,src,0,CR_REFLECTSHIELD,0,rdamage,ATK_DEF,0,additional_effects); else status_fix_damage(bl,src,rdamage,0); - clif_damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0); // in aegis damage reflected is shown in single hit. + clif->damage(src,src,tick, dmg.amotion,0,rdamage,1,4,0); // in aegis damage reflected is shown in single hit. //Use Reflect Shield to signal this kind of skill trigger. [Skotlex] if( tsd && src != bl ) - battle_drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); - skill_additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); + battle->drain(tsd, src, rdamage, rdamage, sstatus->race, is_boss(src)); + skill->additional_effect(bl, src, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); } } if( damage > 0 ) { @@ -2764,14 +2782,14 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds **/ switch( skill_id ) { case RK_CRUSHSTRIKE: - skill_break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon. + skill->break_equip(src,EQP_WEAPON,2000,BCT_SELF); // 20% chance to destroy the weapon. break; case GC_VENOMPRESSURE: { struct status_change *ssc = status_get_sc(src); if( ssc && ssc->data[SC_POISONINGWEAPON] && rnd()%100 < 70 + 5*skill_lv ) { - sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill_get_time2(GC_POISONINGWEAPON, 1)); + sc_start(bl,ssc->data[SC_POISONINGWEAPON]->val2,100,ssc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON, 1)); status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } } break; @@ -2783,7 +2801,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds break; } if( sd ) - skill_onskillusage(sd, bl, skill_id, tick); + skill->onskillusage(sd, bl, skill_id, tick); } if (!(flag&2) && @@ -2794,8 +2812,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds sc->data[SC_DOUBLECAST] && rnd() % 100 < sc->data[SC_DOUBLECAST]->val2) { -// skill_addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); - skill_addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); +// skill->addtimerskill(src, tick + dmg.div_*dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); + skill->addtimerskill(src, tick + dmg.amotion, bl->id, 0, 0, skill_id, skill_lv, BF_MAGIC, flag|2); } map_freeblock_unlock(); @@ -2809,8 +2827,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds * then call func with source,target,skill_id,skill_lv,tick,flag *------------------------------------------*/ typedef int (*SkillFunc)(struct block_list *, struct block_list *, int, int, unsigned int, int); -int skill_area_sub (struct block_list *bl, va_list ap) -{ +int skill_area_sub (struct block_list *bl, va_list ap) { struct block_list *src; uint16 skill_id,skill_lv; int flag; @@ -2826,11 +2843,10 @@ int skill_area_sub (struct block_list *bl, va_list ap) flag=va_arg(ap,int); func=va_arg(ap,SkillFunc); - if(battle_check_target(src,bl,flag) > 0) - { + if(battle->check_target(src,bl,flag) > 0) { // several splash skills need this initial dummy packet to display correctly if (flag&SD_PREAMBLE && skill_area_temp[2] == 0) - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); if (flag&(SD_SPLASH|SD_PREAMBLE)) skill_area_temp[2]++; @@ -2840,8 +2856,7 @@ int skill_area_sub (struct block_list *bl, va_list ap) return 0; } -static int skill_check_unit_range_sub (struct block_list *bl, va_list ap) -{ +int skill_check_unit_range_sub (struct block_list *bl, va_list ap) { struct skill_unit *unit; uint16 skill_id,g_skill_id; @@ -2891,7 +2906,7 @@ static int skill_check_unit_range_sub (struct block_list *bl, va_list ap) case SC_DIMENSIONDOOR: case SC_BLOODYLUST: //Non stackable on themselves and traps (including venom dust which does not has the trap inf2 set) - if (skill_id != g_skill_id && !(skill_get_inf2(g_skill_id)&INF2_TRAP) && g_skill_id != AS_VENOMDUST && g_skill_id != MH_POISON_MIST) + if (skill_id != g_skill_id && !(skill->get_inf2(g_skill_id)&INF2_TRAP) && g_skill_id != AS_VENOMDUST && g_skill_id != MH_POISON_MIST) return 0; break; default: //Avoid stacking with same kind of trap. [Skotlex] @@ -2903,22 +2918,20 @@ static int skill_check_unit_range_sub (struct block_list *bl, va_list ap) return 1; } -static int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv) -{ +int skill_check_unit_range (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv) { //Non players do not check for the skill's splash-trigger area. - int range = bl->type==BL_PC?skill_get_unit_range(skill_id, skill_lv):0; - int layout_type = skill_get_unit_layout_type(skill_id,skill_lv); - if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + int range = bl->type == BL_PC ? skill->get_unit_range(skill_id, skill_lv):0; + int layout_type = skill->get_unit_layout_type(skill_id,skill_lv); + if ( layout_type == - 1 || layout_type > MAX_SQUARE_LAYOUT ) { ShowError("skill_check_unit_range: unsupported layout type %d for skill %d\n",layout_type,skill_id); return 0; } range += layout_type; - return map_foreachinarea(skill_check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skill_id); + return map_foreachinarea(skill->check_unit_range_sub,bl->m,x-range,y-range,x+range,y+range,BL_SKILL,skill_id); } -static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) -{ +int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) { uint16 skill_id; if(bl->prev == NULL) @@ -2937,24 +2950,22 @@ static int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) return 1; } -static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv) -{ +int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv) { int range, type; switch (skill_id) { // to be expanded later - case WZ_ICEWALL: - range = 2; - break; - default: - { - int layout_type = skill_get_unit_layout_type(skill_id,skill_lv); - if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { - ShowError("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skill_id); - return 0; + case WZ_ICEWALL: + range = 2; + break; + default: { + int layout_type = skill->get_unit_layout_type(skill_id,skill_lv); + if (layout_type==-1 || layout_type>MAX_SQUARE_LAYOUT) { + ShowError("skill_check_unit_range2: unsupported layout type %d for skill %d\n",layout_type,skill_id); + return 0; + } + range = skill->get_unit_range(skill_id,skill_lv) + layout_type; } - range = skill_get_unit_range(skill_id,skill_lv) + layout_type; - } - break; + break; } // if the caster is a monster/NPC, only check for players @@ -2964,7 +2975,7 @@ static int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 else type = BL_PC; - return map_foreachinarea(skill_check_unit_range2_sub, bl->m, + return map_foreachinarea(skill->check_unit_range2_sub, bl->m, x - range, y - range, x + range, y + range, type, skill_id); } @@ -2993,8 +3004,7 @@ int skill_guildaura_sub (struct map_session_data* sd, int id, int strvit, int ag * &1: finished casting the skill (invoke hp/sp/item consumption) * &2: picked menu entry (Warp Portal, Teleport and other menu based skills) *------------------------------------------*/ -static int skill_check_condition_mercenary(struct block_list *bl, int skill, int lv, int type) -{ +int skill_check_condition_mercenary(struct block_list *bl, int skill_id, int lv, int type) { struct status_data *status; struct map_session_data *sd = NULL; int i, hp, sp, hp_rate, sp_rate, state, mhp; @@ -3012,7 +3022,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int } status = status_get_status_data(bl); - if( (idx = skill_get_index(skill)) == 0 ) + if( (idx = skill->get_index(skill_id)) == 0 ) return 0; // Requeriments @@ -3037,11 +3047,9 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int else sp += (status->max_sp * (-sp_rate)) / 100; - if( bl->type == BL_HOM ) - { // Intimacy Requeriments + if( bl->type == BL_HOM ) { // Intimacy Requeriments struct homun_data *hd = BL_CAST(BL_HOM, bl); - switch( skill ) - { + switch( skill_id ) { case HFLI_SBR44: if( hd->homunculus.intimacy <= 200 ) return 0; @@ -3053,27 +3061,22 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int } } - if( !(type&2) ) - { - if( hp > 0 && status->hp <= (unsigned int)hp ) - { - clif_skill_fail(sd, skill, USESKILL_FAIL_HP_INSUFFICIENT, 0); + if( !(type&2) ) { + if( hp > 0 && status->hp <= (unsigned int)hp ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_HP_INSUFFICIENT, 0); return 0; } - if( sp > 0 && status->sp <= (unsigned int)sp ) - { - clif_skill_fail(sd, skill, USESKILL_FAIL_SP_INSUFFICIENT, 0); + if( sp > 0 && status->sp <= (unsigned int)sp ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_SP_INSUFFICIENT, 0); return 0; } } if( !type ) - switch( state ) - { + switch( state ) { case ST_MOVE_ENABLE: - if( !unit_can_move(bl) ) - { - clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); + if( !unit_can_move(bl) ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); return 0; } break; @@ -3089,7 +3092,7 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int index[i] = pc_search_inventory(sd, itemid[i]); if( index[i] < 0 || sd->status.inventory[index[i]].amount < amount[i] ) { - clif_skill_fail(sd, skill, USESKILL_FAIL_LEVEL, 0); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); return 0; } } @@ -3110,21 +3113,19 @@ static int skill_check_condition_mercenary(struct block_list *bl, int skill, int } /*========================================== - * + * what the hell it doesn't need to receive this many params, it doesn't do anything ~_~ *------------------------------------------*/ -int skill_area_sub_count (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) -{ +int skill_area_sub_count (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag) { return 1; } /*========================================== * *------------------------------------------*/ -static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) -{ +int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) { struct block_list *src = map_id2bl(id),*target; struct unit_data *ud = unit_bl2ud(src); - struct skill_timerskill *skl = NULL; + struct skill_timerskill *skl; int range; nullpo_ret(src); @@ -3162,24 +3163,24 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) break; case BA_FROSTJOKER: case DC_SCREAM: - range= skill_get_splash(skl->skill_id, skl->skill_lv); - map_foreachinarea(skill_frostjoke_scream,skl->map,skl->x-range,skl->y-range, + range= skill->get_splash(skl->skill_id, skl->skill_lv); + map_foreachinarea(skill->frostjoke_scream,skl->map,skl->x-range,skl->y-range, skl->x+range,skl->y+range,BL_CHAR,src,skl->skill_id,skl->skill_lv,tick); break; case NPC_EARTHQUAKE: if( skl->type > 1 ) - skill_addtimerskill(src,tick+250,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); - skill_area_temp[0] = map_foreachinrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, BCT_ENEMY, skill_area_sub_count); + skill->addtimerskill(src,tick+250,src->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); + skill_area_temp[0] = map_foreachinrange(skill->area_sub, src, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, src, skl->skill_id, skl->skill_lv, tick, BCT_ENEMY, skill->area_sub_count); skill_area_temp[1] = src->id; skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub, src, skill_get_splash(skl->skill_id, skl->skill_lv), splash_target(src), src, skl->skill_id, skl->skill_lv, tick, skl->flag, skill_castend_damage_id); + map_foreachinrange(skill->area_sub, src, skill->get_splash(skl->skill_id, skl->skill_lv), splash_target(src), src, skl->skill_id, skl->skill_lv, tick, skl->flag, skill->castend_damage_id); break; case WZ_WATERBALL: - skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify + skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify if (!status_isdead(target)) - skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); + skill->attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); if (skl->type>1 && !status_isdead(target) && !status_isdead(src)) { - skill_addtimerskill(src,tick+125,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); + skill->addtimerskill(src,tick+125,target->id,0,0,skl->skill_id,skl->skill_lv,skl->type-1,skl->flag); } else { struct status_change *sc = status_get_sc(src); if(sc) { @@ -3193,41 +3194,35 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) /** * Warlock **/ - case WL_CHAINLIGHTNING_ATK: - { + case WL_CHAINLIGHTNING_ATK: { struct block_list *nbl = NULL; // Next Target of Chain - skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); // Hit a Lightning on the current Target - skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if( skl->type > 1 ) - { // Remaining Chains Hit - nbl = battle_getenemyarea(src,target->x,target->y,2,BL_CHAR|BL_SKILL,target->id); // Search for a new Target around current one... - if( nbl == NULL && skl->x > 1 ) - { + skill->attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); // Hit a Lightning on the current Target + skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify + if( skl->type > 1 ) { // Remaining Chains Hit + nbl = battle->get_enemy_area(src,target->x,target->y,2,BL_CHAR|BL_SKILL,target->id); // Search for a new Target around current one... + if( nbl == NULL && skl->x > 1 ) { nbl = target; skl->x--; - } - else skl->x = 3; + } else + skl->x = 3; } if( nbl ) - skill_addtimerskill(src,tick+status_get_adelay(src),nbl->id,skl->x,0,WL_CHAINLIGHTNING_ATK,skl->skill_lv,skl->type-1,skl->flag); + skill->addtimerskill(src,tick+status_get_adelay(src),nbl->id,skl->x,0,WL_CHAINLIGHTNING_ATK,skl->skill_lv,skl->type-1,skl->flag); } break; case WL_TETRAVORTEX_FIRE: case WL_TETRAVORTEX_WATER: case WL_TETRAVORTEX_WIND: case WL_TETRAVORTEX_GROUND: - skill_attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag|SD_ANIMATION); - skill_toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify - if( skl->type >= 3 ) - { // Final Hit - if( !status_isdead(target) ) - { // Final Status Effect + skill->attack(BF_MAGIC,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag|SD_ANIMATION); + skill->toggle_magicpower(src, skl->skill_id); // only the first hit will be amplify + if( skl->type >= 3 ) { // Final Hit + if( !status_isdead(target) ) { // Final Status Effect int effects[4] = { SC_BURNING, SC_FREEZING, SC_BLEEDING, SC_STUN }, applyeffects[4] = { 0, 0, 0, 0 }, i, j = 0, k = 0; - for( i = 1; i <= 8; i = i + i ) - { + for( i = 1; i <= 8; i = i + i ) { if( skl->x&i ) { applyeffects[j] = effects[k]; @@ -3235,20 +3230,19 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) } k++; } - if( j ) - { + if( j ) { i = applyeffects[rnd()%j]; status_change_start(target, i, 10000, skl->skill_lv, (i == SC_BURNING ? 1000 : (i == SC_BLEEDING ? src->id : 0)), (i == SC_BURNING ? src->id : 0), - 0, skill_get_time(WL_TETRAVORTEX,skl->skill_lv), 0); + 0, skill->get_time(WL_TETRAVORTEX,skl->skill_lv), 0); } } } break; case WM_REVERBERATION_MELEE: case WM_REVERBERATION_MAGIC: - skill_castend_damage_id(src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); // damage should split among targets + skill->castend_damage_id(src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); // damage should split among targets break; case SC_FATALMENACE: if( src == target ) // Casters Part @@ -3265,19 +3259,19 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) struct map_session_data *tsd = NULL; if( (tsd = ((TBL_PC*)target)) && !pc_issit(tsd) ) { pc_setsit(tsd); - skill_sit(tsd,1); - clif_sitting(&tsd->bl); + skill->sit(tsd,1); + clif->sitting(&tsd->bl); } } break; case LG_OVERBRAND_BRANDISH: case LG_OVERBRAND_PLUSATK: case SR_KNUCKLEARROW: - skill_attack(BF_WEAPON, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); + skill->attack(BF_WEAPON, src, src, target, skl->skill_id, skl->skill_lv, tick, skl->flag|SD_LEVEL); break; case GN_SPORE_EXPLOSION: - map_foreachinrange(skill_area_sub, target, skill_get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, - src, skl->skill_id, skl->skill_lv, 0, skl->flag|1|BCT_ENEMY, skill_castend_damage_id); + map_foreachinrange(skill->area_sub, target, skill->get_splash(skl->skill_id, skl->skill_lv), BL_CHAR, + src, skl->skill_id, skl->skill_lv, 0, skl->flag|1|BCT_ENEMY, skill->castend_damage_id); break; case CH_PALMSTRIKE: { @@ -3285,39 +3279,35 @@ static int skill_timerskill(int tid, unsigned int tick, int id, intptr_t data) struct status_change* sc = status_get_sc(src); if( ( tsc && tsc->option&OPTION_HIDE ) || ( sc && sc->option&OPTION_HIDE ) ){ - skill_blown(src,target,skill_get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0 ); + skill->blown(src,target,skill->get_blewcount(skl->skill_id, skl->skill_lv), -1, 0x0 ); break; } } default: - skill_attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); + skill->attack(skl->type,src,src,target,skl->skill_id,skl->skill_lv,tick,skl->flag); break; } - } - else { + } else { if(src->m != skl->map) break; - switch( skl->skill_id ) - { + switch( skl->skill_id ) { case WZ_METEOR: - if( skl->type >= 0 ) - { + if( skl->type >= 0 ) { int x = skl->type>>16, y = skl->type&0xFFFF; if( path_search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL) ) - skill_unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag); + skill->unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag); if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) ) - clif_skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick); + clif->skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick); } else if( path_search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) ) - skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag); + skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag); break; - case GN_CRAZYWEED_ATK: - { - int dummy = 1, i = skill_get_unit_range(skl->skill_id,skl->skill_lv); - map_foreachinarea(skill_cell_overlap, src->m, skl->x-i, skl->y-i, skl->x+i, skl->y+i, BL_SKILL, skl->skill_id, &dummy, src); + case GN_CRAZYWEED_ATK: { + int dummy = 1, i = skill->get_unit_range(skl->skill_id,skl->skill_lv); + map_foreachinarea(skill->cell_overlap, src->m, skl->x-i, skl->y-i, skl->x+i, skl->y+i, BL_SKILL, skl->skill_id, &dummy, src); } case WL_EARTHSTRAIN: - skill_unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag); + skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag); break; } @@ -3345,7 +3335,7 @@ int skill_addtimerskill (struct block_list *src, unsigned int tick, int target, if( i == MAX_SKILLTIMERSKILL ) return 1; ud->skilltimerskill[i] = ers_alloc(skill_timer_ers, struct skill_timerskill); - ud->skilltimerskill[i]->timer = add_timer(tick, skill_timerskill, src->id, i); + ud->skilltimerskill[i]->timer = add_timer(tick, skill->timerskill, src->id, i); ud->skilltimerskill[i]->src_id = src->id; ud->skilltimerskill[i]->target_id = target; ud->skilltimerskill[i]->skill_id = skill_id; @@ -3371,34 +3361,32 @@ int skill_cleartimerskill (struct block_list *src) for(i=0;i<MAX_SKILLTIMERSKILL;i++) { if(ud->skilltimerskill[i]) { - delete_timer(ud->skilltimerskill[i]->timer, skill_timerskill); + delete_timer(ud->skilltimerskill[i]->timer, skill->timerskill); ers_free(skill_timer_ers, ud->skilltimerskill[i]); ud->skilltimerskill[i]=NULL; } } return 1; } -static int skill_ative_reverberation( struct block_list *bl, va_list ap) { +int skill_activate_reverbetion( struct block_list *bl, va_list ap) { struct skill_unit *su = (TBL_SKILL*)bl; struct skill_unit_group *sg; if( bl->type != BL_SKILL ) return 0; if( su->alive && (sg = su->group) && sg->skill_id == WM_REVERBERATION ) { - map_foreachinrange(skill_trap_splash, bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, gettick()); + map_foreachinrange(skill->trap_splash, bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, bl, gettick()); su->limit=DIFF_TICK(gettick(),sg->tick); sg->unit_id = UNT_USED_TRAPS; } return 0; } -static int skill_reveal_trap (struct block_list *bl, va_list ap) -{ +int skill_reveal_trap (struct block_list *bl, va_list ap) { TBL_SKILL *su = (TBL_SKILL*)bl; - if (su->alive && su->group && skill_get_inf2(su->group->skill_id)&INF2_TRAP) - { //Reveal trap. + if (su->alive && su->group && skill->get_inf2(su->group->skill_id)&INF2_TRAP) { //Reveal trap. //Change look is not good enough, the client ignores it as an actual trap still. [Skotlex] - //clif_changetraplook(bl, su->group->unit_id); - clif_skill_setunit(su); + //clif->changetraplook(bl, su->group->unit_id); + clif->skill_setunit(su); return 1; } return 0; @@ -3430,12 +3418,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint if (status_isdead(bl)) return 1; - if (skill_id && skill_get_type(skill_id) == BF_MAGIC && status_isimmune(bl) == 100) - { //GTB makes all targetted magic display miss with a single bolt. + if (skill_id && skill->get_type(skill_id) == BF_MAGIC && status_isimmune(bl) == 100) { + //GTB makes all targetted magic display miss with a single bolt. sc_type sct = status_skill2sc(skill_id); if(sct != SC_NONE) status_change_end(bl, sct, INVALID_TIMER); - clif_skill_damage(src, bl, tick, status_get_amotion(src), status_get_dmotion(bl), 0, 1, skill_id, skill_lv, skill_get_hit(skill_id)); + clif->skill_damage(src, bl, tick, status_get_amotion(src), status_get_dmotion(bl), 0, 1, skill_id, skill_lv, skill->get_hit(skill_id)); return 1; } @@ -3447,1200 +3435,1187 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint map_freeblock_lock(); - switch(skill_id) - { - case MER_CRASH: - case SM_BASH: - case MS_BASH: - case MC_MAMMONITE: - case TF_DOUBLE: - case AC_DOUBLE: - case MA_DOUBLE: - case AS_SONICBLOW: - case KN_PIERCE: - case ML_PIERCE: - case KN_SPEARBOOMERANG: - case TF_POISON: - case TF_SPRINKLESAND: - case AC_CHARGEARROW: - case MA_CHARGEARROW: - case RG_INTIMIDATE: - case AM_ACIDTERROR: - case BA_MUSICALSTRIKE: - case DC_THROWARROW: - case BA_DISSONANCE: - case CR_HOLYCROSS: - case NPC_DARKCROSS: - case CR_SHIELDCHARGE: - case CR_SHIELDBOOMERANG: - case NPC_PIERCINGATT: - case NPC_MENTALBREAKER: - case NPC_RANGEATTACK: - case NPC_CRITICALSLASH: - case NPC_COMBOATTACK: - case NPC_GUIDEDATTACK: - case NPC_POISON: - case NPC_RANDOMATTACK: - case NPC_WATERATTACK: - case NPC_GROUNDATTACK: - case NPC_FIREATTACK: - case NPC_WINDATTACK: - case NPC_POISONATTACK: - case NPC_HOLYATTACK: - case NPC_DARKNESSATTACK: - case NPC_TELEKINESISATTACK: - case NPC_UNDEADATTACK: - case NPC_ARMORBRAKE: - case NPC_WEAPONBRAKER: - case NPC_HELMBRAKE: - case NPC_SHIELDBRAKE: - case NPC_BLINDATTACK: - case NPC_SILENCEATTACK: - case NPC_STUNATTACK: - case NPC_PETRIFYATTACK: - case NPC_CURSEATTACK: - case NPC_SLEEPATTACK: - case LK_AURABLADE: - case LK_SPIRALPIERCE: - case ML_SPIRALPIERCE: - case LK_HEADCRUSH: - case CG_ARROWVULCAN: - case HW_MAGICCRASHER: - case ITM_TOMAHAWK: - case MO_TRIPLEATTACK: - case CH_CHAINCRUSH: - case CH_TIGERFIST: - case PA_SHIELDCHAIN: // Shield Chain - case PA_SACRIFICE: - case WS_CARTTERMINATION: // Cart Termination - case AS_VENOMKNIFE: - case HT_PHANTASMIC: - case HT_POWER: - case TK_DOWNKICK: - case TK_COUNTER: - case GS_CHAINACTION: - case GS_TRIPLEACTION: - case GS_MAGICALBULLET: - case GS_TRACKING: - case GS_PIERCINGSHOT: - case GS_RAPIDSHOWER: - case GS_DUST: - case GS_DISARM: // Added disarm. [Reddozen] - case GS_FULLBUSTER: - case NJ_SYURIKEN: - case NJ_KUNAI: - case ASC_BREAKER: - case HFLI_MOON: //[orn] - case HFLI_SBR44: //[orn] - case NPC_BLEEDING: - case NPC_CRITICALWOUND: - case NPC_HELLPOWER: - case RK_SONICWAVE: - case RK_HUNDREDSPEAR: - case AB_DUPLELIGHT_MELEE: - case RA_AIMEDBOLT: - case NC_AXEBOOMERANG: - case NC_POWERSWING: - case GC_CROSSIMPACT: - case GC_VENOMPRESSURE: - case SC_TRIANGLESHOT: - case SC_FEINTBOMB: - case LG_BANISHINGPOINT: - case LG_SHIELDPRESS: - case LG_RAGEBURST: - case LG_RAYOFGENESIS: - case LG_HESPERUSLIT: - case SR_FALLENEMPIRE: - case SR_CRESCENTELBOW_AUTOSPELL: - case SR_GATEOFHELL: - case SR_GENTLETOUCH_QUIET: - case WM_SEVERE_RAINSTORM_MELEE: - case WM_GREAT_ECHO: - case GN_SLINGITEM_RANGEMELEEATK: - case KO_JYUMONJIKIRI: - case KO_SETSUDAN: - case KO_KAIHOU: - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; - - /** - * Mechanic (MADO GEAR) - **/ - case NC_BOOSTKNUCKLE: - case NC_PILEBUNKER: - case NC_VULCANARM: - case NC_COLDSLOWER: - case NC_ARMSCANNON: - if (sd) pc_overheat(sd,1); - case RK_WINDCUTTER: - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); - break; - - case LK_JOINTBEAT: // decide the ailment first (affects attack damage and effect) - switch( rnd()%6 ){ - case 0: flag |= BREAK_ANKLE; break; - case 1: flag |= BREAK_WRIST; break; - case 2: flag |= BREAK_KNEE; break; - case 3: flag |= BREAK_SHOULDER; break; - case 4: flag |= BREAK_WAIST; break; - case 5: flag |= BREAK_NECK; break; - } - //TODO: is there really no cleaner way to do this? - sc = status_get_sc(bl); - if (sc) sc->jb_flag = flag; - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + switch(skill_id) { + case MER_CRASH: + case SM_BASH: + case MS_BASH: + case MC_MAMMONITE: + case TF_DOUBLE: + case AC_DOUBLE: + case MA_DOUBLE: + case AS_SONICBLOW: + case KN_PIERCE: + case ML_PIERCE: + case KN_SPEARBOOMERANG: + case TF_POISON: + case TF_SPRINKLESAND: + case AC_CHARGEARROW: + case MA_CHARGEARROW: + case RG_INTIMIDATE: + case AM_ACIDTERROR: + case BA_MUSICALSTRIKE: + case DC_THROWARROW: + case BA_DISSONANCE: + case CR_HOLYCROSS: + case NPC_DARKCROSS: + case CR_SHIELDCHARGE: + case CR_SHIELDBOOMERANG: + case NPC_PIERCINGATT: + case NPC_MENTALBREAKER: + case NPC_RANGEATTACK: + case NPC_CRITICALSLASH: + case NPC_COMBOATTACK: + case NPC_GUIDEDATTACK: + case NPC_POISON: + case NPC_RANDOMATTACK: + case NPC_WATERATTACK: + case NPC_GROUNDATTACK: + case NPC_FIREATTACK: + case NPC_WINDATTACK: + case NPC_POISONATTACK: + case NPC_HOLYATTACK: + case NPC_DARKNESSATTACK: + case NPC_TELEKINESISATTACK: + case NPC_UNDEADATTACK: + case NPC_ARMORBRAKE: + case NPC_WEAPONBRAKER: + case NPC_HELMBRAKE: + case NPC_SHIELDBRAKE: + case NPC_BLINDATTACK: + case NPC_SILENCEATTACK: + case NPC_STUNATTACK: + case NPC_PETRIFYATTACK: + case NPC_CURSEATTACK: + case NPC_SLEEPATTACK: + case LK_AURABLADE: + case LK_SPIRALPIERCE: + case ML_SPIRALPIERCE: + case LK_HEADCRUSH: + case CG_ARROWVULCAN: + case HW_MAGICCRASHER: + case ITM_TOMAHAWK: + case MO_TRIPLEATTACK: + case CH_CHAINCRUSH: + case CH_TIGERFIST: + case PA_SHIELDCHAIN: // Shield Chain + case PA_SACRIFICE: + case WS_CARTTERMINATION: // Cart Termination + case AS_VENOMKNIFE: + case HT_PHANTASMIC: + case HT_POWER: + case TK_DOWNKICK: + case TK_COUNTER: + case GS_CHAINACTION: + case GS_TRIPLEACTION: + case GS_MAGICALBULLET: + case GS_TRACKING: + case GS_PIERCINGSHOT: + case GS_RAPIDSHOWER: + case GS_DUST: + case GS_DISARM: // Added disarm. [Reddozen] + case GS_FULLBUSTER: + case NJ_SYURIKEN: + case NJ_KUNAI: + case ASC_BREAKER: + case HFLI_MOON: //[orn] + case HFLI_SBR44: //[orn] + case NPC_BLEEDING: + case NPC_CRITICALWOUND: + case NPC_HELLPOWER: + case RK_SONICWAVE: + case RK_HUNDREDSPEAR: + case AB_DUPLELIGHT_MELEE: + case RA_AIMEDBOLT: + case NC_AXEBOOMERANG: + case NC_POWERSWING: + case GC_CROSSIMPACT: + case GC_VENOMPRESSURE: + case SC_TRIANGLESHOT: + case SC_FEINTBOMB: + case LG_BANISHINGPOINT: + case LG_SHIELDPRESS: + case LG_RAGEBURST: + case LG_RAYOFGENESIS: + case LG_HESPERUSLIT: + case SR_FALLENEMPIRE: + case SR_CRESCENTELBOW_AUTOSPELL: + case SR_GATEOFHELL: + case SR_GENTLETOUCH_QUIET: + case WM_SEVERE_RAINSTORM_MELEE: + case WM_GREAT_ECHO: + case GN_SLINGITEM_RANGEMELEEATK: + case KO_JYUMONJIKIRI: + case KO_SETSUDAN: + case KO_KAIHOU: + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); break; - case MO_COMBOFINISH: - if (!(flag&1) && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) - { //Becomes a splash attack when Soul Linked. - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skill_id, skill_lv),splash_target(src), - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - } else - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; + /** + * Mechanic (MADO GEAR) + **/ + case NC_BOOSTKNUCKLE: + case NC_PILEBUNKER: + case NC_VULCANARM: + case NC_COLDSLOWER: + case NC_ARMSCANNON: + if (sd) pc_overheat(sd,1); + case RK_WINDCUTTER: + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); + break; - case TK_STORMKICK: // Taekwon kicks [Dralnu] - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_area_temp[1] = 0; - map_foreachinrange(skill_attack_area, src, - skill_get_splash(skill_id, skill_lv), splash_target(src), - BF_WEAPON, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); - break; + case LK_JOINTBEAT: // decide the ailment first (affects attack damage and effect) + switch( rnd()%6 ){ + case 0: flag |= BREAK_ANKLE; break; + case 1: flag |= BREAK_WRIST; break; + case 2: flag |= BREAK_KNEE; break; + case 3: flag |= BREAK_SHOULDER; break; + case 4: flag |= BREAK_WAIST; break; + case 5: flag |= BREAK_NECK; break; + } + //TODO: is there really no cleaner way to do this? + sc = status_get_sc(bl); + if (sc) sc->jb_flag = flag; + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; - case KN_CHARGEATK: - { - bool path = path_search_long(NULL, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL); - unsigned int dist = distance_bl(src, bl); - uint8 dir = map_calc_dir(bl, src->x, src->y); + case MO_COMBOFINISH: + if (!(flag&1) && sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_MONK) + { //Becomes a splash attack when Soul Linked. + map_foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv),splash_target(src), + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, + skill->castend_damage_id); + } else + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; - // teleport to target (if not on WoE grounds) - if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 0, 1) ) - clif_slide(src, bl->x, bl->y); + case TK_STORMKICK: // Taekwon kicks [Dralnu] + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill_area_temp[1] = 0; + map_foreachinrange(skill->attack_area, src, + skill->get_splash(skill_id, skill_lv), splash_target(src), + BF_WEAPON, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); + break; - // cause damage and knockback if the path to target was a straight one - if( path ) - { - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, dist); - skill_blown(src, bl, dist, dir, 0); - //HACK: since knockback officially defaults to the left, the client also turns to the left... therefore, - // make the caster look in the direction of the target - unit_setdir(src, (dir+4)%8); - } + case KN_CHARGEATK: { + bool path = path_search_long(NULL, src->m, src->x, src->y, bl->x, bl->y,CELL_CHKWALL); + unsigned int dist = distance_bl(src, bl); + uint8 dir = map_calc_dir(bl, src->x, src->y); + + // teleport to target (if not on WoE grounds) + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 0, 1) ) + clif->slide(src, bl->x, bl->y); + + // cause damage and knockback if the path to target was a straight one + if( path ) { + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, dist); + skill->blown(src, bl, dist, dir, 0); + //HACK: since knockback officially defaults to the left, the client also turns to the left... therefore, + // make the caster look in the direction of the target + unit_setdir(src, (dir+4)%8); + } - } - break; + } + break; - case NC_FLAMELAUNCHER: - if (sd) pc_overheat(sd,1); - case SN_SHARPSHOOTING: - case MA_SHARPSHOOTING: - case NJ_KAMAITACHI: - case LG_CANNONSPEAR: - //It won't shoot through walls since on castend there has to be a direct - //line of sight between caster and target. - skill_area_temp[1] = bl->id; - map_foreachinpath (skill_attack_area,src->m,src->x,src->y,bl->x,bl->y, - skill_get_splash(skill_id, skill_lv),skill_get_maxcount(skill_id,skill_lv), splash_target(src), - skill_get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY); - break; + case NC_FLAMELAUNCHER: + if (sd) pc_overheat(sd,1); + case SN_SHARPSHOOTING: + case MA_SHARPSHOOTING: + case NJ_KAMAITACHI: + case LG_CANNONSPEAR: + //It won't shoot through walls since on castend there has to be a direct + //line of sight between caster and target. + skill_area_temp[1] = bl->id; + map_foreachinpath (skill->attack_area,src->m,src->x,src->y,bl->x,bl->y, + skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src), + skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY); + break; - case NPC_ACIDBREATH: - case NPC_DARKNESSBREATH: - case NPC_FIREBREATH: - case NPC_ICEBREATH: - case NPC_THUNDERBREATH: - skill_area_temp[1] = bl->id; - map_foreachinpath(skill_attack_area,src->m,src->x,src->y,bl->x,bl->y, - skill_get_splash(skill_id, skill_lv),skill_get_maxcount(skill_id,skill_lv), splash_target(src), - skill_get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY); - break; + case NPC_ACIDBREATH: + case NPC_DARKNESSBREATH: + case NPC_FIREBREATH: + case NPC_ICEBREATH: + case NPC_THUNDERBREATH: + skill_area_temp[1] = bl->id; + map_foreachinpath(skill->attack_area,src->m,src->x,src->y,bl->x,bl->y, + skill->get_splash(skill_id, skill_lv),skill->get_maxcount(skill_id,skill_lv), splash_target(src), + skill->get_type(skill_id),src,src,skill_id,skill_lv,tick,flag,BCT_ENEMY); + break; - case MO_INVESTIGATE: - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); - break; + case MO_INVESTIGATE: + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + break; - case RG_BACKSTAP: - { - uint8 dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl); - if ((!check_distance_bl(src, bl, 0) && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) { - status_change_end(src, SC_HIDING, INVALID_TIMER); - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); - dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] - unit_setdir(bl,dir); + case RG_BACKSTAP: + { + uint8 dir = map_calc_dir(src, bl->x, bl->y), t_dir = unit_getdir(bl); + if ((!check_distance_bl(src, bl, 0) && !map_check_dir(dir, t_dir)) || bl->type == BL_SKILL) { + status_change_end(src, SC_HIDING, INVALID_TIMER); + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); + dir = dir < 4 ? dir+4 : dir-4; // change direction [Celest] + unit_setdir(bl,dir); + } + else if (sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } - else if (sd) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; - - case MO_FINGEROFFENSIVE: - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - if (battle_config.finger_offensive_type && sd) { - int i; - for (i = 1; i < sd->spiritball_old; i++) - skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); - } - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); - break; + break; - case MO_CHAINCOMBO: - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); - break; + case MO_FINGEROFFENSIVE: + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + if (battle_config.finger_offensive_type && sd) { + int i; + for (i = 1; i < sd->spiritball_old; i++) + skill->addtimerskill(src, tick + i * 200, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); + } + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + break; - case NJ_ISSEN: - status_change_end(src, SC_NEN, INVALID_TIMER); - status_change_end(src, SC_HIDING, INVALID_TIMER); - // fall through - case MO_EXTREMITYFIST: - { - short x, y, i = 2; // Move 2 cells for Issen(from target) - struct block_list *mbl = bl; - short dir = 0; - - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + case MO_CHAINCOMBO: + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + break; - if( skill_id == MO_EXTREMITYFIST ) + case NJ_ISSEN: + status_change_end(src, SC_NEN, INVALID_TIMER); + status_change_end(src, SC_HIDING, INVALID_TIMER); + // fall through + case MO_EXTREMITYFIST: { - mbl = src; - i = 3; // for Asura(from caster) - status_set_sp(src, 0, 0); - status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); - status_change_end(src, SC_BLADESTOP, INVALID_TIMER); -#ifdef RENEWAL - sc_start(src,SC_EXTREMITYFIST2,100,skill_lv,skill_get_time(skill_id,skill_lv)); -#endif - }else - status_set_hp(src, -#ifdef RENEWAL - max(status_get_max_hp(src)/100, 1) -#else - 1 -#endif - , 0); - - dir = map_calc_dir(src,bl->x,bl->y); - if( dir > 0 && dir < 4) x = -i; - else if( dir > 4 ) x = i; - else x = 0; - if( dir > 2 && dir < 6 ) y = -i; - else if( dir == 7 || dir < 2 ) y = i; - else y = 0; - if( (mbl == src || (!map_flag_gvg(src->m) && !map[src->m].flag.battleground) ) && // only NJ_ISSEN don't have slide effect in GVG - unit_movepos(src, mbl->x+x, mbl->y+y, 1, 1) ) { - clif_slide(src, src->x, src->y); - //uncomment this if you want to remove MO_EXTREMITYFIST glitchy walking effect. [malufett] - //clif_fixpos(src); - } - } - break; + short x, y, i = 2; // Move 2 cells for Issen(from target) + struct block_list *mbl = bl; + short dir = 0; + + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - //Splash attack skills. - case AS_GRIMTOOTH: - case MC_CARTREVOLUTION: - case NPC_SPLASHATTACK: - flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit - case AS_SPLASHER: - case SM_MAGNUM: - case MS_MAGNUM: - case HT_BLITZBEAT: - case AC_SHOWER: - case MA_SHOWER: - case MG_NAPALMBEAT: - case MG_FIREBALL: - case RG_RAID: - case HW_NAPALMVULCAN: - case NJ_HUUMA: - case NJ_BAKUENRYU: - case ASC_METEORASSAULT: - case GS_DESPERADO: - case GS_SPREADATTACK: - case NPC_EARTHQUAKE: - case NPC_PULSESTRIKE: - case NPC_HELLJUDGEMENT: - case NPC_VAMPIRE_GIFT: - case RK_IGNITIONBREAK: - case AB_JUDEX: - case WL_SOULEXPANSION: - case WL_CRIMSONROCK: - case WL_COMET: - case WL_JACKFROST: - case RA_ARROWSTORM: - case RA_WUGDASH: - case NC_SELFDESTRUCTION: - case NC_AXETORNADO: - case GC_ROLLINGCUTTER: - case GC_COUNTERSLASH: - case LG_MOONSLASHER: - case LG_EARTHDRIVE: - case SR_TIGERCANNON: - case SR_RAMPAGEBLASTER: - case SR_SKYNETBLOW: - case SR_WINDMILL: - case SR_RIDEINLIGHTNING: - case WM_SOUND_OF_DESTRUCTION: - case WM_REVERBERATION_MELEE: - case WM_REVERBERATION_MAGIC: - case SO_VARETYR_SPEAR: - case GN_CART_TORNADO: - case GN_CARTCANNON: - case KO_HAPPOKUNAI: - case KO_HUUMARANKA: - case KO_MUCHANAGE: - case KO_BAKURETSU: - if( flag&1 ) {//Recursive invocation - // skill_area_temp[0] holds number of targets in area - // skill_area_temp[1] holds the id of the original target - // skill_area_temp[2] counts how many targets have already been processed - int sflag = skill_area_temp[0] & 0xFFF, heal; - if( flag&SD_LEVEL ) - sflag |= SD_LEVEL; // -1 will be used in packets instead of the skill level - if( skill_area_temp[1] != bl->id && !(skill_get_inf2(skill_id)&INF2_NPC_SKILL) ) - sflag |= SD_ANIMATION; // original target gets no animation (as well as all NPC skills) - - heal = skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag); - if( skill_id == NPC_VAMPIRE_GIFT && heal > 0 ) { - clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); - status_heal(src,heal,0,0); + if( skill_id == MO_EXTREMITYFIST ) + { + mbl = src; + i = 3; // for Asura(from caster) + status_set_sp(src, 0, 0); + status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); + status_change_end(src, SC_BLADESTOP, INVALID_TIMER); + #ifdef RENEWAL + sc_start(src,SC_EXTREMITYFIST2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + #endif + }else + status_set_hp(src, + #ifdef RENEWAL + max(status_get_max_hp(src)/100, 1) + #else + 1 + #endif + , 0); + + dir = map_calc_dir(src,bl->x,bl->y); + if( dir > 0 && dir < 4) x = -i; + else if( dir > 4 ) x = i; + else x = 0; + if( dir > 2 && dir < 6 ) y = -i; + else if( dir == 7 || dir < 2 ) y = i; + else y = 0; + if( (mbl == src || (!map_flag_gvg(src->m) && !map[src->m].flag.battleground) ) && // only NJ_ISSEN don't have slide effect in GVG + unit_movepos(src, mbl->x+x, mbl->y+y, 1, 1) ) { + clif->slide(src, src->x, src->y); + //uncomment this if you want to remove MO_EXTREMITYFIST glitchy walking effect. [malufett] + //clif->fixpos(src); + } } - } else { - switch ( skill_id ) { - case NJ_BAKUENRYU: - case LG_EARTHDRIVE: - case GN_CARTCANNON: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case LG_MOONSLASHER: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - break; - case NPC_EARTHQUAKE://FIXME: Isn't EarthQuake a ground skill after all? - skill_addtimerskill(src,tick+250,src->id,0,0,skill_id,skill_lv,2,flag|BCT_ENEMY|SD_SPLASH|1); - default: - break; + break; + + //Splash attack skills. + case AS_GRIMTOOTH: + case MC_CARTREVOLUTION: + case NPC_SPLASHATTACK: + flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit + case AS_SPLASHER: + case SM_MAGNUM: + case MS_MAGNUM: + case HT_BLITZBEAT: + case AC_SHOWER: + case MA_SHOWER: + case MG_NAPALMBEAT: + case MG_FIREBALL: + case RG_RAID: + case HW_NAPALMVULCAN: + case NJ_HUUMA: + case NJ_BAKUENRYU: + case ASC_METEORASSAULT: + case GS_DESPERADO: + case GS_SPREADATTACK: + case NPC_EARTHQUAKE: + case NPC_PULSESTRIKE: + case NPC_HELLJUDGEMENT: + case NPC_VAMPIRE_GIFT: + case RK_IGNITIONBREAK: + case AB_JUDEX: + case WL_SOULEXPANSION: + case WL_CRIMSONROCK: + case WL_COMET: + case WL_JACKFROST: + case RA_ARROWSTORM: + case RA_WUGDASH: + case NC_SELFDESTRUCTION: + case NC_AXETORNADO: + case GC_ROLLINGCUTTER: + case GC_COUNTERSLASH: + case LG_MOONSLASHER: + case LG_EARTHDRIVE: + case SR_TIGERCANNON: + case SR_RAMPAGEBLASTER: + case SR_SKYNETBLOW: + case SR_WINDMILL: + case SR_RIDEINLIGHTNING: + case WM_SOUND_OF_DESTRUCTION: + case WM_REVERBERATION_MELEE: + case WM_REVERBERATION_MAGIC: + case SO_VARETYR_SPEAR: + case GN_CART_TORNADO: + case GN_CARTCANNON: + case KO_HAPPOKUNAI: + case KO_HUUMARANKA: + case KO_MUCHANAGE: + case KO_BAKURETSU: + if( flag&1 ) {//Recursive invocation + // skill_area_temp[0] holds number of targets in area + // skill_area_temp[1] holds the id of the original target + // skill_area_temp[2] counts how many targets have already been processed + int sflag = skill_area_temp[0] & 0xFFF, heal; + if( flag&SD_LEVEL ) + sflag |= SD_LEVEL; // -1 will be used in packets instead of the skill level + if( skill_area_temp[1] != bl->id && !(skill->get_inf2(skill_id)&INF2_NPC_SKILL) ) + sflag |= SD_ANIMATION; // original target gets no animation (as well as all NPC skills) + + heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, sflag); + if( skill_id == NPC_VAMPIRE_GIFT && heal > 0 ) { + clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1); + status_heal(src,heal,0,0); + } + } else { + switch ( skill_id ) { + case NJ_BAKUENRYU: + case LG_EARTHDRIVE: + case GN_CARTCANNON: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case LG_MOONSLASHER: + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + break; + case NPC_EARTHQUAKE://FIXME: Isn't EarthQuake a ground skill after all? + skill->addtimerskill(src,tick+250,src->id,0,0,skill_id,skill_lv,2,flag|BCT_ENEMY|SD_SPLASH|1); + default: + break; + } + + skill_area_temp[0] = 0; + skill_area_temp[1] = bl->id; + skill_area_temp[2] = 0; + if( skill_id == WL_CRIMSONROCK ) { + skill_area_temp[4] = bl->x; + skill_area_temp[5] = bl->y; + } + if( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC ) + skill_area_temp[1] = 0; + // if skill damage should be split among targets, count them + //SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets + //special case: Venom Splasher uses a different range for searching than for splashing + if( flag&SD_LEVEL || skill->get_nk(skill_id)&NK_SPLASHSPLIT ) + skill_area_temp[0] = map_foreachinrange(skill->area_sub, bl, (skill_id == AS_SPLASHER)?1:skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count); + + // recursive invocation of skill->castend_damage_id() with flag|1 + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), ( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC )?BL_CHAR:splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); } + break; - skill_area_temp[0] = 0; - skill_area_temp[1] = bl->id; - skill_area_temp[2] = 0; - if( skill_id == WL_CRIMSONROCK ) { - skill_area_temp[4] = bl->x; - skill_area_temp[5] = bl->y; - } - if( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC ) - skill_area_temp[1] = 0; - // if skill damage should be split among targets, count them - //SD_LEVEL -> Forced splash damage for Auto Blitz-Beat -> count targets - //special case: Venom Splasher uses a different range for searching than for splashing - if( flag&SD_LEVEL || skill_get_nk(skill_id)&NK_SPLASHSPLIT ) - skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, (skill_id == AS_SPLASHER)?1:skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, BCT_ENEMY, skill_area_sub_count); - - // recursive invocation of skill_castend_damage_id() with flag|1 - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), ( skill_id == WM_REVERBERATION_MELEE || skill_id == WM_REVERBERATION_MAGIC )?BL_CHAR:splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - } - break; + case KN_BRANDISHSPEAR: + case ML_BRANDISH: + //Coded apart for it needs the flag passed to the damage calculation. + if (skill_area_temp[1] != bl->id) + skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION); + else + skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); + break; - case KN_BRANDISHSPEAR: - case ML_BRANDISH: - //Coded apart for it needs the flag passed to the damage calculation. - if (skill_area_temp[1] != bl->id) - skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION); - else - skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); - break; + case KN_BOWLINGBASH: + case MS_BOWLINGBASH: + if(flag&1){ + if(bl->id==skill_area_temp[1]) + break; + //two hits for 500% + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); + } else { + int i,c; + c = skill->get_blewcount(skill_id,skill_lv); + // keep moving target in the direction that src is looking, square by square + for(i=0;i<c;i++){ + if (!skill->blown(src,bl,1,(unit_getdir(src)+4)%8,0x1)) + break; //Can't knockback + skill_area_temp[0] = map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count); + if( skill_area_temp[0] > 1 ) break; // collision + } + clif->blown(bl); //Update target pos. + if (i!=c) { //Splash + skill_area_temp[1] = bl->id; + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id); + } + //Weirdo dual-hit property, two attacks for 500% + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); + } + break; - case KN_BOWLINGBASH: - case MS_BOWLINGBASH: - if(flag&1){ - if(bl->id==skill_area_temp[1]) - break; - //two hits for 500% - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); - } else { - int i,c; - c = skill_get_blewcount(skill_id,skill_lv); - // keep moving target in the direction that src is looking, square by square - for(i=0;i<c;i++){ - if (!skill_blown(src,bl,1,(unit_getdir(src)+4)%8,0x1)) - break; //Can't knockback - skill_area_temp[0] = map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill_area_sub_count); - if( skill_area_temp[0] > 1 ) break; // collision - } - clif_blown(bl); //Update target pos. - if (i!=c) { //Splash + case KN_SPEARSTAB: + if(flag&1) { + if (bl->id==skill_area_temp[1]) + break; + if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION)) + skill->blown(src,bl,skill_area_temp[2],-1,0); + } else { + int x=bl->x,y=bl->y,i,dir; + dir = map_calc_dir(bl,src->x,src->y); skill_area_temp[1] = bl->id; - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); + skill_area_temp[2] = skill->get_blewcount(skill_id,skill_lv); + // all the enemies between the caster and the target are hit, as well as the target + if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0)) + skill->blown(src,bl,skill_area_temp[2],-1,0); + for (i=0;i<4;i++) { + map_foreachincell(skill->area_sub,bl->m,x,y,BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + x += dirx[dir]; + y += diry[dir]; + } } - //Weirdo dual-hit property, two attacks for 500% - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); - } - break; + break; - case KN_SPEARSTAB: - if(flag&1) { - if (bl->id==skill_area_temp[1]) - break; - if (skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION)) - skill_blown(src,bl,skill_area_temp[2],-1,0); - } else { - int x=bl->x,y=bl->y,i,dir; - dir = map_calc_dir(bl,src->x,src->y); - skill_area_temp[1] = bl->id; - skill_area_temp[2] = skill_get_blewcount(skill_id,skill_lv); - // all the enemies between the caster and the target are hit, as well as the target - if (skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0)) - skill_blown(src,bl,skill_area_temp[2],-1,0); - for (i=0;i<4;i++) { - map_foreachincell(skill_area_sub,bl->m,x,y,BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - x += dirx[dir]; - y += diry[dir]; - } + case TK_TURNKICK: + case MO_BALKYOUNG: //Active part of the attack. Skill-attack [Skotlex] + { + skill_area_temp[1] = bl->id; //NOTE: This is used in skill->castend_nodamage_id to avoid affecting the target. + if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag)) + map_foreachinrange(skill->area_sub,bl, + skill->get_splash(skill_id, skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1, + skill->castend_nodamage_id); } - break; - - case TK_TURNKICK: - case MO_BALKYOUNG: //Active part of the attack. Skill-attack [Skotlex] - { - skill_area_temp[1] = bl->id; //NOTE: This is used in skill_castend_nodamage_id to avoid affecting the target. - if (skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag)) - map_foreachinrange(skill_area_sub,bl, - skill_get_splash(skill_id, skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1, - skill_castend_nodamage_id); - } - break; - case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex] - // clif_skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/ - clif_damage(src,bl,tick,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack. - skill_addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); - break; + break; + case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex] + // clif->skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/ + clif->damage(src,bl,tick,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack. + skill->addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag); + break; - case PR_TURNUNDEAD: - case ALL_RESURRECTION: - if (!battle_check_undead(tstatus->race, tstatus->def_ele)) + case PR_TURNUNDEAD: + case ALL_RESURRECTION: + if (!battle->check_undead(tstatus->race, tstatus->def_ele)) + break; + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); break; - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - break; - case MG_SOULSTRIKE: - case NPC_DARKSTRIKE: - case MG_COLDBOLT: - case MG_FIREBOLT: - case MG_LIGHTNINGBOLT: - case WZ_EARTHSPIKE: - case AL_HEAL: - case AL_HOLYLIGHT: - case WZ_JUPITEL: - case NPC_DARKTHUNDER: - case PR_ASPERSIO: - case MG_FROSTDIVER: - case WZ_SIGHTBLASTER: - case WZ_SIGHTRASHER: - case NJ_KOUENKA: - case NJ_HYOUSENSOU: - case NJ_HUUJIN: - case AB_ADORAMUS: - case AB_RENOVATIO: - case AB_HIGHNESSHEAL: - case AB_DUPLELIGHT_MAGIC: - case WM_METALICSOUND: - case MH_ERASER_CUTTER: - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - break; + case MG_SOULSTRIKE: + case NPC_DARKSTRIKE: + case MG_COLDBOLT: + case MG_FIREBOLT: + case MG_LIGHTNINGBOLT: + case WZ_EARTHSPIKE: + case AL_HEAL: + case AL_HOLYLIGHT: + case WZ_JUPITEL: + case NPC_DARKTHUNDER: + case PR_ASPERSIO: + case MG_FROSTDIVER: + case WZ_SIGHTBLASTER: + case WZ_SIGHTRASHER: + case NJ_KOUENKA: + case NJ_HYOUSENSOU: + case NJ_HUUJIN: + case AB_ADORAMUS: + case AB_RENOVATIO: + case AB_HIGHNESSHEAL: + case AB_DUPLELIGHT_MAGIC: + case WM_METALICSOUND: + case MH_ERASER_CUTTER: + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); + break; - case NPC_MAGICALATTACK: - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - sc_start(src,status_skill2sc(skill_id),100,skill_lv,skill_get_time(skill_id,skill_lv)); - break; + case NPC_MAGICALATTACK: + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); + sc_start(src,status_skill2sc(skill_id),100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; - case HVAN_CAPRICE: //[blackhole89] - { - int ran=rnd()%4; - int sid = 0; - switch(ran) + case HVAN_CAPRICE: //[blackhole89] { - case 0: sid=MG_COLDBOLT; break; - case 1: sid=MG_FIREBOLT; break; - case 2: sid=MG_LIGHTNINGBOLT; break; - case 3: sid=WZ_EARTHSPIKE; break; + int ran=rnd()%4; + int sid = 0; + switch(ran) + { + case 0: sid=MG_COLDBOLT; break; + case 1: sid=MG_FIREBOLT; break; + case 2: sid=MG_LIGHTNINGBOLT; break; + case 3: sid=WZ_EARTHSPIKE; break; + } + skill->attack(BF_MAGIC,src,src,bl,sid,skill_lv,tick,flag|SD_LEVEL); } - skill_attack(BF_MAGIC,src,src,bl,sid,skill_lv,tick,flag|SD_LEVEL); - } - break; - case WZ_WATERBALL: - { - int range = skill_lv / 2; - int maxlv = skill_get_max(skill_id); // learnable level - int count = 0; - int x, y; - struct skill_unit* unit; - - if( skill_lv > maxlv ) + break; + case WZ_WATERBALL: { - if( src->type == BL_MOB && skill_lv == 10 ) - range = 4; - else - range = maxlv / 2; - } + int range = skill_lv / 2; + int maxlv = skill->get_max(skill_id); // learnable level + int count = 0; + int x, y; + struct skill_unit* unit; - for( y = src->y - range; y <= src->y + range; ++y ) - for( x = src->x - range; x <= src->x + range; ++x ) + if( skill_lv > maxlv ) { - if( !map_find_skill_unit_oncell(src,x,y,SA_LANDPROTECTOR,NULL,1) ) + if( src->type == BL_MOB && skill_lv == 10 ) + range = 4; + else + range = maxlv / 2; + } + + for( y = src->y - range; y <= src->y + range; ++y ) + for( x = src->x - range; x <= src->x + range; ++x ) { - if( src->type != BL_PC || map_getcell(src->m,x,y,CELL_CHKWATER) ) // non-players bypass the water requirement - count++; // natural water cell - else if( (unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL || (unit = map_find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL ) + if( !map_find_skill_unit_oncell(src,x,y,SA_LANDPROTECTOR,NULL,1) ) { - count++; // skill-induced water cell - skill_delunit(unit); // consume cell + if( src->type != BL_PC || map_getcell(src->m,x,y,CELL_CHKWATER) ) // non-players bypass the water requirement + count++; // natural water cell + else if( (unit = map_find_skill_unit_oncell(src,x,y,SA_DELUGE,NULL,1)) != NULL || (unit = map_find_skill_unit_oncell(src,x,y,NJ_SUITON,NULL,1)) != NULL ) + { + count++; // skill-induced water cell + skill->delunit(unit); // consume cell + } } } - } - if( count > 1 ) // queue the remaining count - 1 timerskill Waterballs - skill_addtimerskill(src,tick+150,bl->id,0,0,skill_id,skill_lv,count-1,flag); - } - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - break; - - case PR_BENEDICTIO: - //Should attack undead and demons. [Skotlex] - if (battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON) - skill_attack(BF_MAGIC, src, src, bl, skill_id, skill_lv, tick, flag); - break; - - case SL_SMA: - status_change_end(src, SC_SMA, INVALID_TIMER); - case SL_STIN: - case SL_STUN: - if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { - status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( count > 1 ) // queue the remaining count - 1 timerskill Waterballs + skill->addtimerskill(src,tick+150,bl->id,0,0,skill_id,skill_lv,count-1,flag); + } + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); break; - } - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - break; - case NPC_DARKBREATH: - clif_emotion(src,E_AG); - case SN_FALCONASSAULT: - case PA_PRESSURE: - case CR_ACIDDEMONSTRATION: - case TF_THROWSTONE: - case NPC_SMOKING: - case GS_FLING: - case NJ_ZENYNAGE: - case GN_THORNS_TRAP: - case GN_HELLS_PLANT_ATK: - skill_attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); - break; - /** - * Rune Knight - **/ - case RK_DRAGONBREATH: { - struct status_change *tsc = NULL; - if( (tsc = status_get_sc(bl)) && (tsc->data[SC_HIDING] )) { - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - } else - skill_attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); - } + case PR_BENEDICTIO: + //Should attack undead and demons. [Skotlex] + if (battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON) + skill->attack(BF_MAGIC, src, src, bl, skill_id, skill_lv, tick, flag); break; - case NPC_SELFDESTRUCTION: { - struct status_change *tsc = NULL; - if( (tsc = status_get_sc(bl)) && tsc->data[SC_HIDING] ) + case SL_SMA: + status_change_end(src, SC_SMA, INVALID_TIMER); + case SL_STIN: + case SL_STUN: + if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { + status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); break; - } - case HVAN_EXPLOSION: - if (src != bl) - skill_attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); - break; - - // Celest - case PF_SOULBURN: - if (rnd()%100 < (skill_lv < 5 ? 30 + skill_lv * 10 : 70)) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if (skill_lv == 5) - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - status_percent_damage(src, bl, 0, 100, false); - } else { - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - if (skill_lv == 5) - skill_attack(BF_MAGIC,src,src,src,skill_id,skill_lv,tick,flag); - status_percent_damage(src, src, 0, 100, false); - } - break; - case NPC_BLOODDRAIN: - case NPC_ENERGYDRAIN: - { - int heal = skill_attack( (skill_id == NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC, - src, src, bl, skill_id, skill_lv, tick, flag); - if (heal > 0){ - clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); - status_heal(src, heal, 0, 0); + case NPC_DARKBREATH: + clif->emotion(src,E_AG); + case SN_FALCONASSAULT: + case PA_PRESSURE: + case CR_ACIDDEMONSTRATION: + case TF_THROWSTONE: + case NPC_SMOKING: + case GS_FLING: + case NJ_ZENYNAGE: + case GN_THORNS_TRAP: + case GN_HELLS_PLANT_ATK: + skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); + break; + /** + * Rune Knight + **/ + case RK_DRAGONBREATH: { + struct status_change *tsc = NULL; + if( (tsc = status_get_sc(bl)) && (tsc->data[SC_HIDING] )) { + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + } else + skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); } - } - break; - - case GS_BULLSEYE: - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; - - case NJ_KASUMIKIRI: - if (skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag) > 0) - sc_start(src,SC_HIDING,100,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case NJ_KIRIKAGE: - if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground ) - { //You don't move on GVG grounds. - short x, y; - map_search_freecell(bl, 0, &x, &y, 1, 1, 0); - if (unit_movepos(src, x, y, 0, 0)) - clif_slide(src,src->x,src->y); - } - status_change_end(src, SC_HIDING, INVALID_TIMER); - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; - case RK_PHANTOMTHRUST: - unit_setdir(src,map_calc_dir(src, bl->x, bl->y)); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - - skill_blown(src,bl,distance_bl(src,bl)-1,unit_getdir(src),0); - if( battle_check_target(src,bl,BCT_ENEMY) ) - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; + break; - case RK_STORMBLAST: - case RK_CRUSHSTRIKE: - if( sd ) { - if( pc_checkskill(sd,RK_RUNEMASTERY) >= ( skill_id == RK_CRUSHSTRIKE ? 7 : 3 ) ) - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - else - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } else //non-sd support - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; - case GC_DARKILLUSION: - { - short x, y; - short dir = map_calc_dir(src,bl->x,bl->y); + case NPC_SELFDESTRUCTION: { + struct status_change *tsc = NULL; + if( (tsc = status_get_sc(bl)) && tsc->data[SC_HIDING] ) + break; + } + case HVAN_EXPLOSION: + if (src != bl) + skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); + break; - if( dir > 0 && dir < 4) x = 2; - else if( dir > 4 ) x = -2; - else x = 0; - if( dir > 2 && dir < 6 ) y = 2; - else if( dir == 7 || dir < 2 ) y = -2; - else y = 0; + // Celest + case PF_SOULBURN: + if (rnd()%100 < (skill_lv < 5 ? 30 + skill_lv * 10 : 70)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (skill_lv == 5) + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); + status_percent_damage(src, bl, 0, 100, false); + } else { + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + if (skill_lv == 5) + skill->attack(BF_MAGIC,src,src,src,skill_id,skill_lv,tick,flag); + status_percent_damage(src, src, 0, 100, false); + } + break; - if( unit_movepos(src, bl->x+x, bl->y+y, 1, 1) ) + case NPC_BLOODDRAIN: + case NPC_ENERGYDRAIN: { - clif_slide(src,bl->x+x,bl->y+y); - clif_fixpos(src); // the official server send these two packts. - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - if( rnd()%100 < 4 * skill_lv ) - skill_castend_damage_id(src,bl,GC_CROSSIMPACT,skill_lv,tick,flag); + int heal = skill->attack( (skill_id == NPC_BLOODDRAIN) ? BF_WEAPON : BF_MAGIC, + src, src, bl, skill_id, skill_lv, tick, flag); + if (heal > 0){ + clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1); + status_heal(src, heal, 0, 0); + } } + break; - } - break; - - case GC_WEAPONCRUSH: - if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING ) - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - else if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0); - break; - - case GC_CROSSRIPPERSLASHER: - if( sd && !(sc && sc->data[SC_ROLLINGCUTTER]) ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0); - else - { - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - status_change_end(src,SC_ROLLINGCUTTER,INVALID_TIMER); - } - break; - - case GC_PHANTOMMENACE: - if( flag&1 ) - { // Only Hits Invisible Targets - struct status_change *tsc = status_get_sc(bl); - if(tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY]) ) - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - } - break; - case WL_CHAINLIGHTNING: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_addtimerskill(src,tick + 150,bl->id,3,0,WL_CHAINLIGHTNING_ATK,skill_lv,4+skill_lv,flag); - break; - case WL_DRAINLIFE: - { - int heal = skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); - int rate = 70 + 5 * skill_lv; + case GS_BULLSEYE: + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; - heal = heal * (5 + 5 * skill_lv) / 100; + case NJ_KASUMIKIRI: + if (skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag) > 0) + sc_start(src,SC_HIDING,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case NJ_KIRIKAGE: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground ) + { //You don't move on GVG grounds. + short x, y; + map_search_freecell(bl, 0, &x, &y, 1, 1, 0); + if (unit_movepos(src, x, y, 0, 0)) + clif->slide(src,src->x,src->y); + } + status_change_end(src, SC_HIDING, INVALID_TIMER); + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; + case RK_PHANTOMTHRUST: + unit_setdir(src,map_calc_dir(src, bl->x, bl->y)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - if( bl->type == BL_SKILL ) - heal = 0; // Don't absorb heal from Ice Walls or other skill units. + skill->blown(src,bl,distance_bl(src,bl)-1,unit_getdir(src),0); + if( battle->check_target(src,bl,BCT_ENEMY) > 0 ) + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; - if( heal && rnd()%100 < rate ) + case RK_STORMBLAST: + case RK_CRUSHSTRIKE: + if( sd ) { + if( pc_checkskill(sd,RK_RUNEMASTERY) >= ( skill_id == RK_CRUSHSTRIKE ? 7 : 3 ) ) + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } else //non-sd support + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; + case GC_DARKILLUSION: { - status_heal(src, heal, 0, 0); - clif_skill_nodamage(NULL, src, AL_HEAL, heal, 1); - } - } - break; + short x, y; + short dir = map_calc_dir(src,bl->x,bl->y); - case WL_TETRAVORTEX: - if( sd ) - { - int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }, - i, j = 0, k, subskill = 0; + if( dir > 0 && dir < 4) x = 2; + else if( dir > 4 ) x = -2; + else x = 0; + if( dir > 2 && dir < 6 ) y = 2; + else if( dir == 7 || dir < 2 ) y = -2; + else y = 0; - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - if( sc && sc->data[i] ) + if( unit_movepos(src, bl->x+x, bl->y+y, 1, 1) ) { - spheres[j] = i; - positions[j] = sc->data[i]->val2; - j++; // + clif->slide(src,bl->x+x,bl->y+y); + clif->fixpos(src); // the official server send these two packts. + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + if( rnd()%100 < 4 * skill_lv ) + skill->castend_damage_id(src,bl,GC_CROSSIMPACT,skill_lv,tick,flag); } - if( j < 4 ) - { // Need 4 spheres minimum - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; } + break; - // Sphere Sort, this time from new to old - for( i = 0; i <= j - 2; i++ ) - for( k = i + 1; k <= j - 1; k++ ) - if( positions[i] < positions[k] ) - { - swap(positions[i],positions[k]); - swap(spheres[i],spheres[k]); - } + case GC_WEAPONCRUSH: + if( sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING ) + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + else if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0); + break; - k = 0; - for( i = 0; i < 4; i++ ) + case GC_CROSSRIPPERSLASHER: + if( sd && !(sc && sc->data[SC_ROLLINGCUTTER]) ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_CONDITION,0); + else { - switch( sc->data[spheres[i]]->val1 ) - { - case WLS_FIRE: subskill = WL_TETRAVORTEX_FIRE; k |= 1; break; - case WLS_WIND: subskill = WL_TETRAVORTEX_WIND; k |= 4; break; - case WLS_WATER: subskill = WL_TETRAVORTEX_WATER; k |= 2; break; - case WLS_STONE: subskill = WL_TETRAVORTEX_GROUND; k |= 8; break; - } - skill_addtimerskill(src, tick + i * 200, bl->id, k, 0, subskill, skill_lv, i, flag); - clif_skill_nodamage(src, bl, subskill, skill_lv, 1); - status_change_end(src, spheres[i], INVALID_TIMER); + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + status_change_end(src,SC_ROLLINGCUTTER,INVALID_TIMER); } - } - break; - - case WL_RELEASE: - if( sd ) - { - int i; - // Priority is to release SpellBook - if( sc && sc->data[SC_READING_SB] ) - { // SpellBook - uint16 skill_id, skill_lv, point, s = 0; - int spell[SC_MAXSPELLBOOK-SC_SPELLBOOK1 + 1]; - - for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) // List all available spell to be released - if( sc->data[i] ) spell[s++] = i; - - if ( s == 0 ) - break; + break; - i = spell[s==1?0:rand()%s];// Random select of spell to be released. - if( s && sc->data[i] ){// Now extract the data from the preserved spell - skill_id = sc->data[i]->val1; - skill_lv = sc->data[i]->val2; - point = sc->data[i]->val3; - status_change_end(src, (sc_type)i, INVALID_TIMER); - }else //something went wrong :( - break; + case GC_PHANTOMMENACE: + if( flag&1 ) + { // Only Hits Invisible Targets + struct status_change *tsc = status_get_sc(bl); + if(tsc && (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC__INVISIBILITY]) ) + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + } + break; + case WL_CHAINLIGHTNING: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->addtimerskill(src,tick + 150,bl->id,3,0,WL_CHAINLIGHTNING_ATK,skill_lv,4+skill_lv,flag); + break; + case WL_DRAINLIFE: + { + int heal = skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); + int rate = 70 + 5 * skill_lv; - if( sc->data[SC_READING_SB]->val2 > point ) - sc->data[SC_READING_SB]->val2 -= point; - else // Last spell to be released - status_change_end(src, SC_READING_SB, INVALID_TIMER); + heal = heal * (5 + 5 * skill_lv) / 100; - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - if( !skill_check_condition_castbegin(sd, skill_id, skill_lv) ) - break; + if( bl->type == BL_SKILL ) + heal = 0; // Don't absorb heal from Ice Walls or other skill units. - switch( skill_get_casttype(skill_id) ) + if( heal && rnd()%100 < rate ) { - case CAST_GROUND: - skill_castend_pos2(src, bl->x, bl->y, skill_id, skill_lv, tick, 0); - break; - case CAST_NODAMAGE: - skill_castend_nodamage_id(src, bl, skill_id, skill_lv, tick, 0); - break; - case CAST_DAMAGE: - skill_castend_damage_id(src, bl, skill_id, skill_lv, tick, 0); - break; + status_heal(src, heal, 0, 0); + clif->skill_nodamage(NULL, src, AL_HEAL, heal, 1); } - - sd->ud.canact_tick = tick + skill_delayfix(src, skill_id, skill_lv); - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, skill_id, skill_lv), 0, 0, 0); } - else - { // Summon Balls - int j = 0, k, skele; + break; + + case WL_TETRAVORTEX: + if( sd ) { int spheres[5] = { 0, 0, 0, 0, 0 }, - positions[5] = {-1,-1,-1,-1,-1 }; + positions[5] = {-1,-1,-1,-1,-1 }, + i, j = 0, k, subskill = 0; for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) if( sc && sc->data[i] ) { spheres[j] = i; positions[j] = sc->data[i]->val2; - sc->data[i]->val2--; // Prepares for next position - j++; + j++; // } - if( j == 0 ) - { // No Spheres - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0); + if( j < 4 ) + { // Need 4 spheres minimum + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } - // Sphere Sort + // Sphere Sort, this time from new to old for( i = 0; i <= j - 2; i++ ) for( k = i + 1; k <= j - 1; k++ ) - if( positions[i] > positions[k] ) + if( positions[i] < positions[k] ) { swap(positions[i],positions[k]); swap(spheres[i],spheres[k]); } - if( skill_lv == 1 ) j = 1; // Limit only to one ball - for( i = 0; i < j; i++ ) + k = 0; + for( i = 0; i < 4; i++ ) { - skele = WL_RELEASE - 5 + sc->data[spheres[i]]->val1 - WLS_FIRE; // Convert Ball Element into Skill ATK for balls - // WL_SUMMON_ATK_FIRE, WL_SUMMON_ATK_WIND, WL_SUMMON_ATK_WATER, WL_SUMMON_ATK_GROUND - skill_addtimerskill(src,tick+status_get_adelay(src)*i,bl->id,0,0,skele,sc->data[spheres[i]]->val3,BF_MAGIC,flag|SD_LEVEL); - status_change_end(src, spheres[i], INVALID_TIMER); // Eliminate ball + switch( sc->data[spheres[i]]->val1 ) + { + case WLS_FIRE: subskill = WL_TETRAVORTEX_FIRE; k |= 1; break; + case WLS_WIND: subskill = WL_TETRAVORTEX_WIND; k |= 4; break; + case WLS_WATER: subskill = WL_TETRAVORTEX_WATER; k |= 2; break; + case WLS_STONE: subskill = WL_TETRAVORTEX_GROUND; k |= 8; break; + } + skill->addtimerskill(src, tick + i * 200, bl->id, k, 0, subskill, skill_lv, i, flag); + clif->skill_nodamage(src, bl, subskill, skill_lv, 1); + status_change_end(src, spheres[i], INVALID_TIMER); } - clif_skill_nodamage(src,bl,skill_id,0,1); - } - } - break; - case WL_FROSTMISTY: - // Causes Freezing status through walls. - sc_start(bl,status_skill2sc(skill_id),20+12*skill_lv+(sd ? sd->status.job_level : 50)/5,skill_lv,skill_get_time(skill_id,skill_lv)); - // Doesn't deal damage through non-shootable walls. - if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL) ) - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); - break; - case WL_HELLINFERNO: - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|ELE_DARK); - break; - case RA_WUGSTRIKE: - if( sd && pc_isridingwug(sd) ){ - short x[8]={0,-1,-1,-1,0,1,1,1}; - short y[8]={1,1,0,-1,-1,-1,0,1}; - uint8 dir = map_calc_dir(bl, src->x, src->y); - - if( unit_movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) ) - { - clif_slide(src, bl->x+x[dir], bl->y+y[dir]); - clif_fixpos(src); - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); } break; - } - case RA_WUGBITE: - if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) { - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - }else if( sd && skill_id == RA_WUGBITE ) // Only RA_WUGBITE has the skill fail message. - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; + case WL_RELEASE: + if( sd ) { + int i; + // Priority is to release SpellBook + if( sc && sc->data[SC_READING_SB] ) { // SpellBook + uint16 skill_id, skill_lv, point, s = 0; + int spell[SC_MAXSPELLBOOK-SC_SPELLBOOK1 + 1]; - case RA_SENSITIVEKEEN: - if( bl->type != BL_SKILL ) { // Only Hits Invisible Targets - struct status_change * tsc = status_get_sc(bl); - if( tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK) ){ - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--) // List all available spell to be released + if( sc->data[i] ) spell[s++] = i; + + if ( s == 0 ) + break; + + i = spell[s==1?0:rand()%s];// Random select of spell to be released. + if( s && sc->data[i] ){// Now extract the data from the preserved spell + skill_id = sc->data[i]->val1; + skill_lv = sc->data[i]->val2; + point = sc->data[i]->val3; + status_change_end(src, (sc_type)i, INVALID_TIMER); + }else //something went wrong :( + break; + + if( sc->data[SC_READING_SB]->val2 > point ) + sc->data[SC_READING_SB]->val2 -= point; + else // Last spell to be released + status_change_end(src, SC_READING_SB, INVALID_TIMER); + if( bl->type != BL_SKILL ) /* skill types will crash the client */ + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + if( !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) + break; + + switch( skill->get_casttype(skill_id) ) { + case CAST_GROUND: + skill->castend_pos2(src, bl->x, bl->y, skill_id, skill_lv, tick, 0); + break; + case CAST_NODAMAGE: + skill->castend_nodamage_id(src, bl, skill_id, skill_lv, tick, 0); + break; + case CAST_DAMAGE: + skill->castend_damage_id(src, bl, skill_id, skill_lv, tick, 0); + break; + } + + sd->ud.canact_tick = tick + skill->delay_fix(src, skill_id, skill_lv); + clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, skill_id, skill_lv), 0, 0, 0); + } else { // Summon Balls + int j = 0, k, skele; + int spheres[5] = { 0, 0, 0, 0, 0 }, + positions[5] = {-1,-1,-1,-1,-1 }; + + for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) + if( sc && sc->data[i] ) { + spheres[j] = i; + positions[j] = sc->data[i]->val2; + sc->data[i]->val2--; // Prepares for next position + j++; + } + + if( j == 0 ) { // No Spheres + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON_NONE,0); + break; + } + + // Sphere Sort + for( i = 0; i <= j - 2; i++ ) + for( k = i + 1; k <= j - 1; k++ ) + if( positions[i] > positions[k] ) { + swap(positions[i],positions[k]); + swap(spheres[i],spheres[k]); + } + + if( skill_lv == 1 ) j = 1; // Limit only to one ball + for( i = 0; i < j; i++ ) { + skele = WL_RELEASE - 5 + sc->data[spheres[i]]->val1 - WLS_FIRE; // Convert Ball Element into Skill ATK for balls + // WL_SUMMON_ATK_FIRE, WL_SUMMON_ATK_WIND, WL_SUMMON_ATK_WATER, WL_SUMMON_ATK_GROUND + skill->addtimerskill(src,tick+status_get_adelay(src)*i,bl->id,0,0,skele,sc->data[spheres[i]]->val3,BF_MAGIC,flag|SD_LEVEL); + status_change_end(src, spheres[i], INVALID_TIMER); // Eliminate ball + } + clif->skill_nodamage(src,bl,skill_id,0,1); + } } - } - else - { - struct skill_unit *su = BL_CAST(BL_SKILL,bl); - struct skill_unit_group* sg; + break; + case WL_FROSTMISTY: + // Causes Freezing status through walls. + sc_start(bl,status_skill2sc(skill_id),20+12*skill_lv+(sd ? sd->status.job_level : 50)/5,skill_lv,skill->get_time(skill_id,skill_lv)); + // Doesn't deal damage through non-shootable walls. + if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKWALL) ) + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); + break; + case WL_HELLINFERNO: + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag|ELE_DARK); + break; + case RA_WUGSTRIKE: + if( sd && pc_isridingwug(sd) ){ + short x[8]={0,-1,-1,-1,0,1,1,1}; + short y[8]={1,1,0,-1,-1,-1,0,1}; + uint8 dir = map_calc_dir(bl, src->x, src->y); - if( su && (sg=su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP ) - { - if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) + if( unit_movepos(src, bl->x+x[dir], bl->y+y[dir], 1, 1) ) { - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP; - item_tmp.identify = 1; - if( item_tmp.nameid ) - map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0); + clif->slide(src, bl->x+x[dir], bl->y+y[dir]); + clif->fixpos(src); + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); } - skill_delunit(su); + break; } - } - break; - case NC_INFRAREDSCAN: - if( flag&1 ) - { //TODO: Need a confirmation if the other type of hidden status is included to be scanned. [Jobbie] - if( rnd()%100 < 50 ) - sc_start(bl, SC_INFRAREDSCAN, 10000, skill_lv, skill_get_time(skill_id, skill_lv)); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it. - } - else - { - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( sd ) pc_overheat(sd,1); - } - break; - - case NC_MAGNETICFIELD: - sc_start2(bl,SC_MAGNETICFIELD,100,skill_lv,src->id,skill_get_time(skill_id,skill_lv)); - break; - case SC_FATALMENACE: - if( flag&1 ) - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - else - { - short x, y; - map_search_freecell(src, 0, &x, &y, -1, -1, 0); - // Destination area - skill_area_temp[4] = x; - skill_area_temp[5] = y; - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - skill_addtimerskill(src,tick + 800,src->id,x,y,skill_id,skill_lv,0,flag); // To teleport Self - clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); - } - break; - case LG_PINPOINTATTACK: - if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) ) - clif_slide(src,bl->x,bl->y); - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; + case RA_WUGBITE: + if( path_search(NULL,src->m,src->x,src->y,bl->x,bl->y,1,CELL_CHKNOREACH) ) { + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + }else if( sd && skill_id == RA_WUGBITE ) // Only RA_WUGBITE has the skill fail message. + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - case LG_SHIELDSPELL: - // flag&1: Phisycal Attack, flag&2: Magic Attack. - skill_attack((flag&1)?BF_WEAPON:BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - break; - - case LG_OVERBRAND: - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_LEVEL); - break; + break; - case LG_OVERBRAND_BRANDISH: - skill_addtimerskill(src, tick + status_get_amotion(src)*8/10, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|SD_LEVEL); - break; - case SR_DRAGONCOMBO: - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - break; + case RA_SENSITIVEKEEN: + if( bl->type != BL_SKILL ) { // Only Hits Invisible Targets + struct status_change * tsc = status_get_sc(bl); + if( tsc && tsc->option&(OPTION_HIDE|OPTION_CLOAK) ){ + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + } + } + else + { + struct skill_unit *su = BL_CAST(BL_SKILL,bl); + struct skill_unit_group* sg; - case SR_KNUCKLEARROW: - if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) ) { - clif_slide(src,bl->x,bl->y); - clif_fixpos(src); // Aegis send this packet too. + if( su && (sg=su->group) && skill->get_inf2(sg->skill_id)&INF2_TRAP ) + { + if( !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) + { + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = sg->item_id?sg->item_id:ITEMID_TRAP; + item_tmp.identify = 1; + if( item_tmp.nameid ) + map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0); + } + skill->delunit(su); + } + } + break; + case NC_INFRAREDSCAN: + if( flag&1 ) + { //TODO: Need a confirmation if the other type of hidden status is included to be scanned. [Jobbie] + if( rnd()%100 < 50 ) + sc_start(bl, SC_INFRAREDSCAN, 10000, skill_lv, skill->get_time(skill_id, skill_lv)); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); // Need confirm it. } + else + { + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( sd ) pc_overheat(sd,1); + } + break; + case NC_MAGNETICFIELD: + sc_start2(bl,SC_MAGNETICFIELD,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)); + break; + case SC_FATALMENACE: if( flag&1 ) - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_LEVEL); + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); else - skill_addtimerskill(src, tick + 300, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|SD_LEVEL|2); - break; + { + short x, y; + map_search_freecell(src, 0, &x, &y, -1, -1, 0); + // Destination area + skill_area_temp[4] = x; + skill_area_temp[5] = y; + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id); + skill->addtimerskill(src,tick + 800,src->id,x,y,skill_id,skill_lv,0,flag); // To teleport Self + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + } + break; + case LG_PINPOINTATTACK: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) ) + clif->slide(src,bl->x,bl->y); + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; - case SR_HOWLINGOFLION: - status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); - status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); - status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); - status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); - status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); - status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); - status_change_end(bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); - status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); - status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); - status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); - status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); - status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION); - break; + case LG_SHIELDSPELL: + // flag&1: Phisycal Attack, flag&2: Magic Attack. + skill->attack((flag&1)?BF_WEAPON:BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); + break; - case SR_EARTHSHAKER: - if( flag&1 ) { //by default cloaking skills are remove by aoe skills so no more checking/removing except hiding and cloaking exceed. - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - } else{ - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - } - break; + case LG_OVERBRAND: + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_LEVEL); + break; - case SO_POISON_BUSTER: { - struct status_change *tsc = status_get_sc(bl); - if( tsc && tsc->data[SC_POISON] ) { - skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); - status_change_end(bl, SC_POISON, INVALID_TIMER); - } - else if( sd ) - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - } - break; + case LG_OVERBRAND_BRANDISH: + skill->addtimerskill(src, tick + status_get_amotion(src)*8/10, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|SD_LEVEL); + break; + case SR_DRAGONCOMBO: + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + break; - case GN_SPORE_EXPLOSION: - if( flag&1 ) - skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); - else { - clif_skill_nodamage(src, bl, skill_id, 0, 1); - skill_addtimerskill(src, gettick() + skill_get_time(skill_id, skill_lv) - 1000, bl->id, 0, 0, skill_id, skill_lv, 0, 0); - } - break; + case SR_KNUCKLEARROW: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground && unit_movepos(src, bl->x, bl->y, 1, 1) ) { + clif->slide(src,bl->x,bl->y); + clif->fixpos(src); // Aegis send this packet too. + } - case EL_FIRE_BOMB: - case EL_FIRE_WAVE: - case EL_WATER_SCREW: - case EL_HURRICANE: - case EL_TYPOON_MIS: - if( flag&1 ) - skill_attack(skill_get_type(skill_id+1),src,src,bl,skill_id+1,skill_lv,tick,flag); - else { - int i = skill_get_splash(skill_id,skill_lv); - clif_skill_nodamage(src,battle_get_master(src),skill_id,skill_lv,1); - clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rnd()%100 < 30 ) - map_foreachinrange(skill_area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - else - skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); - } - break; + if( flag&1 ) + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_LEVEL); + else + skill->addtimerskill(src, tick + 300, bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag|SD_LEVEL|2); + break; - case EL_ROCK_CRUSHER: - clif_skill_nodamage(src,battle_get_master(src),skill_id,skill_lv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rnd()%100 < 50 ) - skill_attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); - else - skill_attack(BF_WEAPON,src,src,bl,EL_ROCK_CRUSHER_ATK,skill_lv,tick,flag); - break; + case SR_HOWLINGOFLION: + status_change_end(bl, SC_SWINGDANCE, INVALID_TIMER); + status_change_end(bl, SC_SYMPHONYOFLOVER, INVALID_TIMER); + status_change_end(bl, SC_MOONLITSERENADE, INVALID_TIMER); + status_change_end(bl, SC_RUSHWINDMILL, INVALID_TIMER); + status_change_end(bl, SC_ECHOSONG, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + status_change_end(bl, SC_SIRCLEOFNATURE, INVALID_TIMER); + status_change_end(bl, SC_SATURDAYNIGHTFEVER, INVALID_TIMER); + status_change_end(bl, SC_DANCEWITHWUG, INVALID_TIMER); + status_change_end(bl, SC_LERADSDEW, INVALID_TIMER); + status_change_end(bl, SC_MELODYOFSINK, INVALID_TIMER); + status_change_end(bl, SC_BEYONDOFWARCRY, INVALID_TIMER); + status_change_end(bl, SC_UNLIMITEDHUMMINGVOICE, INVALID_TIMER); + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag|SD_ANIMATION); + break; - case EL_STONE_RAIN: - if( flag&1 ) - skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); - else { - int i = skill_get_splash(skill_id,skill_lv); - clif_skill_nodamage(src,battle_get_master(src),skill_id,skill_lv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rnd()%100 < 30 ) - map_foreachinrange(skill_area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - else - skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); - } - break; + case SR_EARTHSHAKER: + if( flag&1 ) { //by default cloaking skills are remove by aoe skills so no more checking/removing except hiding and cloaking exceed. + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + } else{ + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + } + break; - case EL_FIRE_ARROW: - case EL_ICE_NEEDLE: - case EL_WIND_SLASH: - case EL_STONE_HAMMER: - clif_skill_nodamage(src,battle_get_master(src),skill_id,skill_lv,1); - clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); - break; + case SO_POISON_BUSTER: { + struct status_change *tsc = status_get_sc(bl); + if( tsc && tsc->data[SC_POISON] ) { + skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); + status_change_end(bl, SC_POISON, INVALID_TIMER); + } + else if( sd ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + } + break; - case EL_TIDAL_WEAPON: - if( src->type == BL_ELEM ) { - struct elemental_data *ele = BL_CAST(BL_ELEM,src); - struct status_change *sc = status_get_sc(&ele->bl); - struct status_change *tsc = status_get_sc(bl); - sc_type type = status_skill2sc(skill_id), type2; - type2 = type-1; + case GN_SPORE_EXPLOSION: + if( flag&1 ) + skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); + else { + clif->skill_nodamage(src, bl, skill_id, 0, 1); + skill->addtimerskill(src, gettick() + skill->get_time(skill_id, skill_lv) - 1000, bl->id, 0, 0, skill_id, skill_lv, 0, 0); + } + break; - clif_skill_nodamage(src,battle_get_master(src),skill_id,skill_lv,1); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); + case EL_FIRE_BOMB: + case EL_FIRE_WAVE: + case EL_WATER_SCREW: + case EL_HURRICANE: + case EL_TYPOON_MIS: + if( flag&1 ) + skill->attack(skill->get_type(skill_id+1),src,src,bl,skill_id+1,skill_lv,tick,flag); + else { + int i = skill->get_splash(skill_id,skill_lv); + clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( rnd()%100 < 30 ) + map_foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + else + skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); } + break; + + case EL_ROCK_CRUSHER: + clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); if( rnd()%100 < 50 ) - skill_attack(skill_get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); + skill->attack(BF_MAGIC,src,src,bl,skill_id,skill_lv,tick,flag); + else + skill->attack(BF_WEAPON,src,src,bl,EL_ROCK_CRUSHER_ATK,skill_lv,tick,flag); + break; + + case EL_STONE_RAIN: + if( flag&1 ) + skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); else { - sc_start(src,type2,100,skill_lv,skill_get_time(skill_id,skill_lv)); - sc_start(battle_get_master(src),type,100,ele->bl.id,skill_get_time(skill_id,skill_lv)); + int i = skill->get_splash(skill_id,skill_lv); + clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( rnd()%100 < 30 ) + map_foreachinrange(skill->area_sub,bl,i,BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + else + skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); } - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - } - break; + break; + case EL_FIRE_ARROW: + case EL_ICE_NEEDLE: + case EL_WIND_SLASH: + case EL_STONE_HAMMER: + clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); + break; - //recursive homon skill - case MH_MAGMA_FLOW: - case MH_XENO_SLASHER: - case MH_HEILIGE_STANGE: - if(flag & 1) - skill_attack(skill_get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); - else { - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill_castend_damage_id); - } - break; + case EL_TIDAL_WEAPON: + if( src->type == BL_ELEM ) { + struct elemental_data *ele = BL_CAST(BL_ELEM,src); + struct status_change *sc = status_get_sc(&ele->bl); + struct status_change *tsc = status_get_sc(bl); + sc_type type = status_skill2sc(skill_id), type2; + type2 = type-1; - case MH_STAHL_HORN: - case MH_NEEDLE_OF_PARALYZE: - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); - break; - case MH_TINDER_BREAKER: - if (unit_movepos(src, bl->x, bl->y, 1, 1)) { -#if PACKETVER >= 20111005 - clif_snap(src, bl->x, bl->y); -#else - clif_skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick); -#endif - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,SC_CLOSECONFINE2,100,skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv))); - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); - break; + clif->skill_nodamage(src,battle->get_master(src),skill_id,skill_lv,1); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skill_id); + } + if( rnd()%100 < 50 ) + skill->attack(skill->get_type(skill_id),src,src,bl,skill_id,skill_lv,tick,flag); + else { + sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(battle->get_master(src),type,100,ele->bl.id,skill->get_time(skill_id,skill_lv)); + } + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + } + break; - case 0:/* no skill - basic/normal attack */ - if(sd) { - if (flag & 3){ - if (bl->id != skill_area_temp[1]) - skill_attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, SD_LEVEL|flag); - } else { - skill_area_temp[1] = bl->id; - map_foreachinrange(skill_area_sub, bl, - sd->bonus.splash_range, BL_CHAR, - src, skill_id, skill_lv, tick, flag | BCT_ENEMY | 1, - skill_castend_damage_id); - flag|=1; //Set flag to 1 so ammo is not double-consumed. [Skotlex] + + //recursive homon skill + case MH_MAGMA_FLOW: + case MH_XENO_SLASHER: + case MH_HEILIGE_STANGE: + if(flag & 1) + skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); + else { + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag | BCT_ENEMY | SD_SPLASH | 1, skill->castend_damage_id); } - } - break; + break; - default: - ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skill_id); - clif_skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion, - 0, abs(skill_get_num(skill_id, skill_lv)), - skill_id, skill_lv, skill_get_hit(skill_id)); - map_freeblock_unlock(); - return 1; + case MH_STAHL_HORN: + case MH_NEEDLE_OF_PARALYZE: + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); + break; + case MH_TINDER_BREAKER: + if (unit_movepos(src, bl->x, bl->y, 1, 1)) { + #if PACKETVER >= 20111005 + clif->snap(src, bl->x, bl->y); + #else + clif->skill_poseffect(src,skill_id,skill_lv,bl->x,bl->y,tick); + #endif + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,SC_CLOSECONFINE2,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag); + break; + + case 0:/* no skill - basic/normal attack */ + if(sd) { + if (flag & 3){ + if (bl->id != skill_area_temp[1]) + skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, SD_LEVEL|flag); + } else { + skill_area_temp[1] = bl->id; + map_foreachinrange(skill->area_sub, bl, + sd->bonus.splash_range, BL_CHAR, + src, skill_id, skill_lv, tick, flag | BCT_ENEMY | 1, + skill->castend_damage_id); + flag|=1; //Set flag to 1 so ammo is not double-consumed. [Skotlex] + } + } + break; + + default: + ShowWarning("skill_castend_damage_id: Unknown skill used:%d\n",skill_id); + clif->skill_damage(src, bl, tick, status_get_amotion(src), tstatus->dmotion, + 0, abs(skill->get_num(skill_id, skill_lv)), + skill_id, skill_lv, skill->get_hit(skill_id)); + map_freeblock_unlock(); + return 1; } if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] ) //Should only remove after the skill has been casted. @@ -4654,11 +4629,11 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, uint if( sd->state.arrow_atk ) {// consume arrow on last invocation to this skill. - battle_consume_ammo(sd, skill_id, skill_lv); + battle->consume_ammo(sd, skill_id, skill_lv); } // perform skill requirement consumption - skill_consume_requirement(sd,skill_id,skill_lv,2); + skill->consume_requirement(sd,skill_id,skill_lv,2); } return 0; @@ -4723,7 +4698,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui switch (skill_id) { case HLIF_HEAL: //[orn] if (bl->type != BL_HOM) { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ; + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ; break ; } case AL_HEAL: @@ -4735,33 +4710,33 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui case AB_RENOVATIO: case AB_HIGHNESSHEAL: //Apparently only player casted skills can be offensive like this. - if (sd && battle_check_undead(tstatus->race,tstatus->def_ele)) { - if (battle_check_target(src, bl, BCT_ENEMY) < 1) { + if (sd && battle->check_undead(tstatus->race,tstatus->def_ele)) { + if (battle->check_target(src, bl, BCT_ENEMY) < 1) { //Offensive heal does not works on non-enemies. [Skotlex] - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } - return skill_castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); + return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); } break; case NPC_SMOKING: //Since it is a self skill, this one ends here rather than in damage_id. [Skotlex] - return skill_castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); + return skill->castend_damage_id (src, bl, skill_id, skill_lv, tick, flag); case MH_STEINWAND: { - struct block_list *s_src = battle_get_master(src); + struct block_list *s_src = battle->get_master(src); short ret = 0; - if(!skill_check_unit_range(src, src->x, src->y, skill_id, skill_lv)) //prevent reiteration - ret = skill_castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homon - if(s_src && !skill_check_unit_range(s_src, s_src->x, s_src->y, skill_id, skill_lv)) - ret |= skill_castend_pos2(s_src,s_src->x,s_src->y,skill_id,skill_lv,tick,flag); //cast on master + if(!skill->check_unit_range(src, src->x, src->y, skill_id, skill_lv)) //prevent reiteration + ret = skill->castend_pos2(src,src->x,src->y,skill_id,skill_lv,tick,flag); //cast on homon + if(s_src && !skill->check_unit_range(s_src, s_src->x, s_src->y, skill_id, skill_lv)) + ret |= skill->castend_pos2(s_src,s_src->x,s_src->y,skill_id,skill_lv,tick,flag); //cast on master if (hd) - skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv)); + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); return ret; } break; default: //Skill is actually ground placed. - if (src == bl && skill_get_unit_id(skill_id,0)) - return skill_castend_pos2(src,bl->x,bl->y,skill_id,skill_lv,tick,0); + if (src == bl && skill->get_unit_id(skill_id,0)) + return skill->castend_pos2(src,bl->x,bl->y,skill_id,skill_lv,tick,0); } type = status_skill2sc(skill_id); @@ -4769,4286 +4744,4294 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui tsce = (tsc && type != -1)?tsc->data[type]:NULL; if (src!=bl && type > -1 && - (i = skill_get_ele(skill_id, skill_lv)) > ELE_NEUTRAL && - skill_get_inf(skill_id) != INF_SUPPORT_SKILL && - battle_attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0) + (i = skill->get_ele(skill_id, skill_lv)) > ELE_NEUTRAL && + skill->get_inf(skill_id) != INF_SUPPORT_SKILL && + battle->attr_fix(NULL, NULL, 100, i, tstatus->def_ele, tstatus->ele_lv) <= 0) return 1; //Skills that cause an status should be blocked if the target element blocks its element. map_freeblock_lock(); - switch(skill_id) - { - case HLIF_HEAL: //[orn] - case AL_HEAL: - /** - * Arch Bishop - **/ - case AB_HIGHNESSHEAL: - { - int heal = skill_calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true); - int heal_get_jobexp; - //Highness Heal: starts at 1.5 boost + 0.5 for each level - if( skill_id == AB_HIGHNESSHEAL ) { - heal = heal * ( 15 + 5 * skill_lv ) / 10; - } - if( status_isimmune(bl) || - (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) || - (dstsd && pc_ismadogear(dstsd)) )//Mado is immune to heal - heal=0; + switch(skill_id) { + case HLIF_HEAL: //[orn] + case AL_HEAL: + /** + * Arch Bishop + **/ + case AB_HIGHNESSHEAL: + { + int heal = skill->calc_heal(src, bl, (skill_id == AB_HIGHNESSHEAL)?AL_HEAL:skill_id, (skill_id == AB_HIGHNESSHEAL)?10:skill_lv, true); + int heal_get_jobexp; + //Highness Heal: starts at 1.5 boost + 0.5 for each level + if( skill_id == AB_HIGHNESSHEAL ) { + heal = heal * ( 15 + 5 * skill_lv ) / 10; + } + if( status_isimmune(bl) || + (dstmd && (dstmd->class_ == MOBID_EMPERIUM || mob_is_battleground(dstmd))) || + (dstsd && pc_ismadogear(dstsd)) )//Mado is immune to heal + heal=0; - if( sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 ) - heal = heal*2; + if( sd && dstsd && sd->status.partner_id == dstsd->status.char_id && (sd->class_&MAPID_UPPERMASK) == MAPID_SUPER_NOVICE && sd->status.sex == 0 ) + heal = heal*2; - if( tsc && tsc->count ) - { - if( tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) ) - { //Bounce back heal - if (--tsc->data[SC_KAITE]->val2 <= 0) - status_change_end(bl, SC_KAITE, INVALID_TIMER); - if (src == bl) - heal=0; //When you try to heal yourself under Kaite, the heal is voided. - else { - bl = src; - dstsd = sd; + if( tsc && tsc->count ) + { + if( tsc->data[SC_KAITE] && !(sstatus->mode&MD_BOSS) ) + { //Bounce back heal + if (--tsc->data[SC_KAITE]->val2 <= 0) + status_change_end(bl, SC_KAITE, INVALID_TIMER); + if (src == bl) + heal=0; //When you try to heal yourself under Kaite, the heal is voided. + else { + bl = src; + dstsd = sd; + } } + else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC__BLOODYLUST]) + heal = 0; //Needed so that it actually displays 0 when healing. } - else if (tsc->data[SC_BERSERK] || tsc->data[SC_SATURDAYNIGHTFEVER] || tsc->data[SC__BLOODYLUST]) - heal = 0; //Needed so that it actually displays 0 when healing. - } - clif_skill_nodamage (src, bl, skill_id, heal, 1); - if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL ) - heal = ~heal + 1; - heal_get_jobexp = status_heal(bl,heal,0,0); - - if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){ - heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100; - if (heal_get_jobexp <= 0) - heal_get_jobexp = 1; - pc_gainexp (sd, bl, 0, heal_get_jobexp, false); - } - } - break; + clif->skill_nodamage (src, bl, skill_id, heal, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && heal && skill_id != HLIF_HEAL ) + heal = ~heal + 1; + heal_get_jobexp = status_heal(bl,heal,0,0); - case PR_REDEMPTIO: - if (sd && !(flag&1)) { - if (sd->status.party_id == 0) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - skill_area_temp[0] = 0; - party_foreachsamemap(skill_area_sub, - sd,skill_get_splash(skill_id, skill_lv), - src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, - skill_castend_nodamage_id); - if (skill_area_temp[0] == 0) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty... - if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty - sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each. - sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * skill_area_temp[0] * 2/1000); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_JOBEXP); + if(sd && dstsd && heal > 0 && sd != dstsd && battle_config.heal_exp > 0){ + heal_get_jobexp = heal_get_jobexp * battle_config.heal_exp / 100; + if (heal_get_jobexp <= 0) + heal_get_jobexp = 1; + pc_gainexp (sd, bl, 0, heal_get_jobexp, false); + } } - status_set_hp(src, 1, 0); - status_set_sp(src, 0, 0); - break; - } else if (status_isdead(bl) && flag&1) { //Revive - skill_area_temp[0]++; //Count it in, then fall-through to the Resurrection code. - skill_lv = 3; //Resurrection level 3 is used - } else //Invalid target, skip resurrection. break; - case ALL_RESURRECTION: - if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)) - { //No reviving in WoE grounds! - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - if (!status_isdead(bl)) - break; - { - int per = 0, sper = 0; - if (tsc && tsc->data[SC_HELLPOWER]) + case PR_REDEMPTIO: + if (sd && !(flag&1)) { + if (sd->status.party_id == 0) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + skill_area_temp[0] = 0; + party_foreachsamemap(skill->area_sub, + sd,skill->get_splash(skill_id, skill_lv), + src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, + skill->castend_nodamage_id); + if (skill_area_temp[0] == 0) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + skill_area_temp[0] = 5 - skill_area_temp[0]; // The actual penalty... + if (skill_area_temp[0] > 0 && !map[src->m].flag.noexppenalty) { //Apply penalty + sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * skill_area_temp[0] * 2/1000); //0.2% penalty per each. + sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * skill_area_temp[0] * 2/1000); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_JOBEXP); + } + status_set_hp(src, 1, 0); + status_set_sp(src, 0, 0); break; - - if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0) + } else if (status_isdead(bl) && flag&1) { //Revive + skill_area_temp[0]++; //Count it in, then fall-through to the Resurrection code. + skill_lv = 3; //Resurrection level 3 is used + } else //Invalid target, skip resurrection. break; - switch(skill_lv){ - case 1: per=10; break; - case 2: per=30; break; - case 3: per=50; break; - case 4: per=80; break; + case ALL_RESURRECTION: + if(sd && (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)) + { //No reviving in WoE grounds! + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } - if(dstsd && dstsd->special_state.restart_full_recover) - per = sper = 100; - if (status_revive(bl, per, sper)) + if (!status_isdead(bl)) + break; { - clif_skill_nodamage(src,bl,ALL_RESURRECTION,skill_lv,1); //Both Redemptio and Res show this skill-animation. - if(sd && dstsd && battle_config.resurrection_exp > 0) + int per = 0, sper = 0; + if (tsc && tsc->data[SC_HELLPOWER]) + break; + + if (map[bl->m].flag.pvp && dstsd && dstsd->pvp_point < 0) + break; + + switch(skill_lv){ + case 1: per=10; break; + case 2: per=30; break; + case 3: per=50; break; + case 4: per=80; break; + } + if(dstsd && dstsd->special_state.restart_full_recover) + per = sper = 100; + if (status_revive(bl, per, sper)) { - int exp = 0,jexp = 0; - int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; - if(lv > 0 && pc_nextbaseexp(dstsd)) { - exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); - if (exp < 1) exp = 1; - } - if(jlv > 0 && pc_nextjobexp(dstsd)) { - jexp = (int)((double)dstsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); - if (jexp < 1) jexp = 1; + clif->skill_nodamage(src,bl,ALL_RESURRECTION,skill_lv,1); //Both Redemptio and Res show this skill-animation. + if(sd && dstsd && battle_config.resurrection_exp > 0) + { + int exp = 0,jexp = 0; + int lv = dstsd->status.base_level - sd->status.base_level, jlv = dstsd->status.job_level - sd->status.job_level; + if(lv > 0 && pc_nextbaseexp(dstsd)) { + exp = (int)((double)dstsd->status.base_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + if (exp < 1) exp = 1; + } + if(jlv > 0 && pc_nextjobexp(dstsd)) { + jexp = (int)((double)dstsd->status.job_exp * (double)lv * (double)battle_config.resurrection_exp / 1000000.); + if (jexp < 1) jexp = 1; + } + if(exp > 0 || jexp > 0) + pc_gainexp (sd, bl, exp, jexp, false); } - if(exp > 0 || jexp > 0) - pc_gainexp (sd, bl, exp, jexp, false); } } - } - break; + break; - case AL_DECAGI: - case MER_DECAGI: - clif_skill_nodamage (src, bl, skill_id, skill_lv, - sc_start(bl, type, (40 + skill_lv * 2 + (status_get_lv(src) + sstatus->int_)/5), skill_lv, skill_get_time(skill_id,skill_lv))); - break; + case AL_DECAGI: + case MER_DECAGI: + clif->skill_nodamage (src, bl, skill_id, skill_lv, + sc_start(bl, type, (40 + skill_lv * 2 + (status_get_lv(src) + sstatus->int_)/5), skill_lv, skill->get_time(skill_id,skill_lv))); + break; - case AL_CRUCIS: - if (flag&1) - sc_start(bl,type, 23+skill_lv*4 +status_get_lv(src) -status_get_lv(bl), skill_lv,skill_get_time(skill_id,skill_lv)); - else { - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - } - break; + case AL_CRUCIS: + if (flag&1) + sc_start(bl,type, 23+skill_lv*4 +status_get_lv(src) -status_get_lv(bl), skill_lv,skill->get_time(skill_id,skill_lv)); + else { + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + } + break; - case PR_LEXDIVINA: - case MER_LEXDIVINA: - if( tsce ) - status_change_end(bl,type, INVALID_TIMER); - else - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage (src, bl, skill_id, skill_lv, 1); - break; + case PR_LEXDIVINA: + case MER_LEXDIVINA: + if( tsce ) + status_change_end(bl,type, INVALID_TIMER); + else + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + break; - case SA_ABRACADABRA: - { - int abra_skill_id = 0, abra_skill_lv; - do { - i = rnd() % MAX_SKILL_ABRA_DB; - abra_skill_id = skill_abra_db[i].skill_id; - } while (abra_skill_id == 0 || - skill_abra_db[i].req_lv > skill_lv || //Required lv for it to appear - rnd()%10000 >= skill_abra_db[i].per - ); - abra_skill_lv = min(skill_lv, skill_get_max(abra_skill_id)); - clif_skill_nodamage (src, bl, skill_id, skill_lv, 1); + case SA_ABRACADABRA: + { + int abra_skill_id = 0, abra_skill_lv; + do { + i = rnd() % MAX_SKILL_ABRA_DB; + abra_skill_id = skill_abra_db[i].skill_id; + } while (abra_skill_id == 0 || + skill_abra_db[i].req_lv > skill_lv || //Required lv for it to appear + rnd()%10000 >= skill_abra_db[i].per + ); + abra_skill_lv = min(skill_lv, skill->get_max(abra_skill_id)); + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); - if( sd ) - {// player-casted - sd->state.abra_flag = 1; - sd->skillitem = abra_skill_id; - sd->skillitemlv = abra_skill_lv; - clif_item_skill(sd, abra_skill_id, abra_skill_lv); - } - else - {// mob-casted - struct unit_data *ud = unit_bl2ud(src); - int inf = skill_get_inf(abra_skill_id); - int target_id = 0; - if (!ud) break; - if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { - if (src->type == BL_PET) - bl = (struct block_list*)((TBL_PET*)src)->msd; - if (!bl) bl = src; - unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv); - } else { //Assume offensive skills - if (ud->target) - target_id = ud->target; - else switch (src->type) { - case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; - case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; - } - if (!target_id) - break; - if (skill_get_casttype(abra_skill_id) == CAST_GROUND) { - bl = map_id2bl(target_id); + if( sd ) + {// player-casted + sd->state.abra_flag = 1; + sd->skillitem = abra_skill_id; + sd->skillitemlv = abra_skill_lv; + clif->item_skill(sd, abra_skill_id, abra_skill_lv); + } + else + {// mob-casted + struct unit_data *ud = unit_bl2ud(src); + int inf = skill->get_inf(abra_skill_id); + if (!ud) break; + if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { + if (src->type == BL_PET) + bl = (struct block_list*)((TBL_PET*)src)->msd; if (!bl) bl = src; - unit_skilluse_pos(src, bl->x, bl->y, abra_skill_id, abra_skill_lv); - } else - unit_skilluse_id(src, target_id, abra_skill_id, abra_skill_lv); + unit_skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv); + } else { //Assume offensive skills + int target_id = 0; + if (ud->target) + target_id = ud->target; + else switch (src->type) { + case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; + case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + } + if (!target_id) + break; + if (skill->get_casttype(abra_skill_id) == CAST_GROUND) { + bl = map_id2bl(target_id); + if (!bl) bl = src; + unit_skilluse_pos(src, bl->x, bl->y, abra_skill_id, abra_skill_lv); + } else + unit_skilluse_id(src, target_id, abra_skill_id, abra_skill_lv); + } } } - } - break; + break; - case SA_COMA: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time2(skill_id,skill_lv))); - break; - case SA_FULLRECOVERY: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if (status_isimmune(bl)) + case SA_COMA: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time2(skill_id,skill_lv))); break; - status_percent_heal(bl, 100, 100); - break; - case NPC_ALLHEAL: - { - int heal; - if( status_isimmune(bl) ) + case SA_FULLRECOVERY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (status_isimmune(bl)) break; - heal = status_percent_heal(bl, 100, 0); - clif_skill_nodamage(NULL, bl, AL_HEAL, heal, 1); - if( dstmd ) - { // Reset Damage Logs - memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog)); - dstmd->tdmg = 0; + status_percent_heal(bl, 100, 100); + break; + case NPC_ALLHEAL: + { + int heal; + if( status_isimmune(bl) ) + break; + heal = status_percent_heal(bl, 100, 0); + clif->skill_nodamage(NULL, bl, AL_HEAL, heal, 1); + if( dstmd ) + { // Reset Damage Logs + memset(dstmd->dmglog, 0, sizeof(dstmd->dmglog)); + dstmd->tdmg = 0; + } } - } - break; - case SA_SUMMONMONSTER: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if (sd) mob_once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE); - break; - case SA_LEVELUP: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd, NULL, pc_nextbaseexp(sd) * 10 / 100, 0, false); - break; - case SA_INSTANTDEATH: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - status_set_hp(bl,1,0); - break; - case SA_QUESTION: - case SA_GRAVITY: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case SA_CLASSCHANGE: - case SA_MONOCELL: - if (dstmd) - { - int class_; - if ( sd && dstmd->status.mode&MD_BOSS ) + break; + case SA_SUMMONMONSTER: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (sd) mob_once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE); + break; + case SA_LEVELUP: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (sd && pc_nextbaseexp(sd)) pc_gainexp(sd, NULL, pc_nextbaseexp(sd) * 10 / 100, 0, false); + break; + case SA_INSTANTDEATH: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_set_hp(bl,1,0); + break; + case SA_QUESTION: + case SA_GRAVITY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case SA_CLASSCHANGE: + case SA_MONOCELL: + if (dstmd) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + int class_; + if ( sd && dstmd->status.mode&MD_BOSS ) + { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + class_ = skill_id==SA_MONOCELL?1002:mob_get_random_id(4, 1, 0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + mob_class_change(dstmd,class_); + if( tsc && dstmd->status.mode&MD_BOSS ) + { + const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_SUITON, SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC_BLADESTOP }; + for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) + if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER); + for (i = 0; i < ARRAYLENGTH(scs); i++) + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } } - class_ = skill_id==SA_MONOCELL?1002:mob_get_random_id(4, 1, 0); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - mob_class_change(dstmd,class_); - if( tsc && dstmd->status.mode&MD_BOSS ) + break; + case SA_DEATH: + if ( sd && dstmd && dstmd->status.mode&MD_BOSS ) { - const enum sc_type scs[] = { SC_QUAGMIRE, SC_PROVOKE, SC_ROKISWEIL, SC_GRAVITATION, SC_SUITON, SC_STRIPWEAPON, SC_STRIPSHIELD, SC_STRIPARMOR, SC_STRIPHELM, SC_BLADESTOP }; - for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) - if (tsc->data[i]) status_change_end(bl, (sc_type)i, INVALID_TIMER); - for (i = 0; i < ARRAYLENGTH(scs); i++) - if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; } - } - break; - case SA_DEATH: - if ( sd && dstmd && dstmd->status.mode&MD_BOSS ) - { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_kill(bl); break; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - status_kill(bl); - break; - case SA_REVERSEORCISH: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id, skill_lv))); - break; - case SA_FORTUNE: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if(sd) pc_getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_STEAL,NULL); - break; - case SA_TAMINGMONSTER: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if (sd && dstmd) { - ARR_FIND( 0, MAX_PET_DB, i, dstmd->class_ == pet_db[i].class_ ); - if( i < MAX_PET_DB ) - pet_catch_process1(sd, dstmd->class_); - } - break; - - case CR_PROVIDENCE: - if(sd && dstsd){ //Check they are not another crusader [Skotlex] - if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; + case SA_REVERSEORCISH: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); + break; + case SA_FORTUNE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(sd) pc_getzeny(sd,status_get_lv(bl)*100,LOG_TYPE_STEAL,NULL); + break; + case SA_TAMINGMONSTER: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (sd && dstmd) { + ARR_FIND( 0, MAX_PET_DB, i, dstmd->class_ == pet_db[i].class_ ); + if( i < MAX_PET_DB ) + pet_catch_process1(sd, dstmd->class_); } - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - - case CG_MARIONETTE: - { - struct status_change* sc = status_get_sc(src); + break; - if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex ) - {// Cannot cast on another bard/dancer-type class of the same gender as caster - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; + case CR_PROVIDENCE: + if(sd && dstsd){ //Check they are not another crusader [Skotlex] + if ((dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; - if( sc && tsc ) + case CG_MARIONETTE: { - if( !sc->data[SC_MARIONETTE] && !tsc->data[SC_MARIONETTE2] ) - { - sc_start(src,SC_MARIONETTE,100,bl->id,skill_get_time(skill_id,skill_lv)); - sc_start(bl,SC_MARIONETTE2,100,src->id,skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); + struct status_change* sc = status_get_sc(src); + + if( sd && dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && dstsd->status.sex == sd->status.sex ) + {// Cannot cast on another bard/dancer-type class of the same gender as caster + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; } - else - if( sc->data[SC_MARIONETTE ] && sc->data[SC_MARIONETTE ]->val1 == bl->id && - tsc->data[SC_MARIONETTE2] && tsc->data[SC_MARIONETTE2]->val1 == src->id ) + + if( sc && tsc ) { - status_change_end(src, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); + if( !sc->data[SC_MARIONETTE] && !tsc->data[SC_MARIONETTE2] ) + { + sc_start(src,SC_MARIONETTE,100,bl->id,skill->get_time(skill_id,skill_lv)); + sc_start(bl,SC_MARIONETTE2,100,src->id,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + else + if( sc->data[SC_MARIONETTE ] && sc->data[SC_MARIONETTE ]->val1 == bl->id && + tsc->data[SC_MARIONETTE2] && tsc->data[SC_MARIONETTE2]->val1 == src->id ) + { + status_change_end(src, SC_MARIONETTE, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE2, INVALID_TIMER); + } + else + { + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + map_freeblock_unlock(); + return 1; + } } - else - { - if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + break; - map_freeblock_unlock(); - return 1; + case RG_CLOSECONFINE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv))); + break; + case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris] + case SA_FROSTWEAPON: + case SA_LIGHTNINGLOADER: + case SA_SEISMICWEAPON: + if (dstsd) { + if(dstsd->status.weapon == W_FIST || + (dstsd->sc.count && !dstsd->sc.data[type] && + ( //Allow re-enchanting to lenghten time. [Skotlex] + dstsd->sc.data[SC_FIREWEAPON] || + dstsd->sc.data[SC_WATERWEAPON] || + dstsd->sc.data[SC_WINDWEAPON] || + dstsd->sc.data[SC_EARTHWEAPON] || + dstsd->sc.data[SC_SHADOWWEAPON] || + dstsd->sc.data[SC_GHOSTWEAPON] || + dstsd->sc.data[SC_ENCPOISON] + )) + ) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + break; } } - } - break; + // 100% success rate at lv4 & 5, but lasts longer at lv5 + if(!clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,(60+skill_lv*10),skill_lv, skill->get_time(skill_id,skill_lv)))) { + if (sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if (skill->break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd) + clif->message(sd->fd, msg_txt(669)); + } + break; - case RG_CLOSECONFINE: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,src->id,0,0,skill_get_time(skill_id,skill_lv))); - break; - case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris] - case SA_FROSTWEAPON: - case SA_LIGHTNINGLOADER: - case SA_SEISMICWEAPON: - if (dstsd) { - if(dstsd->status.weapon == W_FIST || - (dstsd->sc.count && !dstsd->sc.data[type] && - ( //Allow re-enchanting to lenghten time. [Skotlex] - dstsd->sc.data[SC_FIREWEAPON] || - dstsd->sc.data[SC_WATERWEAPON] || - dstsd->sc.data[SC_WINDWEAPON] || - dstsd->sc.data[SC_EARTHWEAPON] || - dstsd->sc.data[SC_SHADOWWEAPON] || - dstsd->sc.data[SC_GHOSTWEAPON] || - dstsd->sc.data[SC_ENCPOISON] - )) - ) { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - clif_skill_nodamage(src,bl,skill_id,skill_lv,0); + case PR_ASPERSIO: + if (sd && dstmd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); break; } - } - // 100% success rate at lv4 & 5, but lasts longer at lv5 - if(!clif_skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,type,(60+skill_lv*10),skill_lv, skill_get_time(skill_id,skill_lv)))) { - if (sd) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - if (skill_break_equip(bl, EQP_WEAPON, 10000, BCT_PARTY) && sd && sd != dstsd) - clif_displaymessage(sd->fd, msg_txt(669)); - } - break; - - case PR_ASPERSIO: - if (sd && dstmd) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,0); + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); break; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - case ITEM_ENCHANTARMS: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv, - skill_get_ele(skill_id,skill_lv), skill_get_time(skill_id,skill_lv))); - break; + case ITEM_ENCHANTARMS: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv, + skill->get_ele(skill_id,skill_lv), skill->get_time(skill_id,skill_lv))); + break; - case TK_SEVENWIND: - switch(skill_get_ele(skill_id,skill_lv)) { - case ELE_EARTH : type = SC_EARTHWEAPON; break; - case ELE_WIND : type = SC_WINDWEAPON; break; - case ELE_WATER : type = SC_WATERWEAPON; break; - case ELE_FIRE : type = SC_FIREWEAPON; break; - case ELE_GHOST : type = SC_GHOSTWEAPON; break; - case ELE_DARK : type = SC_SHADOWWEAPON; break; - case ELE_HOLY : type = SC_ASPERSIO; break; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); + case TK_SEVENWIND: + switch(skill->get_ele(skill_id,skill_lv)) { + case ELE_EARTH : type = SC_EARTHWEAPON; break; + case ELE_WIND : type = SC_WINDWEAPON; break; + case ELE_WATER : type = SC_WATERWEAPON; break; + case ELE_FIRE : type = SC_FIREWEAPON; break; + case ELE_GHOST : type = SC_GHOSTWEAPON; break; + case ELE_DARK : type = SC_SHADOWWEAPON; break; + case ELE_HOLY : type = SC_ASPERSIO; break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); - sc_start(bl,SC_SEVENWIND,100,skill_lv,skill_get_time(skill_id,skill_lv)); + sc_start(bl,SC_SEVENWIND,100,skill_lv,skill->get_time(skill_id,skill_lv)); - break; + break; - case PR_KYRIE: - case MER_KYRIE: - clif_skill_nodamage(bl,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - //Passive Magnum, should had been casted on yourself. - case SM_MAGNUM: - case MS_MAGNUM: - skill_area_temp[1] = 0; - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - clif_skill_nodamage (src,src,skill_id,skill_lv,1); - // Initiate 10% of your damage becomes fire element. - sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill_get_time2(skill_id, skill_lv)); - if( sd ) - skill_blockpc_start(sd, skill_id, skill_get_time(skill_id, skill_lv)); - else if( bl->type == BL_MER ) - skill_blockmerc_start((TBL_MER*)bl, skill_id, skill_get_time(skill_id, skill_lv)); - break; + case PR_KYRIE: + case MER_KYRIE: + clif->skill_nodamage(bl,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; + //Passive Magnum, should had been casted on yourself. + case SM_MAGNUM: + case MS_MAGNUM: + skill_area_temp[1] = 0; + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_SKILL|BL_CHAR, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, skill->castend_damage_id); + clif->skill_nodamage (src,src,skill_id,skill_lv,1); + // Initiate 10% of your damage becomes fire element. + sc_start4(src,SC_WATK_ELEMENT,100,3,20,0,0,skill->get_time2(skill_id, skill_lv)); + if( sd ) + skill->blockpc_start(sd, skill_id, skill->get_time(skill_id, skill_lv), false); + else if( bl->type == BL_MER ) + skill->blockmerc_start((TBL_MER*)bl, skill_id, skill->get_time(skill_id, skill_lv)); + break; - case TK_JUMPKICK: - /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit_movepos (exploitable) */ - if( battle_check_target(src, bl, BCT_ENEMY) > 0 ) - { - if( unit_movepos(src, bl->x, bl->y, 1, 1) ) + case TK_JUMPKICK: + /* Check if the target is an enemy; if not, skill should fail so the character doesn't unit_movepos (exploitable) */ + if( battle->check_target(src, bl, BCT_ENEMY) > 0 ) { - skill_attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); - clif_slide(src,bl->x,bl->y); + if( unit_movepos(src, bl->x, bl->y, 1, 1) ) + { + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag); + clif->slide(src,bl->x,bl->y); + } } - } - else - clif_skill_fail(sd,skill_id,USESKILL_FAIL,0); - break; - - case AL_INCAGI: - case AL_BLESSING: - case MER_INCAGI: - case MER_BLESSING: - if (dstsd != NULL && tsc->data[SC_CHANGEUNDEAD]) { - skill_attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); break; - } - case PR_SLOWPOISON: - case PR_IMPOSITIO: - case PR_LEXAETERNA: - case PR_SUFFRAGIUM: - case PR_BENEDICTIO: - case LK_BERSERK: - case MS_BERSERK: - case KN_AUTOCOUNTER: - case KN_TWOHANDQUICKEN: - case KN_ONEHAND: - case MER_QUICKEN: - case CR_SPEARQUICKEN: - case CR_REFLECTSHIELD: - case MS_REFLECTSHIELD: - case AS_POISONREACT: - case MC_LOUD: - case MG_ENERGYCOAT: - case MO_EXPLOSIONSPIRITS: - case MO_STEELBODY: - case MO_BLADESTOP: - case LK_AURABLADE: - case LK_PARRYING: - case MS_PARRYING: - case LK_CONCENTRATION: - case WS_CARTBOOST: - case SN_SIGHT: - case WS_MELTDOWN: - case WS_OVERTHRUSTMAX: - case ST_REJECTSWORD: - case HW_MAGICPOWER: - case PF_MEMORIZE: - case PA_SACRIFICE: - case ASC_EDP: - case PF_DOUBLECASTING: - case SG_SUN_COMFORT: - case SG_MOON_COMFORT: - case SG_STAR_COMFORT: - case NPC_HALLUCINATION: - case GS_MADNESSCANCEL: - case GS_ADJUSTMENT: - case GS_INCREASING: - case NJ_KASUMIKIRI: - case NJ_UTSUSEMI: - case NJ_NEN: - case NPC_DEFENDER: - case NPC_MAGICMIRROR: - case ST_PRESERVE: - case NPC_INVINCIBLE: - case NPC_INVINCIBLEOFF: - case RK_DEATHBOUND: - case AB_RENOVATIO: - case AB_EXPIATIO: - case AB_DUPLELIGHT: - case AB_SECRAMENT: - case NC_ACCELERATION: - case NC_HOVERING: - case NC_SHAPESHIFT: - case WL_RECOGNIZEDSPELL: - case GC_VENOMIMPRESS: - case SC_DEADLYINFECT: - case LG_EXEEDBREAK: - case LG_PRESTIGE: - case SR_CRESCENTELBOW: - case SR_LIGHTNINGWALK: - case SR_GENTLETOUCH_ENERGYGAIN: - case GN_CARTBOOST: - case KO_MEIKYOUSISUI: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - - case SO_STRIKING: - if (sd) { - int bonus = 25 + 10 * skill_lv; - bonus += (pc_checkskill(sd, SA_FLAMELAUNCHER)+pc_checkskill(sd, SA_FROSTWEAPON)+pc_checkskill(sd, SA_LIGHTNINGLOADER)+pc_checkskill(sd, SA_SEISMICWEAPON))*5; - clif_skill_nodamage( src, bl, skill_id, skill_lv, - battle_check_target(src,bl,BCT_PARTY) ? - sc_start2(bl, type, 100, skill_lv, bonus, skill_get_time(skill_id,skill_lv)) : - 0 - ); - } - break; - case NPC_STOP: - if( clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,src->id,skill_get_time(skill_id,skill_lv)) ) ) - sc_start2(src,type,100,skill_lv,bl->id,skill_get_time(skill_id,skill_lv)); - break; - case HP_ASSUMPTIO: - if( sd && dstmd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - else - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - case MG_SIGHT: - case MER_SIGHT: - case AL_RUWACH: - case WZ_SIGHTBLASTER: - case NPC_WIDESIGHT: - case NPC_STONESKIN: - case NPC_ANTIMAGIC: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,skill_id,skill_get_time(skill_id,skill_lv))); - break; - case HLIF_AVOID: - case HAMI_DEFENCE: - i = skill_get_time(skill_id,skill_lv); - clif_skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,i)); // Master - clif_skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,type,100,skill_lv,i)); // Homunc - break; - case NJ_BUNSINJYUTSU: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - status_change_end(bl, SC_NEN, INVALID_TIMER); - break; -/* Was modified to only affect targetted char. [Skotlex] - case HP_ASSUMPTIO: - if (flag&1) - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - else - { - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skill_id, skill_lv), BL_PC, - src, skill_id, skill_lv, tick, flag|BCT_ALL|1, - skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; -*/ - case SM_ENDURE: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - if (sd) - skill_blockpc_start (sd, skill_id, skill_get_time2(skill_id,skill_lv)); - break; - - case AS_ENCHANTPOISON: // Prevent spamming [Valaris] - if (sd && dstsd && dstsd->sc.count) { - if (dstsd->sc.data[SC_FIREWEAPON] || - dstsd->sc.data[SC_WATERWEAPON] || - dstsd->sc.data[SC_WINDWEAPON] || - dstsd->sc.data[SC_EARTHWEAPON] || - dstsd->sc.data[SC_SHADOWWEAPON] || - dstsd->sc.data[SC_GHOSTWEAPON] - // dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex] - ) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,0); - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case AL_INCAGI: + case AL_BLESSING: + case MER_INCAGI: + case MER_BLESSING: + if (dstsd != NULL && tsc->data[SC_CHANGEUNDEAD]) { + skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag); + break; } - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - - case LK_TENSIONRELAX: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,0,0,skill_get_time2(skill_id,skill_lv), - skill_get_time(skill_id,skill_lv))); - break; - - case MC_CHANGECART: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; + case PR_SLOWPOISON: + case PR_IMPOSITIO: + case PR_LEXAETERNA: + case PR_SUFFRAGIUM: + case PR_BENEDICTIO: + case LK_BERSERK: + case MS_BERSERK: + case KN_AUTOCOUNTER: + case KN_TWOHANDQUICKEN: + case KN_ONEHAND: + case MER_QUICKEN: + case CR_SPEARQUICKEN: + case CR_REFLECTSHIELD: + case MS_REFLECTSHIELD: + case AS_POISONREACT: + case MC_LOUD: + case MG_ENERGYCOAT: + case MO_EXPLOSIONSPIRITS: + case MO_STEELBODY: + case MO_BLADESTOP: + case LK_AURABLADE: + case LK_PARRYING: + case MS_PARRYING: + case LK_CONCENTRATION: + case WS_CARTBOOST: + case SN_SIGHT: + case WS_MELTDOWN: + case WS_OVERTHRUSTMAX: + case ST_REJECTSWORD: + case HW_MAGICPOWER: + case PF_MEMORIZE: + case PA_SACRIFICE: + case ASC_EDP: + case PF_DOUBLECASTING: + case SG_SUN_COMFORT: + case SG_MOON_COMFORT: + case SG_STAR_COMFORT: + case NPC_HALLUCINATION: + case GS_MADNESSCANCEL: + case GS_ADJUSTMENT: + case GS_INCREASING: + case NJ_KASUMIKIRI: + case NJ_UTSUSEMI: + case NJ_NEN: + case NPC_DEFENDER: + case NPC_MAGICMIRROR: + case ST_PRESERVE: + case NPC_INVINCIBLE: + case NPC_INVINCIBLEOFF: + case RK_DEATHBOUND: + case AB_RENOVATIO: + case AB_EXPIATIO: + case AB_DUPLELIGHT: + case AB_SECRAMENT: + case NC_ACCELERATION: + case NC_HOVERING: + case NC_SHAPESHIFT: + case WL_RECOGNIZEDSPELL: + case GC_VENOMIMPRESS: + case SC_DEADLYINFECT: + case LG_EXEEDBREAK: + case LG_PRESTIGE: + case SR_CRESCENTELBOW: + case SR_LIGHTNINGWALK: + case SR_GENTLETOUCH_ENERGYGAIN: + case GN_CARTBOOST: + case KO_MEIKYOUSISUI: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; - case TK_MISSION: - if (sd) { - int id; - if (sd->mission_mobid && (sd->mission_count || rnd()%100)) { //Cannot change target when already have one - clif_mission_info(sd, sd->mission_mobid, sd->mission_count); - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case SO_STRIKING: + if (sd) { + int bonus = 25 + 10 * skill_lv; + bonus += (pc_checkskill(sd, SA_FLAMELAUNCHER)+pc_checkskill(sd, SA_FROSTWEAPON)+pc_checkskill(sd, SA_LIGHTNINGLOADER)+pc_checkskill(sd, SA_SEISMICWEAPON))*5; + clif->skill_nodamage( src, bl, skill_id, skill_lv, + battle->check_target(src,bl,BCT_PARTY) > 0 ? + sc_start2(bl, type, 100, skill_lv, bonus, skill->get_time(skill_id,skill_lv)) : + 0 + ); } - id = mob_get_random_id(0,0xF, sd->status.base_level); - if (!id) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + break; + + case NPC_STOP: + if( clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv)) ) ) + sc_start2(src,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)); + break; + case HP_ASSUMPTIO: + if( sd && dstmd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + else + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; + case MG_SIGHT: + case MER_SIGHT: + case AL_RUWACH: + case WZ_SIGHTBLASTER: + case NPC_WIDESIGHT: + case NPC_STONESKIN: + case NPC_ANTIMAGIC: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,skill_id,skill->get_time(skill_id,skill_lv))); + break; + case HLIF_AVOID: + case HAMI_DEFENCE: + i = skill->get_time(skill_id,skill_lv); + clif->skill_nodamage(bl,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,i)); // Master + clif->skill_nodamage(src,src,skill_id,skill_lv,sc_start(src,type,100,skill_lv,i)); // Homunc + break; + case NJ_BUNSINJYUTSU: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + status_change_end(bl, SC_NEN, INVALID_TIMER); + break; + /* Was modified to only affect targetted char. [Skotlex] + case HP_ASSUMPTIO: + if (flag&1) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + else + { + map_foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv), BL_PC, + src, skill_id, skill_lv, tick, flag|BCT_ALL|1, + skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - sd->mission_mobid = id; - sd->mission_count = 0; - pc_setglobalreg(sd,"TK_MISSION_ID", id); - clif_mission_info(sd, id, 0); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + break; + */ + case SM_ENDURE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if (sd) + skill->blockpc_start (sd, skill_id, skill->get_time2(skill_id,skill_lv), false); + break; - case AC_CONCENTRATION: - { - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - map_foreachinrange( status_change_timer_sub, src, - skill_get_splash(skill_id, skill_lv), BL_CHAR, - src,NULL,type,tick); - } - break; + case AS_ENCHANTPOISON: // Prevent spamming [Valaris] + if (sd && dstsd && dstsd->sc.count) { + if (dstsd->sc.data[SC_FIREWEAPON] || + dstsd->sc.data[SC_WATERWEAPON] || + dstsd->sc.data[SC_WINDWEAPON] || + dstsd->sc.data[SC_EARTHWEAPON] || + dstsd->sc.data[SC_SHADOWWEAPON] || + dstsd->sc.data[SC_GHOSTWEAPON] + // dstsd->sc.data[SC_ENCPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex] + ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; - case SM_PROVOKE: - case SM_SELFPROVOKE: - case MER_PROVOKE: - if( (tstatus->mode&MD_BOSS) || battle_check_undead(tstatus->race,tstatus->def_ele) ) - { - map_freeblock_unlock(); - return 1; - } - //TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex] - clif_skill_nodamage(src,bl,skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id,skill_lv, - (i = sc_start(bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status_get_lv(src) - status_get_lv(bl)), skill_lv, skill_get_time(skill_id,skill_lv)))); - if( !i ) - { - if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - unit_skillcastcancel(bl, 2); + case LK_TENSIONRELAX: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,0,0,skill->get_time2(skill_id,skill_lv), + skill->get_time(skill_id,skill_lv))); + break; - if( tsc && tsc->count ) - { - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE ) - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); - } + case MC_CHANGECART: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; - if( dstmd ) - { - dstmd->state.provoke_flag = src->id; - mob_target(dstmd, src, skill_get_range2(src,skill_id,skill_lv)); - } - break; + case TK_MISSION: + if (sd) { + int id; + if (sd->mission_mobid && (sd->mission_count || rnd()%100)) { //Cannot change target when already have one + clif->mission_info(sd, sd->mission_mobid, sd->mission_count); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + id = mob_get_random_id(0,0xF, sd->status.base_level); + if (!id) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + sd->mission_mobid = id; + sd->mission_count = 0; + pc_setglobalreg(sd,"TK_MISSION_ID", id); + clif->mission_info(sd, id, 0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case ML_DEVOTION: - case CR_DEVOTION: - { - int count, lv; - if( !dstsd || (!sd && !mer) ) - { // Only players can be devoted - if( sd ) - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; + case AC_CONCENTRATION: + { + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + map_foreachinrange( status_change_timer_sub, src, + skill->get_splash(skill_id, skill_lv), BL_CHAR, + src,NULL,type,tick); } + break; - if( (lv = status_get_lv(src) - dstsd->status.base_level) < 0 ) - lv = -lv; - if( lv > battle_config.devotion_level_difference || // Level difference requeriments - (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source - (skill_id == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner - (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted - (dstsd->sc.data[SC_HELLPOWER])) // Players affected by SC_HELLPOWERR cannot be devoted. + case SM_PROVOKE: + case SM_SELFPROVOKE: + case MER_PROVOKE: + if( (tstatus->mode&MD_BOSS) || battle->check_undead(tstatus->race,tstatus->def_ele) ) { - if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map_freeblock_unlock(); return 1; } + //TODO: How much does base level affects? Dummy value of 1% per level difference used. [Skotlex] + clif->skill_nodamage(src,bl,skill_id == SM_SELFPROVOKE ? SM_PROVOKE : skill_id,skill_lv, + (i = sc_start(bl,type, skill_id == SM_SELFPROVOKE ? 100:( 50 + 3*skill_lv + status_get_lv(src) - status_get_lv(bl)), skill_lv, skill->get_time(skill_id,skill_lv)))); + if( !i ) + { + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + unit_skillcastcancel(bl, 2); - i = 0; - count = (sd)? min(skill_lv,5) : 1; // Mercenary only can Devote owner - if( sd ) - { // Player Devoting Player - ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); - if( i == count ) + if( tsc && tsc->count ) + { + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + if( tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE ) + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_TRICKDEAD, INVALID_TIMER); + } + + if( dstmd ) + { + dstmd->state.provoke_flag = src->id; + mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv)); + } + break; + + case ML_DEVOTION: + case CR_DEVOTION: + { + int count, lv; + if( !dstsd || (!sd && !mer) ) + { // Only players can be devoted + if( sd ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; + } + + if( (lv = status_get_lv(src) - dstsd->status.base_level) < 0 ) + lv = -lv; + if( lv > battle_config.devotion_level_difference || // Level difference requeriments + (dstsd->sc.data[type] && dstsd->sc.data[type]->val1 != src->id) || // Cannot Devote a player devoted from another source + (skill_id == ML_DEVOTION && (!mer || mer != dstsd->md)) || // Mercenary only can devote owner + (dstsd->class_&MAPID_UPPERMASK) == MAPID_CRUSADER || // Crusader Cannot be devoted + (dstsd->sc.data[SC_HELLPOWER])) // Players affected by SC_HELLPOWERR cannot be devoted. { - ARR_FIND(0, count, i, sd->devotion[i] == 0 ); + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } + + i = 0; + count = (sd)? min(skill_lv,5) : 1; // Mercenary only can Devote owner + if( sd ) + { // Player Devoting Player + ARR_FIND(0, count, i, sd->devotion[i] == bl->id ); if( i == count ) - { // No free slots, skill Fail - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - map_freeblock_unlock(); - return 1; + { + ARR_FIND(0, count, i, sd->devotion[i] == 0 ); + if( i == count ) + { // No free slots, skill Fail + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + map_freeblock_unlock(); + return 1; + } } + + sd->devotion[i] = bl->id; } + else + mer->devotion_flag = 1; // Mercenary Devoting Owner - sd->devotion[i] = bl->id; + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start4(bl, type, 100, src->id, i, skill->get_range2(src,skill_id,skill_lv),0, skill->get_time2(skill_id, skill_lv))); + clif->devotion(src, NULL); } - else - mer->devotion_flag = 1; // Mercenary Devoting Owner - - clif_skill_nodamage(src, bl, skill_id, skill_lv, - sc_start4(bl, type, 100, src->id, i, skill_get_range2(src,skill_id,skill_lv),0, skill_get_time2(skill_id, skill_lv))); - clif_devotion(src, NULL); - } - break; + break; - case MO_CALLSPIRITS: - if(sd) { - int limit = skill_lv; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - pc_addspiritball(sd,skill_get_time(skill_id,skill_lv),limit); - } - break; + case MO_CALLSPIRITS: + if(sd) { + int limit = skill_lv; + if( sd->sc.data[SC_RAISINGDRAGON] ) + limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + pc_addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); + } + break; - case CH_SOULCOLLECT: - if(sd) { - int limit = 5; - if( sd->sc.data[SC_RAISINGDRAGON] ) - limit += sd->sc.data[SC_RAISINGDRAGON]->val1; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - for (i = 0; i < limit; i++) - pc_addspiritball(sd,skill_get_time(skill_id,skill_lv),limit); - } - break; + case CH_SOULCOLLECT: + if(sd) { + int limit = 5; + if( sd->sc.data[SC_RAISINGDRAGON] ) + limit += sd->sc.data[SC_RAISINGDRAGON]->val1; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + for (i = 0; i < limit; i++) + pc_addspiritball(sd,skill->get_time(skill_id,skill_lv),limit); + } + break; - case MO_KITRANSLATION: - if(dstsd && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { - pc_addspiritball(dstsd,skill_get_time(skill_id,skill_lv),5); - } - break; + case MO_KITRANSLATION: + if(dstsd && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) { + pc_addspiritball(dstsd,skill->get_time(skill_id,skill_lv),5); + } + break; - case TK_TURNKICK: - case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex] - if (skill_area_temp[1] != bl->id) { - skill_blown(src,bl,skill_get_blewcount(skill_id,skill_lv),-1,0); - skill_additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); //Use Misc rather than weapon to signal passive pushback - } - break; + case TK_TURNKICK: + case MO_BALKYOUNG: //Passive part of the attack. Splash knock-back+stun. [Skotlex] + if (skill_area_temp[1] != bl->id) { + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),-1,0); + skill->additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); //Use Misc rather than weapon to signal passive pushback + } + break; - case MO_ABSORBSPIRITS: - i = 0; - if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) - { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] - i = dstsd->spiritball * 7; - pc_delspiritball(dstsd,dstsd->spiritball,0); - } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) - { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen] - i = 2 * dstmd->level; - mob_target(dstmd,src,0); - } - if (i) status_heal(src, 0, i, 3); - clif_skill_nodamage(src,bl,skill_id,skill_lv,i?1:0); - break; + case MO_ABSORBSPIRITS: + i = 0; + if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER) + { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen] + i = dstsd->spiritball * 7; + pc_delspiritball(dstsd,dstsd->spiritball,0); + } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20) + { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen] + i = 2 * dstmd->level; + mob_target(dstmd,src,0); + } + if (i) status_heal(src, 0, i, 3); + clif->skill_nodamage(src,bl,skill_id,skill_lv,i?1:0); + break; - case AC_MAKINGARROW: - if(sd) { - clif_arrow_create_list(sd); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + case AC_MAKINGARROW: + if(sd) { + clif->arrow_create_list(sd); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case AM_PHARMACY: - if(sd) { - clif_skill_produce_mix_list(sd,skill_id,22); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + case AM_PHARMACY: + if(sd) { + clif->skill_produce_mix_list(sd,skill_id,22); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case SA_CREATECON: - if(sd) { - clif_elementalconverter_list(sd); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + case SA_CREATECON: + if(sd) { + clif->elementalconverter_list(sd); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case BS_HAMMERFALL: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill_get_time2(skill_id,skill_lv))); - break; - case RG_RAID: - skill_area_temp[1] = 0; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skill_id, skill_lv), splash_target(src), - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - status_change_end(src, SC_HIDING, INVALID_TIMER); - break; + case BS_HAMMERFALL: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,SC_STUN,(20 + 10 * skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv))); + break; + case RG_RAID: + skill_area_temp[1] = 0; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv), splash_target(src), + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, + skill->castend_damage_id); + status_change_end(src, SC_HIDING, INVALID_TIMER); + break; - case ASC_METEORASSAULT: - case GS_SPREADATTACK: - case RK_STORMBLAST: - case NC_AXETORNADO: - case GC_COUNTERSLASH: - case SR_SKYNETBLOW: - case SR_RAMPAGEBLASTER: - case SR_HOWLINGOFLION: - case KO_HAPPOKUNAI: - skill_area_temp[1] = 0; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - i = map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_damage_id); - if( !i && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) ) - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - break; + case ASC_METEORASSAULT: + case GS_SPREADATTACK: + case RK_STORMBLAST: + case NC_AXETORNADO: + case GC_COUNTERSLASH: + case SR_SKYNETBLOW: + case SR_RAMPAGEBLASTER: + case SR_HOWLINGOFLION: + case KO_HAPPOKUNAI: + skill_area_temp[1] = 0; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + i = map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_damage_id); + if( !i && ( skill_id == NC_AXETORNADO || skill_id == SR_SKYNETBLOW || skill_id == KO_HAPPOKUNAI ) ) + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + break; - case NC_EMERGENCYCOOL: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - status_change_end(src,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); - status_change_end(src,SC_OVERHEAT,INVALID_TIMER); - break; - case SR_WINDMILL: - case GN_CART_TORNADO: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - case SR_EARTHSHAKER: - case NC_INFRAREDSCAN: - case NPC_EARTHQUAKE: - case NPC_VAMPIRE_GIFT: - case NPC_HELLJUDGEMENT: - case NPC_PULSESTRIKE: - case LG_MOONSLASHER: - skill_castend_damage_id(src, src, skill_id, skill_lv, tick, flag); - break; + case NC_EMERGENCYCOOL: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_change_end(src,SC_OVERHEAT_LIMITPOINT,INVALID_TIMER); + status_change_end(src,SC_OVERHEAT,INVALID_TIMER); + break; + case SR_WINDMILL: + case GN_CART_TORNADO: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + case SR_EARTHSHAKER: + case NC_INFRAREDSCAN: + case NPC_EARTHQUAKE: + case NPC_VAMPIRE_GIFT: + case NPC_HELLJUDGEMENT: + case NPC_PULSESTRIKE: + case LG_MOONSLASHER: + skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); + break; - case KN_BRANDISHSPEAR: - case ML_BRANDISH: - skill_brandishspear(src, bl, skill_id, skill_lv, tick, flag); - break; + case KN_BRANDISHSPEAR: + case ML_BRANDISH: + skill->brandishspear(src, bl, skill_id, skill_lv, tick, flag); + break; - case WZ_SIGHTRASHER: - //Passive side of the attack. - status_change_end(src, SC_SIGHT, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub,src, - skill_get_splash(skill_id, skill_lv),BL_CHAR|BL_SKILL, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - break; + case WZ_SIGHTRASHER: + //Passive side of the attack. + status_change_end(src, SC_SIGHT, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub,src, + skill->get_splash(skill_id, skill_lv),BL_CHAR|BL_SKILL, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, + skill->castend_damage_id); + break; - case NJ_HYOUSYOURAKU: - case NJ_RAIGEKISAI: - case WZ_FROSTNOVA: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_area_temp[1] = 0; - map_foreachinrange(skill_attack_area, src, - skill_get_splash(skill_id, skill_lv), splash_target(src), - BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); - break; + case NJ_HYOUSYOURAKU: + case NJ_RAIGEKISAI: + case WZ_FROSTNOVA: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill_area_temp[1] = 0; + map_foreachinrange(skill->attack_area, src, + skill->get_splash(skill_id, skill_lv), splash_target(src), + BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY); + break; - case HVAN_EXPLOSION: //[orn] - case NPC_SELFDESTRUCTION: - //Self Destruction hits everyone in range (allies+enemies) - //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. - i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? - BCT_ENEMY:BCT_ALL; - clif_skill_nodamage(src, src, skill_id, -1, 1); - map_delblock(src); //Required to prevent chain-self-destructions hitting back. - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skill_id, skill_lv), splash_target(src), - src, skill_id, skill_lv, tick, flag|i, - skill_castend_damage_id); - map_addblock(src); - status_damage(src, src, sstatus->max_hp,0,0,1); - break; + case HVAN_EXPLOSION: //[orn] + case NPC_SELFDESTRUCTION: + //Self Destruction hits everyone in range (allies+enemies) + //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. + i = ((!md || md->special_state.ai == 2) && !map_flag_vs(src->m))? + BCT_ENEMY:BCT_ALL; + clif->skill_nodamage(src, src, skill_id, -1, 1); + map_delblock(src); //Required to prevent chain-self-destructions hitting back. + map_foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv), splash_target(src), + src, skill_id, skill_lv, tick, flag|i, + skill->castend_damage_id); + map_addblock(src); + status_damage(src, src, sstatus->max_hp,0,0,1); + break; - case AL_ANGELUS: - case PR_MAGNIFICAT: - case PR_GLORIA: - case SN_WINDWALK: - case CASH_BLESSING: - case CASH_INCAGI: - case CASH_ASSUMPTIO: - if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) - clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - else if( sd ) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; - case MER_MAGNIFICAT: - if( mer != NULL ) - { - clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - if( mer->master && mer->master->status.party_id != 0 && !(flag&1) ) - party_foreachsamemap(skill_area_sub, mer->master, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - else if( mer->master && !(flag&1) ) - clif_skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - } - break; + case AL_ANGELUS: + case PR_MAGNIFICAT: + case PR_GLORIA: + case SN_WINDWALK: + case CASH_BLESSING: + case CASH_INCAGI: + case CASH_ASSUMPTIO: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + break; + case MER_MAGNIFICAT: + if( mer != NULL ) + { + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if( mer->master && mer->master->status.party_id != 0 && !(flag&1) ) + party_foreachsamemap(skill->area_sub, mer->master, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + else if( mer->master && !(flag&1) ) + clif->skill_nodamage(src, &mer->master->bl, skill_id, skill_lv, sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + } + break; - case BS_ADRENALINE: - case BS_ADRENALINE2: - case BS_WEAPONPERFECT: - case BS_OVERTHRUST: - if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { - clif_skill_nodamage(bl,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,(src == bl)? 1:0,skill_get_time(skill_id,skill_lv))); - } else if (sd) { - party_foreachsamemap(skill_area_sub, - sd,skill_get_splash(skill_id, skill_lv), - src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, - skill_castend_nodamage_id); - } - break; + case BS_ADRENALINE: + case BS_ADRENALINE2: + case BS_WEAPONPERFECT: + case BS_OVERTHRUST: + if (sd == NULL || sd->status.party_id == 0 || (flag & 1)) { + clif->skill_nodamage(bl,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,(src == bl)? 1:0,skill->get_time(skill_id,skill_lv))); + } else if (sd) { + party_foreachsamemap(skill->area_sub, + sd,skill->get_splash(skill_id, skill_lv), + src,skill_id,skill_lv,tick, flag|BCT_PARTY|1, + skill->castend_nodamage_id); + } + break; - case BS_MAXIMIZE: - case NV_TRICKDEAD: - case CR_DEFENDER: - case ML_DEFENDER: - case CR_AUTOGUARD: - case ML_AUTOGUARD: - case TK_READYSTORM: - case TK_READYDOWN: - case TK_READYTURN: - case TK_READYCOUNTER: - case TK_DODGE: - case CR_SHRINK: - case SG_FUSION: - case GS_GATLINGFEVER: - if( tsce ) - { - clif_skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); - map_freeblock_unlock(); - return 0; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - case SL_KAITE: - case SL_KAAHI: - case SL_KAIZEL: - case SL_KAUPE: - if (sd) { - if (!dstsd || !( - (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SOULLINKER) || - (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER || - dstsd->status.char_id == sd->status.char_id || - dstsd->status.char_id == sd->status.partner_id || - dstsd->status.char_id == sd->status.child - )) { - status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,8); - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case BS_MAXIMIZE: + case NV_TRICKDEAD: + case CR_DEFENDER: + case ML_DEFENDER: + case CR_AUTOGUARD: + case ML_AUTOGUARD: + case TK_READYSTORM: + case TK_READYDOWN: + case TK_READYTURN: + case TK_READYCOUNTER: + case TK_DODGE: + case CR_SHRINK: + case SG_FUSION: + case GS_GATLINGFEVER: + if( tsce ) + { + clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); + map_freeblock_unlock(); + return 0; } - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id, skill_lv))); - break; - case SM_AUTOBERSERK: - case MER_AUTOBERSERK: - if( tsce ) - i = status_change_end(bl, type, INVALID_TIMER); - else - i = sc_start(bl,type,100,skill_lv,60000); - clif_skill_nodamage(src,bl,skill_id,skill_lv,i); - break; - case TF_HIDING: - case ST_CHASEWALK: - case KO_YAMIKUMO: - if (tsce) - { - clif_skill_nodamage(src,bl,skill_id,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation. - map_freeblock_unlock(); - return 0; - } else if( tsc && tsc->option&OPTION_MADOGEAR ) { - //Mado Gear cannot hide - if( sd ) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - clif_skill_nodamage(src,bl,skill_id,-1,sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - case TK_RUN: - if (tsce) - { - clif_skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); - map_freeblock_unlock(); - return 0; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,0)); - if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] - clif_walkok(sd); // So aegis has to resend the walk ok. - break; - case AS_CLOAKING: - case GC_CLOAKINGEXCEED: - case LG_FORCEOFVANGUARD: - case SC_REPRODUCE: - case SC_INVISIBILITY: - if (tsce) { - i = status_change_end(bl, type, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; + case SL_KAITE: + case SL_KAAHI: + case SL_KAIZEL: + case SL_KAUPE: + if (sd) { + if (!dstsd || !( + (sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_SOULLINKER) || + (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER || + dstsd->status.char_id == sd->status.char_id || + dstsd->status.char_id == sd->status.partner_id || + dstsd->status.char_id == sd->status.child + )) { + status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,8); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv))); + break; + case SM_AUTOBERSERK: + case MER_AUTOBERSERK: + if( tsce ) + i = status_change_end(bl, type, INVALID_TIMER); + else + i = sc_start(bl,type,100,skill_lv,60000); + clif->skill_nodamage(src,bl,skill_id,skill_lv,i); + break; + case TF_HIDING: + case ST_CHASEWALK: + case KO_YAMIKUMO: + if (tsce) + { + clif->skill_nodamage(src,bl,skill_id,-1,status_change_end(bl, type, INVALID_TIMER)); //Hide skill-scream animation. + map_freeblock_unlock(); + return 0; + } else if( tsc && tsc->option&OPTION_MADOGEAR ) { + //Mado Gear cannot hide + if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + clif->skill_nodamage(src,bl,skill_id,-1,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; + case TK_RUN: + if (tsce) + { + clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); + map_freeblock_unlock(); + return 0; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,0)); + if (sd) // If the client receives a skill-use packet inmediately before a walkok packet, it will discard the walk packet! [Skotlex] + clif->walkok(sd); // So aegis has to resend the walk ok. + break; + case AS_CLOAKING: + case GC_CLOAKINGEXCEED: + case LG_FORCEOFVANGUARD: + case SC_REPRODUCE: + case SC_INVISIBILITY: + if (tsce) { + i = status_change_end(bl, type, INVALID_TIMER); + if( i ) + clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); + else if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + case RA_CAMOUFLAGE: + i = sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); if( i ) - clif_skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); + clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); else if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } - case RA_CAMOUFLAGE: - i = sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - if( i ) - clif_skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,i); - else if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; - case BD_ADAPTATION: - if(tsc && tsc->data[SC_DANCING]){ - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - status_change_end(bl, SC_DANCING, INVALID_TIMER); - } - break; + case BD_ADAPTATION: + if(tsc && tsc->data[SC_DANCING]){ + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_change_end(bl, SC_DANCING, INVALID_TIMER); + } + break; - case BA_FROSTJOKER: - case DC_SCREAM: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_addtimerskill(src,tick+2000,bl->id,src->x,src->y,skill_id,skill_lv,0,flag); - - if (md) { - // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves - //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) - char temp[70]; - snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skill_id].desc); - clif_message(&md->bl,temp); - } - break; + case BA_FROSTJOKER: + case DC_SCREAM: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->addtimerskill(src,tick+2000,bl->id,src->x,src->y,skill_id,skill_lv,0,flag); - case BA_PANGVOICE: - clif_skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,50,7,skill_get_time(skill_id,skill_lv))); - break; + if (md) { + // custom hack to make the mob display the skill, because these skills don't show the skill use text themselves + //NOTE: mobs don't have the sprite animation that is used when performing this skill (will cause glitches) + char temp[70]; + snprintf(temp, sizeof(temp), "%s : %s !!",md->name,skill_db[skill_id].desc); + clif->disp_overhead(&md->bl,temp); + } + break; - case DC_WINKCHARM: - if( dstsd ) - clif_skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,30,7,skill_get_time2(skill_id,skill_lv))); - else - if( dstmd ) - { - if( status_get_lv(src) > status_get_lv(bl) - && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL) - && !(tstatus->mode&MD_BOSS) ) - clif_skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(bl,type,70,skill_lv,src->id,skill_get_time(skill_id,skill_lv))); + case BA_PANGVOICE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,50,7,skill->get_time(skill_id,skill_lv))); + break; + + case DC_WINKCHARM: + if( dstsd ) + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start(bl,SC_CONFUSION,30,7,skill->get_time2(skill_id,skill_lv))); else + if( dstmd ) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,0); - if(sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( status_get_lv(src) > status_get_lv(bl) + && (tstatus->race == RC_DEMON || tstatus->race == RC_DEMIHUMAN || tstatus->race == RC_ANGEL) + && !(tstatus->mode&MD_BOSS) ) + clif->skill_nodamage(src,bl,skill_id,skill_lv, sc_start2(bl,type,70,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); + else + { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } } - } - break; + break; - case TF_STEAL: - if(sd) { - if(pc_steal_item(sd,bl,skill_lv)) - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - else - clif_skill_fail(sd,skill_id,USESKILL_FAIL,0); - } - break; + case TF_STEAL: + if(sd) { + if(pc_steal_item(sd,bl,skill_lv)) + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); + } + break; + + case RG_STEALCOIN: + if(sd) { + if(pc_steal_coin(sd,bl)) + { + dstmd->state.provoke_flag = src->id; + mob_target(dstmd, src, skill->get_range2(src,skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - case RG_STEALCOIN: - if(sd) { - if(pc_steal_coin(sd,bl)) + } + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + break; + + case MG_STONECURSE: { - dstmd->state.provoke_flag = src->id; - mob_target(dstmd, src, skill_get_range2(src,skill_id,skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); + int brate = 0; + if (tstatus->mode&MD_BOSS) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + if(status_isimmune(bl) || !tsc) + break; + if (sd && sd->sc.data[SC_PETROLOGY_OPTION]) + brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3; + + if (tsc->data[SC_STONE]) { + status_change_end(bl, SC_STONE, INVALID_TIMER); + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + if (sc_start4(bl,SC_STONE,(skill_lv*4+20)+brate, + skill_lv, 0, 0, skill->get_time(skill_id, skill_lv), + skill->get_time2(skill_id,skill_lv))) + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + else if(sd) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + // Level 6-10 doesn't consume a red gem if it fails [celest] + if (skill_lv > 5) + { // not to consume items + map_freeblock_unlock(); + return 0; + } + } } - else - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; + break; - case MG_STONECURSE: - { - int brate = 0; - if (tstatus->mode&MD_BOSS) { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case NV_FIRSTAID: + clif->skill_nodamage(src,bl,skill_id,5,1); + status_heal(bl,5,0,0); + break; + + case AL_CURE: + if(status_isimmune(bl)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); break; } - if(status_isimmune(bl) || !tsc) - break; + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_CONFUSION, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; - if (sd && sd->sc.data[SC_PETROLOGY_OPTION]) - brate = sd->sc.data[SC_PETROLOGY_OPTION]->val3; + case TF_DETOXIFY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_DPOISON, INVALID_TIMER); + break; - if (tsc->data[SC_STONE]) { - status_change_end(bl, SC_STONE, INVALID_TIMER); - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case PR_STRECOVERY: + if(status_isimmune(bl)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); break; } - if (sc_start4(bl,SC_STONE,(skill_lv*4+20)+brate, - skill_lv, 0, 0, skill_get_time(skill_id, skill_lv), - skill_get_time2(skill_id,skill_lv))) - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - else if(sd) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - // Level 6-10 doesn't consume a red gem if it fails [celest] - if (skill_lv > 5) - { // not to consume items - map_freeblock_unlock(); - return 0; - } + if (tsc && tsc->opt1) { + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER); } - } - break; - - case NV_FIRSTAID: - clif_skill_nodamage(src,bl,skill_id,5,1); - status_heal(bl,5,0,0); - break; - - case AL_CURE: - if(status_isimmune(bl)) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,0); + //Is this equation really right? It looks so... special. + if( battle->check_undead(tstatus->race,tstatus->def_ele) ) { + status_change_start(bl, SC_BLIND, + 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), + 1,0,0,0, + skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0); + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(dstmd) + mob_unlocktarget(dstmd,tick); break; - } - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_CONFUSION, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - - case TF_DETOXIFY: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_DPOISON, INVALID_TIMER); - break; - case PR_STRECOVERY: - if(status_isimmune(bl)) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,0); + // Mercenary Supportive Skills + case MER_BENEDICTION: + status_change_end(bl, SC_CURSE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; - } - if (tsc && tsc->opt1) { - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); + case MER_COMPRESS: + status_change_end(bl, SC_BLEEDING, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_MENTALCURE: + status_change_end(bl, SC_CONFUSION, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_RECUPERATE: + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case MER_REGAIN: status_change_end(bl, SC_SLEEP, INVALID_TIMER); status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_WHITEIMPRISON, INVALID_TIMER); - } - //Is this equation really right? It looks so... special. - if(battle_check_undead(tstatus->race,tstatus->def_ele)) - { - status_change_start(bl, SC_BLIND, - 100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), - 1,0,0,0, - skill_get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0); - } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if(dstmd) - mob_unlocktarget(dstmd,tick); - break; - - // Mercenary Supportive Skills - case MER_BENEDICTION: - status_change_end(bl, SC_CURSE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case MER_COMPRESS: - status_change_end(bl, SC_BLEEDING, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case MER_MENTALCURE: - status_change_end(bl, SC_CONFUSION, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case MER_RECUPERATE: - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case MER_REGAIN: - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case MER_TENDER: - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - - case MER_SCAPEGOAT: - if( mer && mer->master ) - { - status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2); - status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1); - } - break; - - case MER_ESTIMATION: - if( !mer ) + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; - sd = mer->master; - case WZ_ESTIMATION: - if( sd == NULL ) + case MER_TENDER: + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); break; - if( dstsd ) - { // Fail on Players - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + case MER_SCAPEGOAT: + if( mer && mer->master ) + { + status_heal(&mer->master->bl, mer->battle_status.hp, 0, 2); + status_damage(src, src, mer->battle_status.max_hp, 0, 0, 1); + } break; - } - if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) - break; // Cannot be Used on Emperium - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - clif_skill_estimation(sd, bl); - if( skill_id == MER_ESTIMATION ) - sd = NULL; - break; + case MER_ESTIMATION: + if( !mer ) + break; + sd = mer->master; + case WZ_ESTIMATION: + if( sd == NULL ) + break; + if( dstsd ) + { // Fail on Players + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) + break; // Cannot be Used on Emperium - case BS_REPAIRWEAPON: - if(sd && dstsd) - clif_item_repair_list(sd,dstsd,skill_lv); - break; + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + clif->skill_estimation(sd, bl); + if( skill_id == MER_ESTIMATION ) + sd = NULL; + break; - case MC_IDENTIFY: - if(sd) - clif_item_identify_list(sd); - break; + case BS_REPAIRWEAPON: + if(sd && dstsd) + clif->item_repair_list(sd,dstsd,skill_lv); + break; - // Weapon Refining [Celest] - case WS_WEAPONREFINE: - if(sd) - clif_item_refine_list(sd); - break; + case MC_IDENTIFY: + if(sd) + clif->item_identify_list(sd); + break; - case MC_VENDING: - if(sd) - { //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex] - if ( !pc_can_give_items(sd) ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - else { - sd->state.prevend = 1; - clif_openvendingreq(sd,2+skill_lv); - } - } - break; + // Weapon Refining [Celest] + case WS_WEAPONREFINE: + if(sd) + clif->item_refine_list(sd); + break; - case AL_TELEPORT: - if(sd) - { - if (map[bl->m].flag.noteleport && skill_lv <= 2) { - clif_skill_teleportmessage(sd,0); - break; - } - if(!battle_config.duel_allow_teleport && sd->duel_group && skill_lv <= 2) { // duel restriction [LuzZza] - char output[128]; sprintf(output, msg_txt(365), skill_get_name(AL_TELEPORT)); - clif_displaymessage(sd->fd, output); //"Duel: Can't use %s in duel." - break; + case MC_VENDING: + if(sd) + { //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex] + if ( !pc_can_give_items(sd) ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + else { + sd->state.prevend = 1; + clif->openvendingreq(sd,2+skill_lv); + } } + break; - if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 ) + case AL_TELEPORT: + if(sd) { + if (map[bl->m].flag.noteleport && skill_lv <= 2) { + clif->skill_teleportmessage(sd,0); + break; + } + if(!battle_config.duel_allow_teleport && sd->duel_group && skill_lv <= 2) { // duel restriction [LuzZza] + char output[128]; sprintf(output, msg_txt(365), skill->get_name(AL_TELEPORT)); + clif->message(sd->fd, output); //"Duel: Can't use %s in duel." + break; + } + + if( sd->state.autocast || ( (sd->skillitem == AL_TELEPORT || battle_config.skip_teleport_lv1_menu) && skill_lv == 1 ) || skill_lv == 3 ) + { + if( skill_lv == 1 ) + pc_randomwarp(sd,CLR_TELEPORT); + else + pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; + } + + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); if( skill_lv == 1 ) - pc_randomwarp(sd,CLR_TELEPORT); + clif->skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,0,0,0); else - pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - } + clif->skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,sd->status.save_point.map,0,0); + } else + unit_warp(bl,-1,-1,-1,CLR_TELEPORT); + break; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if( skill_lv == 1 ) - clif_skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,0,0,0); - else - clif_skill_warppoint(sd,skill_id,skill_lv, (unsigned short)-1,sd->status.save_point.map,0,0); - } else + case NPC_EXPULSION: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); unit_warp(bl,-1,-1,-1,CLR_TELEPORT); - break; - - case NPC_EXPULSION: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - unit_warp(bl,-1,-1,-1,CLR_TELEPORT); - break; - - case AL_HOLYWATER: - if(sd) { - if (skill_produce_mix(sd, skill_id, 523, 0, 0, 0, 1)) - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - else - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; + break; - case TF_PICKSTONE: - if(sd) { - int eflag; - struct item item_tmp; - struct block_list tbl; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - memset(&item_tmp,0,sizeof(item_tmp)); - memset(&tbl,0,sizeof(tbl)); // [MouseJstr] - item_tmp.nameid = ITEMID_STONE; - item_tmp.identify = 1; - tbl.id = 0; - clif_takeitem(&sd->bl,&tbl); - eflag = pc_additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE); - if(eflag) { - clif_additem(sd,0,0,eflag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + case AL_HOLYWATER: + if(sd) { + if (skill->produce_mix(sd, skill_id, 523, 0, 0, 0, 1)) + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } - } - break; - case ASC_CDP: - if(sd) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_produce_mix(sd, skill_id, 678, 0, 0, 0, 1); //Produce a Deadly Poison Bottle. - } - break; - - case RG_STRIPWEAPON: - case RG_STRIPSHIELD: - case RG_STRIPARMOR: - case RG_STRIPHELM: - case ST_FULLSTRIP: - case GC_WEAPONCRUSH: - case SC_STRIPACCESSARY: { - unsigned short location = 0; - int d = 0; - - //Rate in percent - if ( skill_id == ST_FULLSTRIP ) { - i = 5 + 2*skill_lv + (sstatus->dex - tstatus->dex)/5; - } else if( skill_id == SC_STRIPACCESSARY ) { - i = 12 + 2 * skill_lv + (sstatus->dex - tstatus->dex)/5; - } else { - i = 5 + 5*skill_lv + (sstatus->dex - tstatus->dex)/5; - } - - if (i < 5) i = 5; //Minimum rate 5% - - //Duration in ms - if( skill_id == GC_WEAPONCRUSH){ - d = skill_get_time(skill_id,skill_lv); - if(bl->type == BL_PC) - d += skill_lv * 15 + (sstatus->dex - tstatus->dex); - else - d += skill_lv * 30 + (sstatus->dex - tstatus->dex) / 2; - }else - d = skill_get_time(skill_id,skill_lv) + (sstatus->dex - tstatus->dex)*500; + break; - if (d < 0) d = 0; //Minimum duration 0ms + case TF_PICKSTONE: + if(sd) { + int eflag; + struct item item_tmp; + struct block_list tbl; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + memset(&item_tmp,0,sizeof(item_tmp)); + memset(&tbl,0,sizeof(tbl)); // [MouseJstr] + item_tmp.nameid = ITEMID_STONE; + item_tmp.identify = 1; + tbl.id = 0; + clif->takeitem(&sd->bl,&tbl); + eflag = pc_additem(sd,&item_tmp,1,LOG_TYPE_PRODUCE); + if(eflag) { + clif->additem(sd,0,0,eflag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } + } + break; + case ASC_CDP: + if(sd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->produce_mix(sd, skill_id, 678, 0, 0, 0, 1); //Produce a Deadly Poison Bottle. + } + break; - switch (skill_id) { case RG_STRIPWEAPON: - case GC_WEAPONCRUSH: - location = EQP_WEAPON; - break; case RG_STRIPSHIELD: - location = EQP_SHIELD; - break; case RG_STRIPARMOR: - location = EQP_ARMOR; - break; case RG_STRIPHELM: - location = EQP_HELM; - break; case ST_FULLSTRIP: - location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; - break; - case SC_STRIPACCESSARY: - location = EQP_ACC; - break; - } + case GC_WEAPONCRUSH: + case SC_STRIPACCESSARY: { + unsigned short location = 0; + int d = 0; + + //Rate in percent + if ( skill_id == ST_FULLSTRIP ) { + i = 5 + 2*skill_lv + (sstatus->dex - tstatus->dex)/5; + } else if( skill_id == SC_STRIPACCESSARY ) { + i = 12 + 2 * skill_lv + (sstatus->dex - tstatus->dex)/5; + } else { + i = 5 + 5*skill_lv + (sstatus->dex - tstatus->dex)/5; + } - //Special message when trying to use strip on FCP [Jobbie] - if( sd && skill_id == ST_FULLSTRIP && tsc && tsc->data[SC_CP_WEAPON] && tsc->data[SC_CP_HELM] && tsc->data[SC_CP_ARMOR] && tsc->data[SC_CP_SHIELD]) - { - clif_gospel_info(sd, 0x28); - break; - } + if (i < 5) i = 5; //Minimum rate 5% - //Attempts to strip at rate i and duration d - if( (i = skill_strip_equip(bl, location, i, skill_lv, d)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) ) - clif_skill_nodamage(src,bl,skill_id,skill_lv,i); + //Duration in ms + if( skill_id == GC_WEAPONCRUSH){ + d = skill->get_time(skill_id,skill_lv); + if(bl->type == BL_PC) + d += skill_lv * 15 + (sstatus->dex - tstatus->dex); + else + d += skill_lv * 30 + (sstatus->dex - tstatus->dex) / 2; + }else + d = skill->get_time(skill_id,skill_lv) + (sstatus->dex - tstatus->dex)*500; - //Nothing stripped. - if( sd && !i ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } + if (d < 0) d = 0; //Minimum duration 0ms - case AM_BERSERKPITCHER: - case AM_POTIONPITCHER: { - int i,x,hp = 0,sp = 0,bonus=100; - if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) { - map_freeblock_unlock(); - return 1; + switch (skill_id) { + case RG_STRIPWEAPON: + case GC_WEAPONCRUSH: + location = EQP_WEAPON; + break; + case RG_STRIPSHIELD: + location = EQP_SHIELD; + break; + case RG_STRIPARMOR: + location = EQP_ARMOR; + break; + case RG_STRIPHELM: + location = EQP_HELM; + break; + case ST_FULLSTRIP: + location = EQP_WEAPON|EQP_SHIELD|EQP_ARMOR|EQP_HELM; + break; + case SC_STRIPACCESSARY: + location = EQP_ACC; + break; } - if( sd ) { - x = skill_lv%11 - 1; - i = pc_search_inventory(sd,skill_db[skill_id].itemid[x]); - if( i < 0 || skill_db[skill_id].itemid[x] <= 0 ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skill_id].amount[x]) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + //Special message when trying to use strip on FCP [Jobbie] + if( sd && skill_id == ST_FULLSTRIP && tsc && tsc->data[SC_CP_WEAPON] && tsc->data[SC_CP_HELM] && tsc->data[SC_CP_ARMOR] && tsc->data[SC_CP_SHIELD]) + { + clif->gospel_info(sd, 0x28); + break; + } + + //Attempts to strip at rate i and duration d + if( (i = skill->strip_equip(bl, location, i, skill_lv, d)) || (skill_id != ST_FULLSTRIP && skill_id != GC_WEAPONCRUSH ) ) + clif->skill_nodamage(src,bl,skill_id,skill_lv,i); + + //Nothing stripped. + if( sd && !i ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + + case AM_BERSERKPITCHER: + case AM_POTIONPITCHER: { + int i,hp = 0,sp = 0; + if( dstmd && dstmd->class_ == MOBID_EMPERIUM ) { map_freeblock_unlock(); return 1; } - if( skill_id == AM_BERSERKPITCHER ) { - if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( sd ) { + int x,bonus=100; + x = skill_lv%11 - 1; + i = pc_search_inventory(sd,skill_db[skill_id].itemid[x]); + if( i < 0 || skill_db[skill_id].itemid[x] <= 0 ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map_freeblock_unlock(); return 1; } - } - potion_flag = 1; - potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0; - potion_target = bl->id; - run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); - potion_flag = potion_target = 0; - if( sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST ) - bonus += sd->status.base_level; - if( potion_per_hp > 0 || potion_per_sp > 0 ) { - hp = tstatus->max_hp * potion_per_hp / 100; - hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - if( dstsd ) { - sp = dstsd->status.max_sp * potion_per_sp / 100; - sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + if(sd->inventory_data[i] == NULL || sd->status.inventory[i].amount < skill_db[skill_id].amount[x]) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; } - } else { - if( potion_hp > 0 ) { - hp = potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - hp = hp * (100 + (tstatus->vit<<1)) / 100; - if( dstsd ) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; + if( skill_id == AM_BERSERKPITCHER ) { + if( dstsd && dstsd->status.base_level < (unsigned int)sd->inventory_data[i]->elv ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 1; + } } - if( potion_sp > 0 ) { - sp = potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; - sp = sp * (100 + (tstatus->int_<<1)) / 100; - if( dstsd ) - sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; + potion_flag = 1; + potion_hp = potion_sp = potion_per_hp = potion_per_sp = 0; + potion_target = bl->id; + run_script(sd->inventory_data[i]->script,0,sd->bl.id,0); + potion_flag = potion_target = 0; + if( sd->sc.data[SC_SPIRIT] && sd->sc.data[SC_SPIRIT]->val2 == SL_ALCHEMIST ) + bonus += sd->status.base_level; + if( potion_per_hp > 0 || potion_per_sp > 0 ) { + hp = tstatus->max_hp * potion_per_hp / 100; + hp = hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + if( dstsd ) { + sp = dstsd->status.max_sp * potion_per_sp / 100; + sp = sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + } + } else { + if( potion_hp > 0 ) { + hp = potion_hp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + hp = hp * (100 + (tstatus->vit<<1)) / 100; + if( dstsd ) + hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; + } + if( potion_sp > 0 ) { + sp = potion_sp * (100 + pc_checkskill(sd,AM_POTIONPITCHER)*10 + pc_checkskill(sd,AM_LEARNINGPOTION)*5)*bonus/10000; + sp = sp * (100 + (tstatus->int_<<1)) / 100; + if( dstsd ) + sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10) / 100; + } } - } - if (sd->itemgrouphealrate[IG_POTION]>0) { - hp += hp * sd->itemgrouphealrate[IG_POTION] / 100; - sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; - } + if (sd->itemgrouphealrate[IG_POTION]>0) { + hp += hp * sd->itemgrouphealrate[IG_POTION] / 100; + sp += sp * sd->itemgrouphealrate[IG_POTION] / 100; + } - if( (i = pc_skillheal_bonus(sd, skill_id)) ) { + if( (i = pc_skillheal_bonus(sd, skill_id)) ) { + hp += hp * i / 100; + sp += sp * i / 100; + } + } else { + hp = (1 + rnd()%400) * (100 + skill_lv*10) / 100; + hp = hp * (100 + (tstatus->vit<<1)) / 100; + if( dstsd ) + hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; + } + if( dstsd && (i = pc_skillheal2_bonus(dstsd, skill_id)) ) { hp += hp * i / 100; sp += sp * i / 100; } - } else { - hp = (1 + rnd()%400) * (100 + skill_lv*10) / 100; - hp = hp * (100 + (tstatus->vit<<1)) / 100; - if( dstsd ) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10) / 100; - } - if( dstsd && (i = pc_skillheal2_bonus(dstsd, skill_id)) ) { - hp += hp * i / 100; - sp += sp * i / 100; - } - if( tsc && tsc->count ) { - if( tsc->data[SC_CRITICALWOUND] ) { - hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - } - if( tsc->data[SC_DEATHHURT] ) { - hp -= hp * 20 / 100; - sp -= sp * 20 / 100; - } - if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2 ) { - hp += hp / 10; - sp += sp / 10; - } - } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if( hp > 0 || (skill_id == AM_POTIONPITCHER && sp <= 0) ) - clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); - if( sp > 0 ) - clif_skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); -#ifdef RENEWAL - if( tsc && tsc->data[SC_EXTREMITYFIST2] ) - sp = 0; -#endif - status_heal(bl,hp,sp,0); - } - break; - case AM_CP_WEAPON: - case AM_CP_SHIELD: - case AM_CP_ARMOR: - case AM_CP_HELM: - { - unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; - - if( sd && ( bl->type != BL_PC || ( dstsd && pc_checkequip(dstsd,equip[skill_id - AM_CP_WEAPON]) < 0 ) ) ){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); // Don't consume item requirements - return 0; + if( tsc && tsc->count ) { + if( tsc->data[SC_CRITICALWOUND] ) { + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + } + if( tsc->data[SC_DEATHHURT] ) { + hp -= hp * 20 / 100; + sp -= sp * 20 / 100; + } + if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2 ) { + hp += hp / 10; + sp += sp / 10; + } + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( hp > 0 || (skill_id == AM_POTIONPITCHER && sp <= 0) ) + clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1); + if( sp > 0 ) + clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); + #ifdef RENEWAL + if( tsc && tsc->data[SC_EXTREMITYFIST2] ) + sp = 0; + #endif + status_heal(bl,hp,sp,0); } + break; + case AM_CP_WEAPON: + case AM_CP_SHIELD: + case AM_CP_ARMOR: + case AM_CP_HELM: + { + unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - } - break; - case AM_TWILIGHT1: - if (sd) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - //Prepare 200 White Potions. - if (!skill_produce_mix(sd, skill_id, 504, 0, 0, 0, 200)) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; - case AM_TWILIGHT2: - if (sd) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - //Prepare 200 Slim White Potions. - if (!skill_produce_mix(sd, skill_id, 547, 0, 0, 0, 200)) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; - case AM_TWILIGHT3: - if (sd) { - int ebottle = pc_search_inventory(sd,713); - if( ebottle >= 0 ) - ebottle = sd->status.inventory[ebottle].amount; - //check if you can produce all three, if not, then fail: - if (!skill_can_produce_mix(sd,970,-1, 100) //100 Alcohol - || !skill_can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle - || !skill_can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle - || ebottle < 200 //200 empty bottle are required at total. - ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( sd && ( bl->type != BL_PC || ( dstsd && pc_checkequip(dstsd,equip[skill_id - AM_CP_WEAPON]) < 0 ) ) ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); // Don't consume item requirements + return 0; + } + + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_produce_mix(sd, skill_id, 970, 0, 0, 0, 100); - skill_produce_mix(sd, skill_id, 7136, 0, 0, 0, 50); - skill_produce_mix(sd, skill_id, 7135, 0, 0, 0, 50); - } - break; - case SA_DISPELL: - if (flag&1 || (i = skill_get_splash(skill_id, skill_lv)) < 1) - { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) - || (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel. - || rnd()%100 >= 50+10*skill_lv - || ( tsc && tsc->option&OPTION_MADOGEAR ) )//Mado Gear is immune to dispell according to bug report 49 [Ind] - { - if (sd) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + break; + case AM_TWILIGHT1: + if (sd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + //Prepare 200 White Potions. + if (!skill->produce_mix(sd, skill_id, 504, 0, 0, 0, 200)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } - if(status_isimmune(bl) || !tsc || !tsc->count) - break; - for(i=0;i<SC_MAX;i++) + break; + case AM_TWILIGHT2: + if (sd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + //Prepare 200 Slim White Potions. + if (!skill->produce_mix(sd, skill_id, 547, 0, 0, 0, 200)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + break; + case AM_TWILIGHT3: + if (sd) { + int ebottle = pc_search_inventory(sd,713); + if( ebottle >= 0 ) + ebottle = sd->status.inventory[ebottle].amount; + //check if you can produce all three, if not, then fail: + if (!skill->can_produce_mix(sd,970,-1, 100) //100 Alcohol + || !skill->can_produce_mix(sd,7136,-1, 50) //50 Acid Bottle + || !skill->can_produce_mix(sd,7135,-1, 50) //50 Flame Bottle + || ebottle < 200 //200 empty bottle are required at total. + ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->produce_mix(sd, skill_id, 970, 0, 0, 0, 100); + skill->produce_mix(sd, skill_id, 7136, 0, 0, 0, 50); + skill->produce_mix(sd, skill_id, 7135, 0, 0, 0, 50); + } + break; + case SA_DISPELL: + if (flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1) { - if (!tsc->data[i]) - continue; - switch (i) { - case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: - case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR: - case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD: - case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO: - case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: - case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: - case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: - case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: - case SC_EDP: case SC_AUTOBERSERK: - case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: - case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: - case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: - case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: - case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: - case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: - case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: - case SC_READYCOUNTER: case SC_DODGE: case SC_WARM: - case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: - case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: - case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: - case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: - case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: - case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: - case SC_INTOABYSS: case SC_SIEGFRIED: case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: case SC_FOOD_LUK_CASH: case SC_SEVENWIND: - case SC_MIRACLE: case SC_S_LIFEPOTION: case SC_L_LIFEPOTION: - case SC_INCHEALRATE: case SC_ELECTRICSHOCKER: case SC__STRIPACCESSORY: - //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ: - //case SC_SIROMA_ICE_TEA: case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: - case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: case SC_STEALTHFIELD_MASTER: - case SC_STEALTHFIELD: case SC_GIANTGROWTH: case SC_MILLENNIUMSHIELD: - case SC_REFRESH: case SC_STONEHARDSKIN: case SC_VITALITYACTIVATION: - case SC_FIGHTINGSPIRIT: case SC_ABUNDANCE: case SC__SHADOWFORM: - case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: - case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: - case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: - case SC_GT_REVITALIZE: case SC_REFLECTDAMAGE: case SC_INSPIRATION: - case SC_EXEEDBREAK: case SC_FORCEOFVANGUARD: case SC_BANDING: - case SC_DUPLELIGHT: case SC_EXPIATIO: case SC_LAUDAAGNUS: - case SC_LAUDARAMUS: case SC_GATLINGFEVER: case SC_INCREASING: - case SC_ADJUSTMENT: case SC_MADNESSCANCEL: -#ifdef RENEWAL - case SC_EXTREMITYFIST2: -#endif - continue; - /** - * bugreport:4888 these songs may only be dispelled if you're not in their song area anymore - **/ - case SC_WHISTLE: - case SC_ASSNCROS: - case SC_POEMBRAGI: - case SC_APPLEIDUN: - case SC_HUMMING: - case SC_DONTFORGETME: - case SC_FORTUNE: - case SC_SERVICE4U: - if( tsc->data[i]->val4 ) //val4 = out-of-song-area - continue; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) + || (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_ROGUE) //Rogue's spirit defends againt dispel. + || rnd()%100 >= 50+10*skill_lv + || ( tsc && tsc->option&OPTION_MADOGEAR ) )//Mado Gear is immune to dispell according to bug report 49 [Ind] + { + if (sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; - case SC_ASSUMPTIO: - if( bl->type == BL_MOB ) - continue; + } + if(status_isimmune(bl) || !tsc || !tsc->count) + break; + + if( sd && dstsd && !map_flag_vs(sd->bl.m) && sd->status.guild_id == dstsd->status.guild_id ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } - if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. - status_change_end(bl, (sc_type)i, INVALID_TIMER); + + for(i=0;i<SC_MAX;i++) + { + if (!tsc->data[i]) + continue; + switch (i) { + case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: + case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR: + case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD: + case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO: + case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: + case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: + case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: + case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: + case SC_EDP: case SC_AUTOBERSERK: + case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: + case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: + case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: + case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: + case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: + case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: + case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: + case SC_READYCOUNTER: case SC_DODGE: case SC_WARM: + case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: + case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: + case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: + case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: + case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: + case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: + case SC_INTOABYSS: case SC_SIEGFRIED: case SC_FOOD_STR_CASH: + case SC_FOOD_AGI_CASH: case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: + case SC_FOOD_INT_CASH: case SC_FOOD_LUK_CASH: case SC_SEVENWIND: + case SC_MIRACLE: case SC_S_LIFEPOTION: case SC_L_LIFEPOTION: + case SC_INCHEALRATE: case SC_ELECTRICSHOCKER: case SC__STRIPACCESSORY: + //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: case SC_MINOR_BBQ: + //case SC_SIROMA_ICE_TEA: case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: + case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: case SC_STEALTHFIELD_MASTER: + case SC_STEALTHFIELD: case SC_GIANTGROWTH: case SC_MILLENNIUMSHIELD: + case SC_REFRESH: case SC_STONEHARDSKIN: case SC_VITALITYACTIVATION: + case SC_FIGHTINGSPIRIT: case SC_ABUNDANCE: case SC__SHADOWFORM: + case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: + case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: + case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: + case SC_GT_REVITALIZE: case SC_REFLECTDAMAGE: case SC_INSPIRATION: + case SC_EXEEDBREAK: case SC_FORCEOFVANGUARD: case SC_BANDING: + case SC_DUPLELIGHT: case SC_EXPIATIO: case SC_LAUDAAGNUS: + case SC_LAUDARAMUS: case SC_GATLINGFEVER: case SC_INCREASING: + case SC_ADJUSTMENT: case SC_MADNESSCANCEL: case SC_ALL_RIDING: + #ifdef RENEWAL + case SC_EXTREMITYFIST2: + #endif + continue; + /** + * bugreport:4888 these songs may only be dispelled if you're not in their song area anymore + **/ + case SC_WHISTLE: + case SC_ASSNCROS: + case SC_POEMBRAGI: + case SC_APPLEIDUN: + case SC_HUMMING: + case SC_DONTFORGETME: + case SC_FORTUNE: + case SC_SERVICE4U: + if( !tsc->data[i]->val4 ) //val4 = out-of-song-area + continue; + break; + case SC_ASSUMPTIO: + if( bl->type == BL_MOB ) + continue; + break; + } + if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + status_change_end(bl, (sc_type)i, INVALID_TIMER); + } + break; } + //Affect all targets on splash area. + map_foreachinrange(skill->area_sub, bl, i, BL_CHAR, + src, skill_id, skill_lv, tick, flag|1, + skill->castend_damage_id); break; - } - //Affect all targets on splash area. - map_foreachinrange(skill_area_sub, bl, i, BL_CHAR, - src, skill_id, skill_lv, tick, flag|1, - skill_castend_damage_id); - break; - case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex] - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_blown(src,bl,skill_get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); - break; + case TF_BACKSLIDING: //This is the correct implementation as per packet logging information. [Skotlex] + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); + break; - case TK_HIGHJUMP: - { - int x,y, dir = unit_getdir(src); + case TK_HIGHJUMP: + { + int x,y, dir = unit_getdir(src); - //Fails on noteleport maps, except for GvG and BG maps [Skotlex] - if( map[src->m].flag.noteleport && - !(map[src->m].flag.battleground || map_flag_gvg2(src->m) ) - ) { - x = src->x; - y = src->y; - } else { - x = src->x + dirx[dir]*skill_lv*2; - y = src->y + diry[dir]*skill_lv*2; - } + //Fails on noteleport maps, except for GvG and BG maps [Skotlex] + if( map[src->m].flag.noteleport && + !(map[src->m].flag.battleground || map_flag_gvg2(src->m) ) + ) { + x = src->x; + y = src->y; + } else { + x = src->x + dirx[dir]*skill_lv*2; + y = src->y + diry[dir]*skill_lv*2; + } - clif_skill_nodamage(src,bl,TK_HIGHJUMP,skill_lv,1); - if(!map_count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && map_getcell(src->m,x,y,CELL_CHKREACH)) { - clif_slide(src,x,y); - unit_movepos(src, x, y, 1, 0); + clif->skill_nodamage(src,bl,TK_HIGHJUMP,skill_lv,1); + if(!map_count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB) && map_getcell(src->m,x,y,CELL_CHKREACH)) { + clif->slide(src,x,y); + unit_movepos(src, x, y, 1, 0); + } } - } - break; + break; - case SA_CASTCANCEL: - case SO_SPELLFIST: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - unit_skillcastcancel(src,1); - if(sd) { - int sp = skill_get_sp(sd->skill_id_old,sd->skill_lv_old); - if( skill_id == SO_SPELLFIST ){ - sc_start4(src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill_get_time(skill_id,skill_lv)); - sd->skill_id_old = sd->skill_lv_old = 0; - break; + case SA_CASTCANCEL: + case SO_SPELLFIST: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + unit_skillcastcancel(src,1); + if(sd) { + int sp = skill->get_sp(sd->skill_id_old,sd->skill_lv_old); + if( skill_id == SO_SPELLFIST ){ + sc_start4(src,type,100,skill_lv+1,skill_lv,sd->skill_id_old,sd->skill_lv_old,skill->get_time(skill_id,skill_lv)); + sd->skill_id_old = sd->skill_lv_old = 0; + break; + } + sp = sp * (90 - (skill_lv-1)*20) / 100; + if(sp < 0) sp = 0; + status_zap(src, 0, sp); } - sp = sp * (90 - (skill_lv-1)*20) / 100; - if(sp < 0) sp = 0; - status_zap(src, 0, sp); - } - break; - case SA_SPELLBREAKER: - { - int sp; - if(tsc && tsc->data[SC_MAGICROD]) { - sp = skill_get_sp(skill_id,skill_lv); - sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; - if(sp < 1) sp = 1; - status_heal(bl,0,sp,2); - status_percent_damage(bl, src, 0, -20, false); //20% max SP damage. - } else { - struct unit_data *ud = unit_bl2ud(bl); - int bl_skill_id=0,bl_skill_lv=0,hp = 0; - if (!ud || ud->skilltimer == INVALID_TIMER) - break; //Nothing to cancel. - bl_skill_id = ud->skill_id; - bl_skill_lv = ud->skill_lv; - if (tstatus->mode & MD_BOSS) - { //Only 10% success chance against bosses. [Skotlex] - if (rnd()%100 < 90) - { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - } else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players. - hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex] + break; + case SA_SPELLBREAKER: + { + int sp; + if(tsc && tsc->data[SC_MAGICROD]) { + sp = skill->get_sp(skill_id,skill_lv); + sp = sp * tsc->data[SC_MAGICROD]->val2 / 100; + if(sp < 1) sp = 1; + status_heal(bl,0,sp,2); + status_percent_damage(bl, src, 0, -20, false); //20% max SP damage. + } else { + struct unit_data *ud = unit_bl2ud(bl); + int bl_skill_id=0,bl_skill_lv=0,hp = 0; + if (!ud || ud->skilltimer == INVALID_TIMER) + break; //Nothing to cancel. + bl_skill_id = ud->skill_id; + bl_skill_lv = ud->skill_lv; + if (tstatus->mode & MD_BOSS) + { //Only 10% success chance against bosses. [Skotlex] + if (rnd()%100 < 90) + { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + } else if (!dstsd || map_flag_vs(bl->m)) //HP damage only on pvp-maps when against players. + hp = tstatus->max_hp/50; //Recover 2% HP [Skotlex] - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - unit_skillcastcancel(bl,0); - sp = skill_get_sp(bl_skill_id,bl_skill_lv); - status_zap(bl, hp, sp); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + unit_skillcastcancel(bl,0); + sp = skill->get_sp(bl_skill_id,bl_skill_lv); + status_zap(bl, hp, sp); - if (hp && skill_lv >= 5) - hp>>=1; //Recover half damaged HP at level 5 [Skotlex] - else - hp = 0; + if (hp && skill_lv >= 5) + hp>>=1; //Recover half damaged HP at level 5 [Skotlex] + else + hp = 0; - if (sp) //Recover some of the SP used - sp = sp*(25*(skill_lv-1))/100; + if (sp) //Recover some of the SP used + sp = sp*(25*(skill_lv-1))/100; - if(hp || sp) - status_heal(src, hp, sp, 2); + if(hp || sp) + status_heal(src, hp, sp, 2); + } } - } - break; - case SA_MAGICROD: - clif_skill_nodamage(src,src,SA_MAGICROD,skill_lv,1); - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - break; - case SA_AUTOSPELL: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if(sd) - clif_autospell(sd,skill_lv); - else { - int maxlv=1,spellid=0; - static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT }; - if(skill_lv >= 10) { - spellid = MG_FROSTDIVER; -// if (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SA_SAGE) -// maxlv = 10; -// else - maxlv = skill_lv - 9; - } - else if(skill_lv >=8) { - spellid = MG_FIREBALL; - maxlv = skill_lv - 7; - } - else if(skill_lv >=5) { - spellid = MG_SOULSTRIKE; - maxlv = skill_lv - 4; - } - else if(skill_lv >=2) { - int i = rnd()%3; - spellid = spellarray[i]; - maxlv = skill_lv - 1; - } - else if(skill_lv > 0) { - spellid = MG_NAPALMBEAT; - maxlv = 3; - } - if(spellid > 0) - sc_start4(src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0, - skill_get_time(SA_AUTOSPELL,skill_lv)); - } - break; + break; + case SA_MAGICROD: + clif->skill_nodamage(src,src,SA_MAGICROD,skill_lv,1); + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + case SA_AUTOSPELL: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(sd) + clif->autospell(sd,skill_lv); + else { + int maxlv=1,spellid=0; + static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT }; + if(skill_lv >= 10) { + spellid = MG_FROSTDIVER; + // if (tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SA_SAGE) + // maxlv = 10; + // else + maxlv = skill_lv - 9; + } + else if(skill_lv >=8) { + spellid = MG_FIREBALL; + maxlv = skill_lv - 7; + } + else if(skill_lv >=5) { + spellid = MG_SOULSTRIKE; + maxlv = skill_lv - 4; + } + else if(skill_lv >=2) { + int i = rnd()%3; + spellid = spellarray[i]; + maxlv = skill_lv - 1; + } + else if(skill_lv > 0) { + spellid = MG_NAPALMBEAT; + maxlv = 3; + } + if(spellid > 0) + sc_start4(src,SC_AUTOSPELL,100,skill_lv,spellid,maxlv,0, + skill->get_time(SA_AUTOSPELL,skill_lv)); + } + break; - case BS_GREED: - if(sd){ - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_greed,bl, - skill_get_splash(skill_id, skill_lv),BL_ITEM,bl); - } - break; + case BS_GREED: + if(sd){ + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->greed,bl, + skill->get_splash(skill_id, skill_lv),BL_ITEM,bl); + } + break; - case SA_ELEMENTWATER: - case SA_ELEMENTFIRE: - case SA_ELEMENTGROUND: - case SA_ELEMENTWIND: - if(sd && !dstmd) //Only works on monsters. - break; - if(tstatus->mode&MD_BOSS) - break; - case NPC_ATTRICHANGE: - case NPC_CHANGEWATER: - case NPC_CHANGEGROUND: - case NPC_CHANGEFIRE: - case NPC_CHANGEWIND: - case NPC_CHANGEPOISON: - case NPC_CHANGEHOLY: - case NPC_CHANGEDARKNESS: - case NPC_CHANGETELEKINESIS: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl, type, 100, skill_lv, skill_get_ele(skill_id,skill_lv), - skill_get_time(skill_id, skill_lv))); - break; - case NPC_CHANGEUNDEAD: - //This skill should fail if target is wearing bathory/evil druid card [Brainstorm] - //TO-DO This is ugly, fix it - if(tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break; - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl, type, 100, skill_lv, skill_get_ele(skill_id,skill_lv), - skill_get_time(skill_id, skill_lv))); - break; + case SA_ELEMENTWATER: + case SA_ELEMENTFIRE: + case SA_ELEMENTGROUND: + case SA_ELEMENTWIND: + if(sd && !dstmd) //Only works on monsters. + break; + if(tstatus->mode&MD_BOSS) + break; + case NPC_ATTRICHANGE: + case NPC_CHANGEWATER: + case NPC_CHANGEGROUND: + case NPC_CHANGEFIRE: + case NPC_CHANGEWIND: + case NPC_CHANGEPOISON: + case NPC_CHANGEHOLY: + case NPC_CHANGEDARKNESS: + case NPC_CHANGETELEKINESIS: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), + skill->get_time(skill_id, skill_lv))); + break; + case NPC_CHANGEUNDEAD: + //This skill should fail if target is wearing bathory/evil druid card [Brainstorm] + //TO-DO This is ugly, fix it + if(tstatus->def_ele==ELE_UNDEAD || tstatus->def_ele==ELE_DARK) break; + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl, type, 100, skill_lv, skill->get_ele(skill_id,skill_lv), + skill->get_time(skill_id, skill_lv))); + break; - case NPC_PROVOCATION: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if (md) mob_unlocktarget(md, tick); - break; + case NPC_PROVOCATION: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (md) mob_unlocktarget(md, tick); + break; - case NPC_KEEPING: - case NPC_BARRIER: - { - int skill_time = skill_get_time(skill_id,skill_lv); - struct unit_data *ud = unit_bl2ud(bl); - if (clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_time)) - && ud) { //Disable attacking/acting/moving for skill's duration. - ud->attackabletime = - ud->canact_tick = - ud->canmove_tick = tick + skill_time; + case NPC_KEEPING: + case NPC_BARRIER: + { + int skill_time = skill->get_time(skill_id,skill_lv); + struct unit_data *ud = unit_bl2ud(bl); + if (clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill_time)) + && ud) { //Disable attacking/acting/moving for skill's duration. + ud->attackabletime = + ud->canact_tick = + ud->canmove_tick = tick + skill_time; + } } - } - break; - - case NPC_REBIRTH: - if( md && md->state.rebirth ) - break; // only works once - sc_start(bl,type,100,skill_lv,-1); - break; + break; - case NPC_DARKBLESSING: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill_get_time2(skill_id,skill_lv))); - break; + case NPC_REBIRTH: + if( md && md->state.rebirth ) + break; // only works once + sc_start(bl,type,100,skill_lv,-1); + break; - case NPC_LICK: - status_zap(bl, 0, 100); - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,(skill_lv*5),skill_lv,skill_get_time2(skill_id,skill_lv))); - break; + case NPC_DARKBLESSING: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,(50+skill_lv*5),skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv))); + break; - case NPC_SUICIDE: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - status_kill(src); //When suiciding, neither exp nor drops is given. - break; + case NPC_LICK: + status_zap(bl, 0, 100); + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,(skill_lv*5),skill_lv,skill->get_time2(skill_id,skill_lv))); + break; - case NPC_SUMMONSLAVE: - case NPC_SUMMONMONSTER: - if(md && md->skill_idx >= 0) - mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv,skill_id); - break; + case NPC_SUICIDE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + status_kill(src); //When suiciding, neither exp nor drops is given. + break; - case NPC_CALLSLAVE: - mob_warpslave(src,MOB_SLAVEDISTANCE); - break; + case NPC_SUMMONSLAVE: + case NPC_SUMMONMONSTER: + if(md && md->skill_idx >= 0) + mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv,skill_id); + break; - case NPC_RANDOMMOVE: - if (md) { - md->next_walktime = tick - 1; - mob_randomwalk(md,tick); - } - break; + case NPC_CALLSLAVE: + mob_warpslave(src,MOB_SLAVEDISTANCE); + break; - case NPC_SPEEDUP: - { - // or does it increase casting rate? just a guess xD - int i = SC_ASPDPOTION0 + skill_lv - 1; - if (i > SC_ASPDPOTION3) - i = SC_ASPDPOTION3; - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,(sc_type)i,100,skill_lv,skill_lv * 60000)); - } - break; + case NPC_RANDOMMOVE: + if (md) { + md->next_walktime = tick - 1; + mob_randomwalk(md,tick); + } + break; - case NPC_REVENGE: - // not really needed... but adding here anyway ^^ - if (md && md->master_id > 0) { - struct block_list *mbl, *tbl; - if ((mbl = map_id2bl(md->master_id)) == NULL || - (tbl = battle_gettargeted(mbl)) == NULL) - break; - md->state.provoke_flag = tbl->id; - mob_target(md, tbl, sstatus->rhw.range); - } - break; + case NPC_SPEEDUP: + { + // or does it increase casting rate? just a guess xD + int i = SC_ASPDPOTION0 + skill_lv - 1; + if (i > SC_ASPDPOTION3) + i = SC_ASPDPOTION3; + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,(sc_type)i,100,skill_lv,skill_lv * 60000)); + } + break; - case NPC_RUN: - { - const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; - uint8 dir = (bl == src)?unit_getdir(src):map_calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away. - unit_stop_attack(src); - //Run skillv tiles overriding the can-move check. - if (unit_walktoxy(src, src->x + skill_lv * mask[dir][0], src->y + skill_lv * mask[dir][1], 2) && md) - md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai. - } - break; + case NPC_REVENGE: + // not really needed... but adding here anyway ^^ + if (md && md->master_id > 0) { + struct block_list *mbl, *tbl; + if ((mbl = map_id2bl(md->master_id)) == NULL || + (tbl = battle->get_targeted(mbl)) == NULL) + break; + md->state.provoke_flag = tbl->id; + mob_target(md, tbl, sstatus->rhw.range); + } + break; - case NPC_TRANSFORMATION: - case NPC_METAMORPHOSIS: - if(md && md->skill_idx >= 0) { - int class_ = mob_random_class (md->db->skill[md->skill_idx].val,0); - if (skill_lv > 1) //Multiply the rest of mobs. [Skotlex] - mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv-1,skill_id); - if (class_) mob_class_change(md, class_); - } - break; + case NPC_RUN: + { + const int mask[8][2] = {{0,-1},{1,-1},{1,0},{1,1},{0,1},{-1,1},{-1,0},{-1,-1}}; + uint8 dir = (bl == src)?unit_getdir(src):map_calc_dir(src,bl->x,bl->y); //If cast on self, run forward, else run away. + unit_stop_attack(src); + //Run skillv tiles overriding the can-move check. + if (unit_walktoxy(src, src->x + skill_lv * mask[dir][0], src->y + skill_lv * mask[dir][1], 2) && md) + md->state.skillstate = MSS_WALK; //Otherwise it isn't updated in the ai. + } + break; - case NPC_EMOTION_ON: - case NPC_EMOTION: - //va[0] is the emotion to use. - //NPC_EMOTION & NPC_EMOTION_ON can change a mob's mode 'permanently' [Skotlex] - //val[1] 'sets' the mode - //val[2] adds to the current mode - //val[3] removes from the current mode - //val[4] if set, asks to delete the previous mode change. - if(md && md->skill_idx >= 0 && tsc) - { - clif_emotion(bl, md->db->skill[md->skill_idx].val[0]); - if(md->db->skill[md->skill_idx].val[4] && tsce) - status_change_end(bl, type, INVALID_TIMER); + case NPC_TRANSFORMATION: + case NPC_METAMORPHOSIS: + if(md && md->skill_idx >= 0) { + int class_ = mob_random_class (md->db->skill[md->skill_idx].val,0); + if (skill_lv > 1) //Multiply the rest of mobs. [Skotlex] + mob_summonslave(md,md->db->skill[md->skill_idx].val,skill_lv-1,skill_id); + if (class_) mob_class_change(md, class_); + } + break; - if(md->db->skill[md->skill_idx].val[1] || md->db->skill[md->skill_idx].val[2]) - sc_start4(src, type, 100, skill_lv, - md->db->skill[md->skill_idx].val[1], - md->db->skill[md->skill_idx].val[2], - md->db->skill[md->skill_idx].val[3], - skill_get_time(skill_id, skill_lv)); - } - break; + case NPC_EMOTION_ON: + case NPC_EMOTION: + //val[0] is the emotion to use. + //NPC_EMOTION & NPC_EMOTION_ON can change a mob's mode 'permanently' [Skotlex] + //val[1] 'sets' the mode + //val[2] adds to the current mode + //val[3] removes from the current mode + //val[4] if set, asks to delete the previous mode change. + if(md && md->skill_idx >= 0 && tsc) { + clif->emotion(bl, md->db->skill[md->skill_idx].val[0]); + if(md->db->skill[md->skill_idx].val[4] && tsce) + status_change_end(bl, type, INVALID_TIMER); - case NPC_POWERUP: - sc_start(bl,SC_INCATKRATE,100,200,skill_get_time(skill_id, skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,100,skill_get_time(skill_id, skill_lv))); - break; + //If mode gets set by NPC_EMOTION then the target should be reset [Playtester] + if(skill_id == NPC_EMOTION && md->db->skill[md->skill_idx].val[1]) + mob_unlocktarget(md,tick); + + if(md->db->skill[md->skill_idx].val[1] || md->db->skill[md->skill_idx].val[2]) + sc_start4(src, type, 100, skill_lv, + md->db->skill[md->skill_idx].val[1], + md->db->skill[md->skill_idx].val[2], + md->db->skill[md->skill_idx].val[3], + skill->get_time(skill_id, skill_lv)); + } + break; - case NPC_AGIUP: - sc_start(bl,SC_SPEEDUP1,100,skill_lv,skill_get_time(skill_id, skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,100,skill_get_time(skill_id, skill_lv))); - break; + case NPC_POWERUP: + sc_start(bl,SC_INCATKRATE,100,200,skill->get_time(skill_id, skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); + break; - case NPC_INVISIBLE: - //Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use). - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,0,0,6,skill_get_time(skill_id,skill_lv))); - break; + case NPC_AGIUP: + sc_start(bl,SC_SPEEDUP1,100,skill_lv,skill->get_time(skill_id, skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,100,skill->get_time(skill_id, skill_lv))); + break; - case NPC_SIEGEMODE: - // not sure what it does - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; + case NPC_INVISIBLE: + //Have val4 passed as 6 is for "infinite cloak" (do not end on attack/skill use). + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,0,0,6,skill->get_time(skill_id,skill_lv))); + break; - case WE_MALE: - { - int hp_rate=(!skill_lv)? 0:skill_db[skill_id].hp_rate[skill_lv-1]; - int gain_hp= tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex] - clif_skill_nodamage(src,bl,skill_id,status_heal(bl, gain_hp, 0, 0),1); - } - break; - case WE_FEMALE: - { - int sp_rate=(!skill_lv)? 0:skill_db[skill_id].sp_rate[skill_lv-1]; - int gain_sp=tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex] - clif_skill_nodamage(src,bl,skill_id,status_heal(bl, 0, gain_sp, 0),1); - } - break; + case NPC_SIEGEMODE: + // not sure what it does + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; - // parent-baby skills - case WE_BABY: - if(sd){ - struct map_session_data *f_sd = pc_get_father(sd); - struct map_session_data *m_sd = pc_get_mother(sd); - // if neither was found - if(!f_sd && !m_sd){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; + case WE_MALE: + { + int hp_rate=(!skill_lv)? 0:skill_db[skill_id].hp_rate[skill_lv-1]; + int gain_hp= tstatus->max_hp*abs(hp_rate)/100; // The earned is the same % of the target HP than it costed the caster. [Skotlex] + clif->skill_nodamage(src,bl,skill_id,status_heal(bl, gain_hp, 0, 0),1); } - status_change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill_get_time2(skill_id,skill_lv),8); - if (f_sd) sc_start(&f_sd->bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - if (m_sd) sc_start(&m_sd->bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - } - break; + break; + case WE_FEMALE: + { + int sp_rate=(!skill_lv)? 0:skill_db[skill_id].sp_rate[skill_lv-1]; + int gain_sp=tstatus->max_sp*abs(sp_rate)/100;// The earned is the same % of the target SP than it costed the caster. [Skotlex] + clif->skill_nodamage(src,bl,skill_id,status_heal(bl, 0, gain_sp, 0),1); + } + break; - case PF_HPCONVERSION: - { - int hp, sp; - hp = sstatus->max_hp/10; - sp = hp * 10 * skill_lv / 100; - if (!status_charge(src,hp,0)) { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + // parent-baby skills + case WE_BABY: + if(sd){ + struct map_session_data *f_sd = pc_get_father(sd); + struct map_session_data *m_sd = pc_get_mother(sd); + // if neither was found + if(!f_sd && !m_sd){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + status_change_start(bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8); + if (f_sd) sc_start(&f_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + if (m_sd) sc_start(&m_sd->bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); } - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - status_heal(bl,0,sp,2); - } - break; + break; - case MA_REMOVETRAP: - case HT_REMOVETRAP: - { - struct skill_unit* su; - struct skill_unit_group* sg; - su = BL_CAST(BL_SKILL, bl); + case PF_HPCONVERSION: + { + int hp, sp; + hp = sstatus->max_hp/10; + sp = hp * 10 * skill_lv / 100; + if (!status_charge(src,hp,0)) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + status_heal(bl,0,sp,2); + } + break; - // Mercenaries can remove any trap - // Players can only remove their own traps or traps on Vs maps. - if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill_get_inf2(sg->skill_id)&INF2_TRAP) ) + case MA_REMOVETRAP: + case HT_REMOVETRAP: { - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) - { // prevent picking up expired traps - if( battle_config.skill_removetrap_type ) - { // get back all items used to deploy the trap - for( i = 0; i < 10; i++ ) - { - if( skill_db[su->group->skill_id].itemid[i] > 0 ) + struct skill_unit* su; + struct skill_unit_group* sg; + su = BL_CAST(BL_SKILL, bl); + + // Mercenaries can remove any trap + // Players can only remove their own traps or traps on Vs maps. + if( su && (sg = su->group) && (src->type == BL_MER || sg->src_id == src->id || map_flag_vs(bl->m)) && (skill->get_inf2(sg->skill_id)&INF2_TRAP) ) + { + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + if( sd && !(sg->unit_id == UNT_USED_TRAPS || (sg->unit_id == UNT_ANKLESNARE && sg->val2 != 0 )) ) + { // prevent picking up expired traps + if( battle_config.skill_removetrap_type ) + { // get back all items used to deploy the trap + for( i = 0; i < 10; i++ ) { - int flag; - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = skill_db[su->group->skill_id].itemid[i]; - item_tmp.identify = 1; - if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) + if( skill_db[su->group->skill_id].itemid[i] > 0 ) { - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + int flag; + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = skill_db[su->group->skill_id].itemid[i]; + item_tmp.identify = 1; + if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,skill_db[su->group->skill_id].amount[i],LOG_TYPE_OTHER)) ) + { + clif->additem(sd,0,0,flag); + map_addflooritem(&item_tmp,skill_db[su->group->skill_id].amount[i],sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } } } } - } - else - { // get back 1 trap - struct item item_tmp; - memset(&item_tmp,0,sizeof(item_tmp)); - item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; - item_tmp.identify = 1; - if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) ) - { - clif_additem(sd,0,0,flag); - map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + else + { // get back 1 trap + struct item item_tmp; + memset(&item_tmp,0,sizeof(item_tmp)); + item_tmp.nameid = su->group->item_id?su->group->item_id:ITEMID_TRAP; + item_tmp.identify = 1; + if( item_tmp.nameid && (flag=pc_additem(sd,&item_tmp,1,LOG_TYPE_OTHER)) ) + { + clif->additem(sd,0,0,flag); + map_addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); + } } } - } - skill_delunit(su); - }else if(sd) - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + skill->delunit(su); + }else if(sd) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - } - break; - case HT_SPRINGTRAP: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - { - struct skill_unit *su=NULL; - if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ - switch(su->group->unit_id){ - case UNT_ANKLESNARE: // ankle snare - if (su->group->val2 != 0) - // if it is already trapping something don't spring it, - // remove trap should be used instead - break; - // otherwise fallthrough to below - case UNT_BLASTMINE: - case UNT_SKIDTRAP: - case UNT_LANDMINE: - case UNT_SHOCKWAVE: - case UNT_SANDMAN: - case UNT_FLASHER: - case UNT_FREEZINGTRAP: - case UNT_CLAYMORETRAP: - case UNT_TALKIEBOX: - su->group->unit_id = UNT_USED_TRAPS; - clif_changetraplook(bl, UNT_USED_TRAPS); - su->group->limit=DIFF_TICK(tick+1500,su->group->tick); - su->limit=DIFF_TICK(tick+1500,su->group->tick); - } } - } - break; - case BD_ENCORE: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if(sd) - unit_skilluse_id(src,src->id,sd->skill_id_dance,sd->skill_lv_dance); - break; - - case AS_SPLASHER: - if(tstatus->mode&MD_BOSS - /** - * Renewal dropped the 3/4 hp requirement - **/ - #ifndef RENEWAL - || tstatus-> hp > tstatus->max_hp*3/4 - #endif - ) { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 1; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill_get_time(skill_id,skill_lv),1000)); -#ifndef RENEWAL - if (sd) skill_blockpc_start (sd, skill_id, skill_get_time(skill_id, skill_lv)+3000); -#endif - break; - - case PF_MINDBREAKER: - { - if(tstatus->mode&MD_BOSS || battle_check_undead(tstatus->race,tstatus->def_ele)) + break; + case HT_SPRINGTRAP: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); { - map_freeblock_unlock(); - return 1; + struct skill_unit *su=NULL; + if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){ + switch(su->group->unit_id){ + case UNT_ANKLESNARE: // ankle snare + if (su->group->val2 != 0) + // if it is already trapping something don't spring it, + // remove trap should be used instead + break; + // otherwise fallthrough to below + case UNT_BLASTMINE: + case UNT_SKIDTRAP: + case UNT_LANDMINE: + case UNT_SHOCKWAVE: + case UNT_SANDMAN: + case UNT_FLASHER: + case UNT_FREEZINGTRAP: + case UNT_CLAYMORETRAP: + case UNT_TALKIEBOX: + su->group->unit_id = UNT_USED_TRAPS; + clif->changetraplook(bl, UNT_USED_TRAPS); + su->group->limit=DIFF_TICK(tick+1500,su->group->tick); + su->limit=DIFF_TICK(tick+1500,su->group->tick); + } + } } + break; + case BD_ENCORE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(sd) + unit_skilluse_id(src,src->id,sd->skill_id_dance,sd->skill_lv_dance); + break; - if (tsce) - { //HelloKitty2 (?) explained that this silently fails when target is - //already inflicted. [Skotlex] + case AS_SPLASHER: + if(tstatus->mode&MD_BOSS + /** + * Renewal dropped the 3/4 hp requirement + **/ + #ifndef RENEWAL + || tstatus-> hp > tstatus->max_hp*3/4 + #endif + ) { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); map_freeblock_unlock(); return 1; } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,skill_id,src->id,skill->get_time(skill_id,skill_lv),1000)); + #ifndef RENEWAL + if (sd) skill->blockpc_start (sd, skill_id, skill->get_time(skill_id, skill_lv)+3000, false); + #endif + break; - //Has a 55% + skill_lv*5% success chance. - if (!clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,55+5*skill_lv,skill_lv,skill_get_time(skill_id,skill_lv)))) + case PF_MINDBREAKER: { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; - } + if(tstatus->mode&MD_BOSS || battle->check_undead(tstatus->race,tstatus->def_ele) ) { + map_freeblock_unlock(); + return 1; + } - unit_skillcastcancel(bl,0); + if (tsce) + { //HelloKitty2 (?) explained that this silently fails when target is + //already inflicted. [Skotlex] + map_freeblock_unlock(); + return 1; + } - if(tsc && tsc->count){ - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - } + //Has a 55% + skill_lv*5% success chance. + if (!clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,55+5*skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)))) + { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } - if(dstmd) - mob_target(dstmd,src,skill_get_range2(src,skill_id,skill_lv)); - } - break; + unit_skillcastcancel(bl,0); - case PF_SOULCHANGE: - { - unsigned int sp1 = 0, sp2 = 0; - if (dstmd) { - if (dstmd->state.soul_change_flag) { - if(sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if(tsc && tsc->count){ + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + if(tsc->data[SC_STONE] && tsc->opt1 == OPT1_STONE) + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_SLEEP, INVALID_TIMER); } - dstmd->state.soul_change_flag = 1; - sp2 = sstatus->max_sp * 3 /100; - status_heal(src, 0, sp2, 2); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; + + if(dstmd) + mob_target(dstmd,src,skill->get_range2(src,skill_id,skill_lv)); } - sp1 = sstatus->sp; - sp2 = tstatus->sp; - #ifdef RENEWAL - sp1 = sp1 / 2; - sp2 = sp2 / 2; - if( tsc && tsc->data[SC_EXTREMITYFIST2] ) - sp1 = tstatus->sp; - #endif - status_set_sp(src, sp2, 3); - status_set_sp(bl, sp1, 3); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + break; - // Slim Pitcher - case CR_SLIMPITCHER: - // Updated to block Slim Pitcher from working on barricades and guardian stones. - if( dstmd && (dstmd->class_ == MOBID_EMPERIUM || (dstmd->class_ >= MOBID_BARRICADE1 && dstmd->class_ <= MOBID_GUARIDAN_STONE2)) ) + case PF_SOULCHANGE: + { + unsigned int sp1 = 0, sp2 = 0; + if (dstmd) { + if (dstmd->state.soul_change_flag) { + if(sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + dstmd->state.soul_change_flag = 1; + sp2 = sstatus->max_sp * 3 /100; + status_heal(src, 0, sp2, 2); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + } + sp1 = sstatus->sp; + sp2 = tstatus->sp; + #ifdef RENEWAL + sp1 = sp1 / 2; + sp2 = sp2 / 2; + if( tsc && tsc->data[SC_EXTREMITYFIST2] ) + sp1 = tstatus->sp; + #endif + status_set_sp(src, sp2, 3); + status_set_sp(bl, sp1, 3); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } break; - if (potion_hp || potion_sp) { - int hp = potion_hp, sp = potion_sp; - hp = hp * (100 + (tstatus->vit<<1))/100; - sp = sp * (100 + (tstatus->int_<<1))/100; - if (dstsd) { - if (hp) - hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10 + pc_skillheal2_bonus(dstsd, skill_id))/100; - if (sp) - sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10 + pc_skillheal2_bonus(dstsd, skill_id))/100; - } - if( tsc && tsc->count ) { - if (tsc->data[SC_CRITICALWOUND]) { - hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; - } - if (tsc->data[SC_DEATHHURT]) { - hp -= hp * 20 / 100; - sp -= sp * 20 / 100; - } - if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2) { - hp += hp / 10; - sp += sp / 10; - } - } - if(hp > 0) - clif_skill_nodamage(NULL,bl,AL_HEAL,hp,1); - if(sp > 0) - clif_skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); - status_heal(bl,hp,sp,0); - } - break; - // Full Chemical Protection - case CR_FULLPROTECTION: - { - unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; - int i, s = 0, skilltime = skill_get_time(skill_id,skill_lv); - for (i=0 ; i<4; i++) { - if( bl->type != BL_PC || ( dstsd && pc_checkequip(dstsd,equip[i]) < 0 ) ) - continue; - sc_start(bl,(sc_type)(SC_CP_WEAPON + i),100,skill_lv,skilltime); - s++; + // Slim Pitcher + case CR_SLIMPITCHER: + // Updated to block Slim Pitcher from working on barricades and guardian stones. + if( dstmd && (dstmd->class_ == MOBID_EMPERIUM || (dstmd->class_ >= MOBID_BARRICADE1 && dstmd->class_ <= MOBID_GUARIDAN_STONE2)) ) + break; + if (potion_hp || potion_sp) { + int hp = potion_hp, sp = potion_sp; + hp = hp * (100 + (tstatus->vit<<1))/100; + sp = sp * (100 + (tstatus->int_<<1))/100; + if (dstsd) { + if (hp) + hp = hp * (100 + pc_checkskill(dstsd,SM_RECOVERY)*10 + pc_skillheal2_bonus(dstsd, skill_id))/100; + if (sp) + sp = sp * (100 + pc_checkskill(dstsd,MG_SRECOVERY)*10 + pc_skillheal2_bonus(dstsd, skill_id))/100; + } + if( tsc && tsc->count ) { + if (tsc->data[SC_CRITICALWOUND]) { + hp -= hp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + sp -= sp * tsc->data[SC_CRITICALWOUND]->val2 / 100; + } + if (tsc->data[SC_DEATHHURT]) { + hp -= hp * 20 / 100; + sp -= sp * 20 / 100; + } + if( tsc->data[SC_WATER_INSIGNIA] && tsc->data[SC_WATER_INSIGNIA]->val1 == 2) { + hp += hp / 10; + sp += sp / 10; + } + } + if(hp > 0) + clif->skill_nodamage(NULL,bl,AL_HEAL,hp,1); + if(sp > 0) + clif->skill_nodamage(NULL,bl,MG_SRECOVERY,sp,1); + status_heal(bl,hp,sp,0); } - if( sd && !s ){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); // Don't consume item requirements - return 0; + break; + // Full Chemical Protection + case CR_FULLPROTECTION: + { + unsigned int equip[] = {EQP_WEAPON, EQP_SHIELD, EQP_ARMOR, EQP_HEAD_TOP}; + int i, s = 0, skilltime = skill->get_time(skill_id,skill_lv); + + for (i=0 ; i<4; i++) { + if( bl->type != BL_PC || ( dstsd && pc_checkequip(dstsd,equip[i]) < 0 ) ) + continue; + sc_start(bl,(sc_type)(SC_CP_WEAPON + i),100,skill_lv,skilltime); + s++; + } + if( sd && !s ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); // Don't consume item requirements + return 0; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + break; - case RG_CLEANER: //AppleGirl - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; + case RG_CLEANER: //AppleGirl + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; - case CG_LONGINGFREEDOM: - { - if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 - && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] + case CG_LONGINGFREEDOM: { - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); + if (tsc && !tsce && (tsce=tsc->data[SC_DANCING]) && tsce->val4 + && (tsce->val1&0xFFFF) != CG_MOONLIT) //Can't use Longing for Freedom while under Moonlight Petals. [Skotlex] + { + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + } } - } - break; + break; - case CG_TAROTCARD: - { - int eff, count = -1; - if( rnd() % 100 > skill_lv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) ) + case CG_TAROTCARD: { - if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - - map_freeblock_unlock(); - return 0; - } - status_zap(src,0,skill_db[skill_get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] - do { - eff = rnd() % 14; - clif_specialeffect(bl, 523 + eff, AREA); - switch (eff) + int eff, count = -1; + if( rnd() % 100 > skill_lv * 8 || (dstmd && ((dstmd->guardian_data && dstmd->class_ == MOBID_EMPERIUM) || mob_is_battleground(dstmd))) ) { - case 0: // heals SP to 0 - status_percent_damage(src, bl, 0, 100, false); - break; - case 1: // matk halved - sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skill_id,skill_lv)); - break; - case 2: // all buffs removed - status_change_clear_buffs(bl,1); - break; - case 3: // 1000 damage, random armor destroyed - { - int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; - status_fix_damage(src, bl, 1000, 0); - clif_damage(src,bl,tick,0,0,1000,0,0,0); - if( !status_isdead(bl) ) - skill_break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); - } - break; - case 4: // atk halved - sc_start(bl,SC_INCATKRATE,100,-50,skill_get_time2(skill_id,skill_lv)); - break; - case 5: // 2000HP heal, random teleported - status_heal(src, 2000, 0, 0); - if( !map_flag_vs(bl->m) ) - unit_warp(bl, -1,-1,-1, CLR_TELEPORT); - break; - case 6: // random 2 other effects - if (count == -1) - count = 3; - else - count++; //Should not retrigger this one. - break; - case 7: // stop freeze or stoned + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + + map_freeblock_unlock(); + return 0; + } + status_zap(src,0,skill_db[skill->get_index(skill_id)].sp[skill_lv]); // consume sp only if succeeded [Inkfish] + do { + eff = rnd() % 14; + clif->specialeffect(bl, 523 + eff, AREA); + switch (eff) { - enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; - sc_start(bl,sc[rnd()%3],100,skill_lv,skill_get_time2(skill_id,skill_lv)); + case 0: // heals SP to 0 + status_percent_damage(src, bl, 0, 100, false); + break; + case 1: // matk halved + sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + break; + case 2: // all buffs removed + status_change_clear_buffs(bl,1); + break; + case 3: // 1000 damage, random armor destroyed + { + status_fix_damage(src, bl, 1000, 0); + clif->damage(src,bl,tick,0,0,1000,0,0,0); + if( !status_isdead(bl) ) { + int where[] = { EQP_ARMOR, EQP_SHIELD, EQP_HELM, EQP_SHOES, EQP_GARMENT }; + skill->break_equip(bl, where[rnd()%5], 10000, BCT_ENEMY); + } + } + break; + case 4: // atk halved + sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + break; + case 5: // 2000HP heal, random teleported + status_heal(src, 2000, 0, 0); + if( !map_flag_vs(bl->m) ) + unit_warp(bl, -1,-1,-1, CLR_TELEPORT); + break; + case 6: // random 2 other effects + if (count == -1) + count = 3; + else + count++; //Should not retrigger this one. + break; + case 7: // stop freeze or stoned + { + enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE }; + sc_start(bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv)); + } + break; + case 8: // curse coma and poison + sc_start(bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case 9: // confusion + sc_start(bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; + case 10: // 6666 damage, atk matk halved, cursed + status_fix_damage(src, bl, 6666, 0); + clif->damage(src,bl,tick,0,0,6666,0,0,0); + sc_start(bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv)); + break; + case 11: // 4444 damage + status_fix_damage(src, bl, 4444, 0); + clif->damage(src,bl,tick,0,0,4444,0,0,0); + break; + case 12: // stun + sc_start(bl,SC_STUN,100,skill_lv,5000); + break; + case 13: // atk,matk,hit,flee,def reduced + sc_start(bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCFLEERATE,100,-20,skill->get_time2(skill_id,skill_lv)); + sc_start(bl,SC_INCDEFRATE,100,-20,skill->get_time2(skill_id,skill_lv)); + break; + default: + break; } - break; - case 8: // curse coma and poison - sc_start(bl,SC_COMA,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_CURSE,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_POISON,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case 9: // confusion - sc_start(bl,SC_CONFUSION,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; - case 10: // 6666 damage, atk matk halved, cursed - status_fix_damage(src, bl, 6666, 0); - clif_damage(src,bl,tick,0,0,6666,0,0,0); - sc_start(bl,SC_INCATKRATE,100,-50,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCMATKRATE,100,-50,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_CURSE,skill_lv,100,skill_get_time2(skill_id,skill_lv)); - break; - case 11: // 4444 damage - status_fix_damage(src, bl, 4444, 0); - clif_damage(src,bl,tick,0,0,4444,0,0,0); - break; - case 12: // stun - sc_start(bl,SC_STUN,100,skill_lv,5000); - break; - case 13: // atk,matk,hit,flee,def reduced - sc_start(bl,SC_INCATKRATE,100,-20,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCMATKRATE,100,-20,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCHITRATE,100,-20,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCFLEERATE,100,-20,skill_get_time2(skill_id,skill_lv)); - sc_start(bl,SC_INCDEFRATE,100,-20,skill_get_time2(skill_id,skill_lv)); - break; - default: - break; - } - } while ((--count) > 0); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; - - case SL_ALCHEMIST: - case SL_ASSASIN: - case SL_BARDDANCER: - case SL_BLACKSMITH: - case SL_CRUSADER: - case SL_HUNTER: - case SL_KNIGHT: - case SL_MONK: - case SL_PRIEST: - case SL_ROGUE: - case SL_SAGE: - case SL_SOULLINKER: - case SL_STAR: - case SL_SUPERNOVICE: - case SL_WIZARD: - //NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SPIRIT constant. - if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) - { //Erase death count 1% of the casts - dstsd->die_counter = 0; - pc_setglobalreg(dstsd,"PC_DIE_COUNTER", 0); - clif_specialeffect(bl, 0x152, AREA); - //SC_SPIRIT invokes status_calc_pc for us. - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,SC_SPIRIT,100,skill_lv,skill_id,0,0,skill_get_time(skill_id,skill_lv))); - sc_start(src,SC_SMA,100,skill_lv,skill_get_time(SL_SMA,skill_lv)); - break; - case SL_HIGH: - if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } while ((--count) > 0); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } break; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start4(bl,type,100,skill_lv,skill_id,0,0,skill_get_time(skill_id,skill_lv))); - sc_start(src,SC_SMA,100,skill_lv,skill_get_time(SL_SMA,skill_lv)); - break; - case SL_SWOO: - if (tsce) { - if(sd) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,10000,8); - status_change_end(bl, SC_SWOO, INVALID_TIMER); + case SL_ALCHEMIST: + case SL_ASSASIN: + case SL_BARDDANCER: + case SL_BLACKSMITH: + case SL_CRUSADER: + case SL_HUNTER: + case SL_KNIGHT: + case SL_MONK: + case SL_PRIEST: + case SL_ROGUE: + case SL_SAGE: + case SL_SOULLINKER: + case SL_STAR: + case SL_SUPERNOVICE: + case SL_WIZARD: + //NOTE: here, 'type' has the value of the associated MAPID, not of the SC_SPIRIT constant. + if (sd && !(dstsd && (dstsd->class_&MAPID_UPPERMASK) == type)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) + { //Erase death count 1% of the casts + dstsd->die_counter = 0; + pc_setglobalreg(dstsd,"PC_DIE_COUNTER", 0); + clif->specialeffect(bl, 0x152, AREA); + //SC_SPIRIT invokes status_calc_pc for us. + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,SC_SPIRIT,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; - } - case SL_SKA: // [marquis007] - case SL_SKE: - if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); + case SL_HIGH: + if (sd && !(dstsd && (dstsd->class_&JOBL_UPPER) && !(dstsd->class_&JOBL_2) && dstsd->status.base_level < 70)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start4(bl,type,100,skill_lv,skill_id,0,0,skill->get_time(skill_id,skill_lv))); + sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); break; - } - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - if (skill_id == SL_SKE) - sc_start(src,SC_SMA,100,skill_lv,skill_get_time(SL_SMA,skill_lv)); - break; - // New guild skills [Celest] - case GD_BATTLEORDER: - if(flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id, skill_lv)); - } else if (status_get_guild_id(src)) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skill_id, skill_lv), BL_PC, - src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, - skill_castend_nodamage_id); - if (sd) - guild_block_skill(sd,skill_get_time2(skill_id,skill_lv)); - } - break; - case GD_REGENERATION: - if(flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id, skill_lv)); - } else if (status_get_guild_id(src)) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skill_id, skill_lv), BL_PC, - src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, - skill_castend_nodamage_id); - if (sd) - guild_block_skill(sd,skill_get_time2(skill_id,skill_lv)); - } - break; - case GD_RESTORE: - if(flag&1) { - if (status_get_guild_id(src) == status_get_guild_id(bl)) - clif_skill_nodamage(src,bl,AL_HEAL,status_percent_heal(bl,90,90),1); - } else if (status_get_guild_id(src)) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skill_id, skill_lv), BL_PC, - src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, - skill_castend_nodamage_id); - if (sd) - guild_block_skill(sd,skill_get_time2(skill_id,skill_lv)); - } - break; - case GD_EMERGENCYCALL: - { - int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0}; - int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0}; - int j = 0; - struct guild *g = NULL; - // i don't know if it actually summons in a circle, but oh well. ;P - g = sd?sd->state.gmaster_flag:guild_search(status_get_guild_id(src)); - if (!g) + case SL_SWOO: + if (tsce) { + if(sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,10000,8); + status_change_end(bl, SC_SWOO, INVALID_TIMER); break; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - for(i = 0; i < g->max_member; i++, j++) { - if (j>8) j=0; - if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { - if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m)) - continue; - if(map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH)) - dx[j] = dy[j] = 0; - pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN); + } + case SL_SKA: // [marquis007] + case SL_SKE: + if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + status_change_start(src,SC_STUN,10000,skill_lv,0,0,0,500,10); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if (skill_id == SL_SKE) + sc_start(src,SC_SMA,100,skill_lv,skill->get_time(SL_SMA,skill_lv)); + break; + + // New guild skills [Celest] + case GD_BATTLEORDER: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); + } else if (status_get_guild_id(src)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id, skill_lv), BL_PC, + src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, + skill->castend_nodamage_id); + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); + } + break; + case GD_REGENERATION: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id, skill_lv)); + } else if (status_get_guild_id(src)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id, skill_lv), BL_PC, + src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, + skill->castend_nodamage_id); + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); + } + break; + case GD_RESTORE: + if(flag&1) { + if (status_get_guild_id(src) == status_get_guild_id(bl)) + clif->skill_nodamage(src,bl,AL_HEAL,status_percent_heal(bl,90,90),1); + } else if (status_get_guild_id(src)) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id, skill_lv), BL_PC, + src,skill_id,skill_lv,tick, flag|BCT_GUILD|1, + skill->castend_nodamage_id); + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); + } + break; + case GD_EMERGENCYCALL: + { + int dx[9]={-1, 1, 0, 0,-1, 1,-1, 1, 0}; + int dy[9]={ 0, 0, 1,-1, 1,-1,-1, 1, 0}; + int j = 0; + struct guild *g; + // i don't know if it actually summons in a circle, but oh well. ;P + g = sd?sd->state.gmaster_flag:guild->search(status_get_guild_id(src)); + if (!g) + break; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + for(i = 0; i < g->max_member; i++, j++) { + if (j>8) j=0; + if ((dstsd = g->member[i].sd) != NULL && sd != dstsd && !dstsd->state.autotrade && !pc_isdead(dstsd)) { + if (map[dstsd->bl.m].flag.nowarp && !map_flag_gvg2(dstsd->bl.m)) + continue; + if(map_getcell(src->m,src->x+dx[j],src->y+dy[j],CELL_CHKNOREACH)) + dx[j] = dy[j] = 0; + pc_setpos(dstsd, map_id2index(src->m), src->x+dx[j], src->y+dy[j], CLR_RESPAWN); + } } + if (sd) + guild->block_skill(sd,skill->get_time2(skill_id,skill_lv)); } - if (sd) - guild_block_skill(sd,skill_get_time2(skill_id,skill_lv)); - } - break; + break; - case SG_FEEL: - //AuronX reported you CAN memorize the same map as all three. [Skotlex] - if (sd) { - if(!sd->feel_map[skill_lv-1].index) - clif_feel_req(sd->fd,sd, skill_lv); - else - clif_feel_info(sd, skill_lv-1, 1); - } - break; + case SG_FEEL: + //AuronX reported you CAN memorize the same map as all three. [Skotlex] + if (sd) { + if(!sd->feel_map[skill_lv-1].index) + clif->feel_req(sd->fd,sd, skill_lv); + else + clif->feel_info(sd, skill_lv-1, 1); + } + break; - case SG_HATE: - if (sd) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if (!pc_set_hate_mob(sd, skill_lv-1, bl)) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; + case SG_HATE: + if (sd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if (!pc_set_hate_mob(sd, skill_lv-1, bl)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + break; - case GS_GLITTERING: - if(sd) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if(rnd()%100 < (20+10*skill_lv)) - pc_addspiritball(sd,skill_get_time(skill_id,skill_lv),10); - else if(sd->spiritball > 0) - pc_delspiritball(sd,1,0); - } - break; + case GS_GLITTERING: + if(sd) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if(rnd()%100 < (20+10*skill_lv)) + pc_addspiritball(sd,skill->get_time(skill_id,skill_lv),10); + else if(sd->spiritball > 0) + pc_delspiritball(sd,1,0); + } + break; - case GS_CRACKER: - /* per official standards, this skill works on players and mobs. */ - if (sd && (dstsd || dstmd)) - { - i =65 -5*distance_bl(src,bl); //Base rate - if (i < 30) i = 30; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - sc_start(bl,SC_STUN, i,skill_lv,skill_get_time2(skill_id,skill_lv)); - } - break; + case GS_CRACKER: + /* per official standards, this skill works on players and mobs. */ + if (sd && (dstsd || dstmd)) + { + i =65 -5*distance_bl(src,bl); //Base rate + if (i < 30) i = 30; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + sc_start(bl,SC_STUN, i,skill_lv,skill->get_time2(skill_id,skill_lv)); + } + break; - case AM_CALLHOMUN: //[orn] - if (sd && !merc_call_homunculus(sd)) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case AM_CALLHOMUN: //[orn] + if (sd && homun->call(sd)) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; - case AM_REST: - if (sd) { - if (merc_hom_vaporize(sd,1)) - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - else - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; + case AM_REST: + if (sd) { + if (homun->vaporize(sd,1)) + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + break; - case HAMI_CASTLE: //[orn] - if(rnd()%100 < 20*skill_lv && src != bl) - { - int x,y; - x = src->x; - y = src->y; - if (hd) - skill_blockhomun_start(hd, skill_id, skill_get_time2(skill_id,skill_lv)); + case HAMI_CASTLE: //[orn] + if(rnd()%100 < 20*skill_lv && src != bl) + { + int x,y; + x = src->x; + y = src->y; + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); - if (unit_movepos(src,bl->x,bl->y,0,0)) { - clif_skill_nodamage(src,src,skill_id,skill_lv,1); // Homunc - clif_slide(src,bl->x,bl->y) ; - if (unit_movepos(bl,x,y,0,0)) - { - clif_skill_nodamage(bl,bl,skill_id,skill_lv,1); // Master - clif_slide(bl,x,y) ; - } + if (unit_movepos(src,bl->x,bl->y,0,0)) { + clif->skill_nodamage(src,src,skill_id,skill_lv,1); // Homunc + clif->slide(src,bl->x,bl->y) ; + if (unit_movepos(bl,x,y,0,0)) + { + clif->skill_nodamage(bl,bl,skill_id,skill_lv,1); // Master + clif->slide(bl,x,y) ; + } - //TODO: Shouldn't also players and the like switch targets? - map_foreachinrange(skill_chastle_mob_changetarget,src, - AREA_SIZE, BL_MOB, bl, src); + //TODO: Shouldn't also players and the like switch targets? + map_foreachinrange(skill->chastle_mob_changetarget,src, + AREA_SIZE, BL_MOB, bl, src); + } } - } - // Failed - else if (hd && hd->master) - clif_skill_fail(hd->master, skill_id, USESKILL_FAIL_LEVEL, 0); - else if (sd) - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; - case HVAN_CHAOTIC: //[orn] - { - static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}}; - int r = rnd()%100; - i = (skill_lv-1)%5; - if(r<per[i][0]) //Self - bl = src; - else if(r<per[i][1]) //Master - bl = battle_get_master(src); - else //Enemy - bl = map_id2bl(battle_gettarget(src)); - - if (!bl) bl = src; - i = skill_calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true); - //Eh? why double skill packet? - clif_skill_nodamage(src,bl,AL_HEAL,i,1); - clif_skill_nodamage(src,bl,skill_id,i,1); - status_heal(bl, i, 0, 0); - } - break; - //Homun single-target support skills [orn] - case HAMI_BLOODLUST: - case HFLI_FLEET: - case HFLI_SPEED: - case HLIF_CHANGE: - case MH_ANGRIFFS_MODUS: - case MH_GOLDENE_FERSE: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - if (hd) - skill_blockhomun_start(hd, skill_id, skill_get_time2(skill_id,skill_lv)); - break; + // Failed + else if (hd && hd->master) + clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_LEVEL, 0); + else if (sd) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; + case HVAN_CHAOTIC: //[orn] + { + static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}}; + int r = rnd()%100; + i = (skill_lv-1)%5; + if(r<per[i][0]) //Self + bl = src; + else if(r<per[i][1]) //Master + bl = battle->get_master(src); + else //Enemy + bl = map_id2bl(battle->get_target(src)); + + if (!bl) bl = src; + i = skill->calc_heal(src, bl, skill_id, 1+rnd()%skill_lv, true); + //Eh? why double skill packet? + clif->skill_nodamage(src,bl,AL_HEAL,i,1); + clif->skill_nodamage(src,bl,skill_id,i,1); + status_heal(bl, i, 0, 0); + } + break; + //Homun single-target support skills [orn] + case HAMI_BLOODLUST: + case HFLI_FLEET: + case HFLI_SPEED: + case HLIF_CHANGE: + case MH_ANGRIFFS_MODUS: + case MH_GOLDENE_FERSE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_time2(skill_id,skill_lv)); + break; - case NPC_DRAGONFEAR: - if (flag&1) { - const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLEEDING }; - int j; - j = i = rnd()%ARRAYLENGTH(sc); - while ( !sc_start2(bl,sc[i],100,skill_lv,src->id,skill_get_time2(skill_id,i+1)) ) { - i++; - if ( i == ARRAYLENGTH(sc) ) - i = 0; - if (i == j) - break; + case NPC_DRAGONFEAR: + if (flag&1) { + const enum sc_type sc[] = { SC_STUN, SC_SILENCE, SC_CONFUSION, SC_BLEEDING }; + int j; + j = i = rnd()%ARRAYLENGTH(sc); + while ( !sc_start2(bl,sc[i],100,skill_lv,src->id,skill->get_time2(skill_id,i+1)) ) { + i++; + if ( i == ARRAYLENGTH(sc) ) + i = 0; + if (i == j) + break; + } + break; + } + case NPC_WIDEBLEEDING: + case NPC_WIDECONFUSE: + case NPC_WIDECURSE: + case NPC_WIDEFREEZE: + case NPC_WIDESLEEP: + case NPC_WIDESILENCE: + case NPC_WIDESTONE: + case NPC_WIDESTUN: + case NPC_SLOWCAST: + case NPC_WIDEHELLDIGNITY: + if (flag&1) + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time2(skill_id,skill_lv)); + else { + skill_area_temp[2] = 0; //For SD_PREAMBLE + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, + skill->castend_nodamage_id); } break; - } - case NPC_WIDEBLEEDING: - case NPC_WIDECONFUSE: - case NPC_WIDECURSE: - case NPC_WIDEFREEZE: - case NPC_WIDESLEEP: - case NPC_WIDESILENCE: - case NPC_WIDESTONE: - case NPC_WIDESTUN: - case NPC_SLOWCAST: - case NPC_WIDEHELLDIGNITY: - if (flag&1) - sc_start2(bl,type,100,skill_lv,src->id,skill_get_time2(skill_id,skill_lv)); - else { - skill_area_temp[2] = 0; //For SD_PREAMBLE - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skill_id, skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, - skill_castend_nodamage_id); - } - break; - case NPC_WIDESOULDRAIN: - if (flag&1) - status_percent_damage(src,bl,0,((skill_lv-1)%5+1)*20,false); - else { - skill_area_temp[2] = 0; //For SD_PREAMBLE - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub, bl, - skill_get_splash(skill_id, skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, - skill_castend_nodamage_id); - } - break; - case ALL_PARTYFLEE: - if( sd && !(flag&1) ) - { - if( !sd->status.party_id ) + case NPC_WIDESOULDRAIN: + if (flag&1) + status_percent_damage(src,bl,0,((skill_lv-1)%5+1)*20,false); + else { + skill_area_temp[2] = 0; //For SD_PREAMBLE + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub, bl, + skill->get_splash(skill_id, skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick, flag|BCT_ENEMY|SD_PREAMBLE|1, + skill->castend_nodamage_id); + } + break; + case ALL_PARTYFLEE: + if( sd && !(flag&1) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( !sd->status.party_id ) + { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); } - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } - else - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - break; - case NPC_TALK: - case ALL_WEWISH: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; - case ALL_BUYING_STORE: - if( sd ) - {// players only, skill allows 5 buying slots - clif_skill_nodamage(src, bl, skill_id, skill_lv, buyingstore_setup(sd, MAX_BUYINGSTORE_SLOTS)); - } - break; - case RK_ENCHANTBLADE: - clif_skill_nodamage(src,bl,skill_id,skill_lv,// formula not confirmed - sc_start2(bl,type,100,skill_lv,100+20*skill_lv/*+sstatus->int_/2+status_get_lv(bl)/10*/,skill_get_time(skill_id,skill_lv))); - break; - case RK_DRAGONHOWLING: - if( flag&1) - sc_start(bl,type,50 + 6 * skill_lv,skill_lv,skill_get_time(skill_id,skill_lv)); - else - { - skill_area_temp[2] = 0; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub, src, - skill_get_splash(skill_id,skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1, - skill_castend_nodamage_id); - } - break; - case RK_IGNITIONBREAK: - case LG_EARTHDRIVE: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - i = skill_get_splash(skill_id,skill_lv); - if( skill_id == LG_EARTHDRIVE ) { - int dummy = 1; - map_foreachinarea(skill_cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src); + else + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + break; + case NPC_TALK: + case ALL_WEWISH: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; + case ALL_BUYING_STORE: + if( sd ) + {// players only, skill allows 5 buying slots + clif->skill_nodamage(src, bl, skill_id, skill_lv, buyingstore->setup(sd, MAX_BUYINGSTORE_SLOTS)); } - map_foreachinrange(skill_area_sub, bl,i,BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; - case RK_STONEHARDSKIN: - if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 4 ) - { - int heal = sstatus->hp / 4; // 25% HP - if( status_charge(bl,heal,0) ) - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(bl,type,100,skill_lv,heal,skill_get_time(skill_id,skill_lv))); + break; + case RK_ENCHANTBLADE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,// formula not confirmed + sc_start2(bl,type,100,skill_lv,100+20*skill_lv/*+sstatus->int_/2+status_get_lv(bl)/10*/,skill->get_time(skill_id,skill_lv))); + break; + case RK_DRAGONHOWLING: + if( flag&1) + sc_start(bl,type,50 + 6 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); else - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; - case RK_REFRESH: - if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 8 ) - { - int heal = status_get_max_hp(bl) * 25 / 100; - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - status_heal(bl,heal,0,1); - status_change_clear_buffs(bl,4); - } - break; + { + skill_area_temp[2] = 0; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub, src, + skill->get_splash(skill_id,skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|1, + skill->castend_nodamage_id); + } + break; + case RK_IGNITIONBREAK: + case LG_EARTHDRIVE: + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + i = skill->get_splash(skill_id,skill_lv); + if( skill_id == LG_EARTHDRIVE ) { + int dummy = 1; + map_foreachinarea(skill->cell_overlap, src->m, src->x-i, src->y-i, src->x+i, src->y+i, BL_SKILL, LG_EARTHDRIVE, &dummy, src); + } + map_foreachinrange(skill->area_sub, bl,i,BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + break; + case RK_STONEHARDSKIN: + if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 4 ) + { + int heal = sstatus->hp / 4; // 25% HP + if( status_charge(bl,heal,0) ) + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start2(bl,type,100,skill_lv,heal,skill->get_time(skill_id,skill_lv))); + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + break; + case RK_REFRESH: + if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 8 ) + { + int heal = status_get_max_hp(bl) * 25 / 100; + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + status_heal(bl,heal,0,1); + status_change_clear_buffs(bl,4); + } + break; - case RK_MILLENNIUMSHIELD: - if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 9 ) - { - 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_skill_nodamage(src,bl,skill_id,1,1); - } - break; + case RK_MILLENNIUMSHIELD: + if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 9 ) + { + 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->skill_nodamage(src,bl,skill_id,1,1); + } + break; - case RK_GIANTGROWTH: - case RK_VITALITYACTIVATION: - case RK_ABUNDANCE: - case RK_CRUSHSTRIKE: - if( sd ) - { - int lv = 1; // RK_GIANTGROWTH - if( skill_id == RK_VITALITYACTIVATION ) - lv = 2; - else if( skill_id == RK_ABUNDANCE ) - lv = 6; - else if( skill_id == RK_CRUSHSTRIKE ) - lv = 7; - if( pc_checkskill(sd,RK_RUNEMASTERY) >= lv ) - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - } - break; + case RK_GIANTGROWTH: + case RK_VITALITYACTIVATION: + case RK_ABUNDANCE: + case RK_CRUSHSTRIKE: + if( sd ) + { + int lv = 1; // RK_GIANTGROWTH + if( skill_id == RK_VITALITYACTIVATION ) + lv = 2; + else if( skill_id == RK_ABUNDANCE ) + lv = 6; + else if( skill_id == RK_CRUSHSTRIKE ) + lv = 7; + if( pc_checkskill(sd,RK_RUNEMASTERY) >= lv ) + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + } + break; - case RK_FIGHTINGSPIRIT: - if( flag&1 ) { - if( src == bl ) - sc_start2(bl,type,100,skill_area_temp[5],10*(sd?pc_checkskill(sd,RK_RUNEMASTERY):10),skill_get_time(skill_id,skill_lv)); - else - sc_start(bl,type,100,skill_area_temp[5]/4,skill_get_time(skill_id,skill_lv)); - } else if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 5 ) { - if( sd->status.party_id ) { - i = party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill_area_sub_count); - skill_area_temp[5] = 7 * i; // ATK - party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id); - } else - sc_start2(bl,type,100,7,5,skill_get_time(skill_id,skill_lv)); - } - clif_skill_nodamage(src,bl,skill_id,1,1); - break; - /** - * Guilotine Cross - **/ - case GC_ROLLINGCUTTER: - { - short count = 1; - skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill_castend_damage_id); - if( tsc && tsc->data[SC_ROLLINGCUTTER] ) - { // Every time the skill is casted the status change is reseted adding a counter. - count += (short)tsc->data[SC_ROLLINGCUTTER]->val1; - if( count > 10 ) - count = 10; // Max coounter - status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); - } - sc_start(bl,SC_ROLLINGCUTTER,100,count,skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - } - break; + case RK_FIGHTINGSPIRIT: + if( flag&1 ) { + if( src == bl ) + sc_start2(bl,type,100,skill_area_temp[5],10*(sd?pc_checkskill(sd,RK_RUNEMASTERY):10),skill->get_time(skill_id,skill_lv)); + else + sc_start(bl,type,100,skill_area_temp[5]/4,skill->get_time(skill_id,skill_lv)); + } else if( sd && pc_checkskill(sd,RK_RUNEMASTERY) >= 5 ) { + if( sd->status.party_id ) { + i = party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,BCT_PARTY,skill->area_sub_count); + skill_area_temp[5] = 7 * i; // ATK + party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id); + } else + sc_start2(bl,type,100,7,5,skill->get_time(skill_id,skill_lv)); + } + clif->skill_nodamage(src,bl,skill_id,1,1); + break; + /** + * Guilotine Cross + **/ + case GC_ROLLINGCUTTER: + { + short count = 1; + skill_area_temp[2] = 0; + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_PREAMBLE|SD_SPLASH|1,skill->castend_damage_id); + if( tsc && tsc->data[SC_ROLLINGCUTTER] ) + { // Every time the skill is casted the status change is reseted adding a counter. + count += (short)tsc->data[SC_ROLLINGCUTTER]->val1; + if( count > 10 ) + count = 10; // Max coounter + status_change_end(bl, SC_ROLLINGCUTTER, INVALID_TIMER); + } + sc_start(bl,SC_ROLLINGCUTTER,100,count,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + } + break; - case GC_WEAPONBLOCKING: - if( tsc && tsc->data[SC_WEAPONBLOCKING] ) - status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER); - else - sc_start(bl,SC_WEAPONBLOCKING,100,skill_lv,skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; + case GC_WEAPONBLOCKING: + if( tsc && tsc->data[SC_WEAPONBLOCKING] ) + status_change_end(bl, SC_WEAPONBLOCKING, INVALID_TIMER); + else + sc_start(bl,SC_WEAPONBLOCKING,100,skill_lv,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; - case GC_CREATENEWPOISON: - if( sd ) - { - clif_skill_produce_mix_list(sd,skill_id,25); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - } - break; + case GC_CREATENEWPOISON: + if( sd ) + { + clif->skill_produce_mix_list(sd,skill_id,25); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + } + break; - case GC_POISONINGWEAPON: - if( sd ) { - clif_poison_list(sd,skill_lv); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + case GC_POISONINGWEAPON: + if( sd ) { + clif->poison_list(sd,skill_lv); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case GC_ANTIDOTE: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if( tsc ) - { - status_change_end(bl, SC_PARALYSE, INVALID_TIMER); - status_change_end(bl, SC_PYREXIA, INVALID_TIMER); - status_change_end(bl, SC_DEATHHURT, INVALID_TIMER); - status_change_end(bl, SC_LEECHESEND, INVALID_TIMER); - status_change_end(bl, SC_VENOMBLEED, INVALID_TIMER); - status_change_end(bl, SC_MAGICMUSHROOM, INVALID_TIMER); - status_change_end(bl, SC_TOXIN, INVALID_TIMER); - status_change_end(bl, SC_OBLIVIONCURSE, INVALID_TIMER); - } - break; + case GC_ANTIDOTE: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( tsc ) + { + status_change_end(bl, SC_PARALYSE, INVALID_TIMER); + status_change_end(bl, SC_PYREXIA, INVALID_TIMER); + status_change_end(bl, SC_DEATHHURT, INVALID_TIMER); + status_change_end(bl, SC_LEECHESEND, INVALID_TIMER); + status_change_end(bl, SC_VENOMBLEED, INVALID_TIMER); + status_change_end(bl, SC_MAGICMUSHROOM, INVALID_TIMER); + status_change_end(bl, SC_TOXIN, INVALID_TIMER); + status_change_end(bl, SC_OBLIVIONCURSE, INVALID_TIMER); + } + break; - case GC_PHANTOMMENACE: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; + case GC_PHANTOMMENACE: + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + break; - case GC_HALLUCINATIONWALK: - { - int heal = status_get_max_hp(bl) / 10; - if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails. - if( sd ) clif_skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); - break; + case GC_HALLUCINATIONWALK: + { + int heal = status_get_max_hp(bl) / 10; + if( status_get_hp(bl) < heal ) { // if you haven't enough HP skill fails. + if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); + break; + } + if( !status_charge(bl,heal,0) ) + { + if( sd ) clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + } + break; + /** + * Arch Bishop + **/ + case AB_ANCILLA: + if( sd ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->produce_mix(sd, skill_id, ITEMID_ANCILLA, 0, 0, 0, 1); } - if( !status_charge(bl,heal,0) ) + break; + + case AB_CLEMENTIA: + case AB_CANTO: { - if( sd ) clif_skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); - break; + int bless_lv = pc_checkskill(sd,AL_BLESSING) + (sd->status.job_level / 10); + int agi_lv = pc_checkskill(sd,AL_INCAGI) + (sd->status.job_level / 10); + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100, + (skill_id == AB_CLEMENTIA)? bless_lv : (skill_id == AB_CANTO)? agi_lv : skill_lv, skill->get_time(skill_id,skill_lv))); + else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); } - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - } - break; - /** - * Arch Bishop - **/ - case AB_ANCILLA: - if( sd ) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_produce_mix(sd, skill_id, ITEMID_ANCILLA, 0, 0, 0, 1); - } - break; + break; - case AB_CLEMENTIA: - case AB_CANTO: - { - int bless_lv = pc_checkskill(sd,AL_BLESSING) + (sd->status.job_level / 10); - int agi_lv = pc_checkskill(sd,AL_INCAGI) + (sd->status.job_level / 10); + case AB_PRAEFATIO: if( sd == NULL || sd->status.party_id == 0 || flag&1 ) - clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start(bl,type,100, - (skill_id == AB_CLEMENTIA)? bless_lv : (skill_id == AB_CANTO)? agi_lv : skill_lv, skill_get_time(skill_id,skill_lv))); + clif->skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(bl, type, 100, skill_lv, 0, 0, 1, skill->get_time(skill_id, skill_lv))); else if( sd ) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } - break; - - case AB_PRAEFATIO: - if( sd == NULL || sd->status.party_id == 0 || flag&1 ) - clif_skill_nodamage(bl, bl, skill_id, skill_lv, sc_start4(bl, type, 100, skill_lv, 0, 0, 1, skill_get_time(skill_id, skill_lv))); - else if( sd ) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + break; - case AB_CHEAL: - if( sd == NULL || sd->status.party_id == 0 || flag&1 ) - { - if( sd && tstatus && !battle_check_undead(tstatus->race, tstatus->def_ele) ) - { - i = skill_calc_heal(src, bl, AL_HEAL, pc_checkskill(sd, AL_HEAL), true); + case AB_CHEAL: + if( sd == NULL || sd->status.party_id == 0 || flag&1 ) { + if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) ) { + i = skill->calc_heal(src, bl, AL_HEAL, pc_checkskill(sd, AL_HEAL), true); - if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl)) - i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] + if( (dstsd && pc_ismadogear(dstsd)) || status_isimmune(bl)) + i = 0; // Should heal by 0 or won't do anything?? in iRO it breaks the healing to members.. [malufett] - clif_skill_nodamage(bl, bl, skill_id, i, 1); - if( tsc && tsc->data[SC_AKAITSUKI] && i ) - i = ~i + 1; - status_heal(bl, i, 0, 0); + clif->skill_nodamage(bl, bl, skill_id, i, 1); + if( tsc && tsc->data[SC_AKAITSUKI] && i ) + i = ~i + 1; + status_heal(bl, i, 0, 0); + } } - } - else if( sd ) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + break; - case AB_ORATIO: - if( flag&1 ) - sc_start(bl, type, 40 + 5 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv)); - else - { - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - } - break; + case AB_ORATIO: + if( flag&1 ) + sc_start(bl, type, 40 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv)); + else + { + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + } + break; - case AB_LAUDAAGNUS: - if( flag&1 || sd == NULL ) { - if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] || - tsc->data[SC_BURNING] || tsc->data[SC_FREEZING] || tsc->data[SC_CRYSTALIZE])) { - // Success Chance: (40 + 10 * Skill Level) % - if( rnd()%100 > 40+10*skill_lv ) break; - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); - }else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets - clif_skill_nodamage(bl, bl, skill_id, skill_lv, - sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv))); - } else if( sd ) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), - src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + case AB_LAUDAAGNUS: + if( flag&1 || sd == NULL ) { + if( tsc && (tsc->data[SC_FREEZE] || tsc->data[SC_STONE] || tsc->data[SC_BLIND] || + tsc->data[SC_BURNING] || tsc->data[SC_FREEZING] || tsc->data[SC_CRYSTALIZE])) { + // Success Chance: (40 + 10 * Skill Level) % + if( rnd()%100 > 40+10*skill_lv ) break; + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); + }else //Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets + clif->skill_nodamage(bl, bl, skill_id, skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + } else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), + src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + break; - case AB_LAUDARAMUS: - if( flag&1 || sd == NULL ) { - if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE]) ){ - // Success Chance: (40 + 10 * Skill Level) % - if( rnd()%100 > 40+10*skill_lv ) break; - status_change_end(bl, SC_SLEEP, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - }else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets - clif_skill_nodamage(bl, bl, skill_id, skill_lv, - sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv))); - } else if( sd ) - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), - src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - break; + case AB_LAUDARAMUS: + if( flag&1 || sd == NULL ) { + if( tsc && (tsc->data[SC_SLEEP] || tsc->data[SC_STUN] || tsc->data[SC_MANDRAGORA] || tsc->data[SC_SILENCE]) ){ + // Success Chance: (40 + 10 * Skill Level) % + if( rnd()%100 > 40+10*skill_lv ) break; + status_change_end(bl, SC_SLEEP, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_MANDRAGORA, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + }else // Success rate only applies to the curing effect and not stat bonus. Bonus status only applies to non infected targets + clif->skill_nodamage(bl, bl, skill_id, skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + } else if( sd ) + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), + src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + break; - case AB_CLEARANCE: - if( flag&1 || (i = skill_get_splash(skill_id, skill_lv)) < 1 ) - { //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie] - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 30 + 10 * skill_lv) - { - if (sd) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case AB_CLEARANCE: + if( flag&1 || (i = skill->get_splash(skill_id, skill_lv)) < 1 ) + { //As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie] + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if((dstsd && (dstsd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER) || rnd()%100 >= 30 + 10 * skill_lv) + { + if (sd) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + if(status_isimmune(bl) || !tsc || !tsc->count) + break; + for(i=0;i<SC_MAX;i++) + { + if (!tsc->data[i]) + continue; + switch (i) { + case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: + case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR: + case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD: + case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO: + case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: + case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: + case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: + case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: + case SC_SPIRIT: case SC_AUTOBERSERK: + case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: + case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: + case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: + case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: + case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: + case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: + case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: + case SC_READYCOUNTER:case SC_DODGE: case SC_WARM: + case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: + case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: + case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: + case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: + case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: + case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: + case SC_INTOABYSS: case SC_SIEGFRIED: case SC_WHISTLE: + case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN: + case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE: + case SC_SERVICE4U: case SC_FOOD_STR_CASH: case SC_FOOD_AGI_CASH: + case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: case SC_FOOD_INT_CASH: + case SC_FOOD_LUK_CASH: case SC_ELECTRICSHOCKER: case SC_BITE: + case SC__STRIPACCESSORY: case SC__ENERVATION: case SC__GROOMY: + case SC__IGNORANCE: case SC__LAZINESS: case SC__UNLUCKY: + case SC__WEAKNESS: //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: + case SC_MAGNETICFIELD://case SC_MINOR_BBQ: case SC_SIROMA_ICE_TEA: + //case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: + case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: + case SC_STEALTHFIELD_MASTER: case SC_STEALTHFIELD: + case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: + case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: + case SC_PARTYFLEE: case SC_GT_REVITALIZE: + case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: + #ifdef RENEWAL + case SC_EXTREMITYFIST2: + #endif + continue; + case SC_ASSUMPTIO: + if( bl->type == BL_MOB ) + continue; + break; + } + if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. + status_change_end(bl,(sc_type)i,INVALID_TIMER); + } break; } - if(status_isimmune(bl) || !tsc || !tsc->count) - break; - for(i=0;i<SC_MAX;i++) + map_foreachinrange(skill->area_sub, bl, i, BL_CHAR, src, skill_id, skill_lv, tick, flag|1, skill->castend_damage_id); + break; + + case AB_SILENTIUM: + // Should the level of Lex Divina be equivalent to the level of Silentium or should the highest level learned be used? [LimitLine] + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, PR_LEXDIVINA, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + break; + /** + * Warlock + **/ + case WL_STASIS: + if( flag&1 ) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + else { - if (!tsc->data[i]) - continue; - switch (i) { - case SC_WEIGHT50: case SC_WEIGHT90: case SC_HALLUCINATION: - case SC_STRIPWEAPON: case SC_STRIPSHIELD: case SC_STRIPARMOR: - case SC_STRIPHELM: case SC_CP_WEAPON: case SC_CP_SHIELD: - case SC_CP_ARMOR: case SC_CP_HELM: case SC_COMBO: - case SC_STRFOOD: case SC_AGIFOOD: case SC_VITFOOD: - case SC_INTFOOD: case SC_DEXFOOD: case SC_LUKFOOD: - case SC_HITFOOD: case SC_FLEEFOOD: case SC_BATKFOOD: - case SC_WATKFOOD: case SC_MATKFOOD: case SC_DANCING: - case SC_SPIRIT: case SC_AUTOBERSERK: - case SC_CARTBOOST: case SC_MELTDOWN: case SC_SAFETYWALL: - case SC_SMA: case SC_SPEEDUP0: case SC_NOCHAT: - case SC_ANKLE: case SC_SPIDERWEB: case SC_JAILED: - case SC_ITEMBOOST: case SC_EXPBOOST: case SC_LIFEINSURANCE: - case SC_BOSSMAPINFO: case SC_PNEUMA: case SC_AUTOSPELL: - case SC_INCHITRATE: case SC_INCATKRATE: case SC_NEN: - case SC_READYSTORM: case SC_READYDOWN: case SC_READYTURN: - case SC_READYCOUNTER:case SC_DODGE: case SC_WARM: - case SC_SPEEDUP1: case SC_AUTOTRADE: case SC_CRITICALWOUND: - case SC_JEXPBOOST: case SC_INVINCIBLE: case SC_INVINCIBLEOFF: - case SC_HELLPOWER: case SC_MANU_ATK: case SC_MANU_DEF: - case SC_SPL_ATK: case SC_SPL_DEF: case SC_MANU_MATK: - case SC_SPL_MATK: case SC_RICHMANKIM: case SC_ETERNALCHAOS: - case SC_DRUMBATTLE: case SC_NIBELUNGEN: case SC_ROKISWEIL: - case SC_INTOABYSS: case SC_SIEGFRIED: case SC_WHISTLE: - case SC_ASSNCROS: case SC_POEMBRAGI: case SC_APPLEIDUN: - case SC_HUMMING: case SC_DONTFORGETME: case SC_FORTUNE: - case SC_SERVICE4U: case SC_FOOD_STR_CASH: case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: case SC_FOOD_DEX_CASH: case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: case SC_ELECTRICSHOCKER: case SC_BITE: - case SC__STRIPACCESSORY: case SC__ENERVATION: case SC__GROOMY: - case SC__IGNORANCE: case SC__LAZINESS: case SC__UNLUCKY: - case SC__WEAKNESS: //case SC_SAVAGE_STEAK: case SC_COCKTAIL_WARG_BLOOD: - case SC_MAGNETICFIELD://case SC_MINOR_BBQ: case SC_SIROMA_ICE_TEA: - //case SC_DROCERA_HERB_STEAMED: case SC_PUTTI_TAILS_NOODLES: - case SC_NEUTRALBARRIER_MASTER: case SC_NEUTRALBARRIER: - case SC_STEALTHFIELD_MASTER: case SC_STEALTHFIELD: - case SC_LEADERSHIP: case SC_GLORYWOUNDS: case SC_SOULCOLD: - case SC_HAWKEYES: case SC_GUILDAURA: case SC_PUSH_CART: - case SC_PARTYFLEE: case SC_GT_REVITALIZE: - case SC_RAISINGDRAGON: case SC_GT_ENERGYGAIN: case SC_GT_CHANGE: -#ifdef RENEWAL - case SC_EXTREMITYFIST2: -#endif - continue; - case SC_ASSUMPTIO: - if( bl->type == BL_MOB ) - continue; - break; - } - if(i==SC_BERSERK || i==SC_SATURDAYNIGHTFEVER) tsc->data[i]->val2=0; //Mark a dispelled berserk to avoid setting hp to 100 by setting hp penalty to 0. - status_change_end(bl,(sc_type)i,INVALID_TIMER); + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } break; - } - map_foreachinrange(skill_area_sub, bl, i, BL_CHAR, src, skill_id, skill_lv, tick, flag|1, skill_castend_damage_id); - break; - case AB_SILENTIUM: - // Should the level of Lex Divina be equivalent to the level of Silentium or should the highest level learned be used? [LimitLine] - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id, skill_lv), BL_CHAR, - src, PR_LEXDIVINA, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - break; - /** - * Warlock - **/ - case WL_STASIS: - if( flag&1 ) - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - else - { - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id, skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,(map_flag_vs(src->m)?BCT_ALL:BCT_ENEMY|BCT_SELF)|flag|1,skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - } - break; + case WL_WHITEIMPRISON: + if( (src == bl || battle->check_target(src, bl, BCT_ENEMY) > 0 ) && !is_boss(bl) )// Should not work with bosses. + { + int rate = ( sd? sd->status.job_level : 50 ) / 4; - case WL_WHITEIMPRISON: - if( (src == bl || battle_check_target(src, bl, BCT_ENEMY)) && !is_boss(bl) )// Should not work with bosses. - { - int rate = ( sd? sd->status.job_level : 50 ) / 4; + if( src == bl ) rate = 100; // Success Chance: On self, 100% + else if(bl->type == BL_PC) rate += 20 + 10 * skill_lv; // On Players, (20 + 10 * Skill Level) % + else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) % - if( src == bl ) rate = 100; // Success Chance: On self, 100% - else if(bl->type == BL_PC) rate += 20 + 10 * skill_lv; // On Players, (20 + 10 * Skill Level) % - else rate += 40 + 10 * skill_lv; // On Monsters, (40 + 10 * Skill Level) % + if( sd ) + skill->blockpc_start(sd,skill_id,4000, false); + if( !(tsc && tsc->data[type]) ){ + i = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill->get_time(skill_id,skill_lv):skill->get_time2(skill_id, skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,i); + if( !i ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } + }else if( sd ) - skill_blockpc_start(sd,skill_id,4000); - - if( !(tsc && tsc->data[type]) ){ - i = sc_start2(bl,type,rate,skill_lv,src->id,(src == bl)?5000:(bl->type == BL_PC)?skill_get_time(skill_id,skill_lv):skill_get_time2(skill_id, skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv,i); - if( !i ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - }else - if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); - break; - - case WL_FROSTMISTY: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill_castend_damage_id); - break; + clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); + break; - case WL_JACKFROST: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_foreachinshootrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; + case WL_FROSTMISTY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); + break; - case WL_MARSHOFABYSS: - // Should marsh of abyss still apply half reduction to players after the 28/10 patch? [LimitLine] - clif_skill_nodamage(src, bl, skill_id, skill_lv, - sc_start4(bl, type, 100, skill_lv, status_get_int(src), sd ? sd->status.job_level : 50, 0, - skill_get_time(skill_id, skill_lv))); - break; + case WL_JACKFROST: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_foreachinshootrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + break; - case WL_SIENNAEXECRATE: - if( status_isimmune(bl) || !tsc ) + case WL_MARSHOFABYSS: + // Should marsh of abyss still apply half reduction to players after the 28/10 patch? [LimitLine] + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start4(bl, type, 100, skill_lv, status_get_int(src), sd ? sd->status.job_level : 50, 0, + skill->get_time(skill_id, skill_lv))); break; - if( flag&1 ) { - if( bl->id == skill_area_temp[1] ) - break; // Already work on this target + case WL_SIENNAEXECRATE: + if( status_isimmune(bl) || !tsc ) + break; - if( tsc && tsc->data[SC_STONE] ) - status_change_end(bl,SC_STONE,INVALID_TIMER); - else - status_change_start(bl,SC_STONE,10000,skill_lv,0,0,1000,skill_get_time(skill_id, skill_lv),2); - } else { - int rate = 40 + 8 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4; - // IroWiki says Rate should be reduced by target stats, but currently unknown - if( rnd()%100 < rate ) { // Success on First Target - if( !tsc->data[SC_STONE] ) - rate = status_change_start(bl,SC_STONE,10000,skill_lv,0,0,1000,skill_get_time(skill_id, skill_lv),2); - else { - rate = 1; + if( flag&1 ) { + if( bl->id == skill_area_temp[1] ) + break; // Already work on this target + + if( tsc && tsc->data[SC_STONE] ) status_change_end(bl,SC_STONE,INVALID_TIMER); - } + else + status_change_start(bl,SC_STONE,10000,skill_lv,0,0,1000,skill->get_time(skill_id, skill_lv),2); + } else { + int rate = 40 + 8 * skill_lv + ( sd? sd->status.job_level : 50 ) / 4; + // IroWiki says Rate should be reduced by target stats, but currently unknown + if( rnd()%100 < rate ) { // Success on First Target + if( !tsc->data[SC_STONE] ) + rate = status_change_start(bl,SC_STONE,10000,skill_lv,0,0,1000,skill->get_time(skill_id, skill_lv),2); + else { + rate = 1; + status_change_end(bl,SC_STONE,INVALID_TIMER); + } - if( rate ) { - skill_area_temp[1] = bl->id; - map_foreachinrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id); + if( rate ) { + skill_area_temp[1] = bl->id; + map_foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id); + } + // Doesn't send failure packet if it fails on defense. } - // Doesn't send failure packet if it fails on defense. - } - else if( sd ) // Failure on Rate - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } - break; - - case WL_SUMMONFB: - case WL_SUMMONBL: - case WL_SUMMONWB: - case WL_SUMMONSTONE: - { - short element = 0, sctype = 0, pos = -1; - struct status_change *sc = status_get_sc(src); - if( !sc ) break; - - for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) - { - if( !sctype && !sc->data[i] ) - sctype = i; // Take the free SC - if( sc->data[i] ) - pos = max(sc->data[i]->val2,pos); + else if( sd ) // Failure on Rate + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); } + break; - if( !sctype ) + case WL_SUMMONFB: + case WL_SUMMONBL: + case WL_SUMMONWB: + case WL_SUMMONSTONE: { - if( sd ) // No free slots to put SC - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); - break; - } + short element = 0, sctype = 0, pos = -1; + struct status_change *sc = status_get_sc(src); + if( !sc ) break; - pos++; // Used in val2 for SC. Indicates the order of this ball - switch( skill_id ) - { // Set val1. The SC element for this ball - case WL_SUMMONFB: element = WLS_FIRE; break; - case WL_SUMMONBL: element = WLS_WIND; break; - case WL_SUMMONWB: element = WLS_WATER; break; - case WL_SUMMONSTONE: element = WLS_STONE; break; - } + for( i = SC_SPHERE_1; i <= SC_SPHERE_5; i++ ) + { + if( !sctype && !sc->data[i] ) + sctype = i; // Take the free SC + if( sc->data[i] ) + pos = max(sc->data[i]->val2,pos); + } - sc_start4(src,sctype,100,element,pos,skill_lv,0,skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage(src,bl,skill_id,0,0); - } - break; + if( !sctype ) + { + if( sd ) // No free slots to put SC + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); + break; + } - case WL_READING_SB: - if( sd ) { - struct status_change *sc = status_get_sc(bl); + pos++; // Used in val2 for SC. Indicates the order of this ball + switch( skill_id ) { // Set val1. The SC element for this ball + case WL_SUMMONFB: element = WLS_FIRE; break; + case WL_SUMMONBL: element = WLS_WIND; break; + case WL_SUMMONWB: element = WLS_WATER; break; + case WL_SUMMONSTONE: element = WLS_STONE; break; + } - for( i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) - if( sc && !sc->data[i] ) - break; - if( i == SC_MAXSPELLBOOK ) { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); - break; + sc_start4(src,sctype,100,element,pos,skill_lv,0,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,0,0); } + break; - sc_start(bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook. - clif_spellbook_list(sd); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - } - break; - /** - * Ranger - **/ - case RA_FEARBREEZE: - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv))); - break; + case WL_READING_SB: + if( sd ) { + struct status_change *sc = status_get_sc(bl); - case RA_WUGMASTERY: - if( sd ) { - if( !pc_iswug(sd) ) - pc_setoption(sd,sd->sc.option|OPTION_WUG); - else - pc_setoption(sd,sd->sc.option&~OPTION_WUG); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + for( i = SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) + if( sc && !sc->data[i] ) + break; + if( i == SC_MAXSPELLBOOK ) { + clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); + break; + } - case RA_WUGRIDER: - if( sd ) { - if( !pc_isridingwug(sd) && pc_iswug(sd) ) { - pc_setoption(sd,sd->sc.option&~OPTION_WUG); - pc_setoption(sd,sd->sc.option|OPTION_WUGRIDER); - } else if( pc_isridingwug(sd) ) { - pc_setoption(sd,sd->sc.option&~OPTION_WUGRIDER); - pc_setoption(sd,sd->sc.option|OPTION_WUG); + sc_start(bl, SC_STOP, 100, skill_lv, INVALID_TIMER); //Can't move while selecting a spellbook. + clif->spellbook_list(sd); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + break; + /** + * Ranger + **/ + case RA_FEARBREEZE: + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); + break; - case RA_WUGDASH: - if( tsce ) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); - map_freeblock_unlock(); - return 0; - } - if( sd && pc_isridingwug(sd) ) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,1)); - clif_walkok(sd); - } - break; + case RA_WUGMASTERY: + if( sd ) { + if( !pc_iswug(sd) ) + pc_setoption(sd,sd->sc.option|OPTION_WUG); + else + pc_setoption(sd,sd->sc.option&~OPTION_WUG); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case RA_SENSITIVEKEEN: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill_castend_damage_id); - break; - /** - * Mechanic - **/ - case NC_F_SIDESLIDE: - case NC_B_SIDESLIDE: - { - uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit_getdir(src)+4)%8 : unit_getdir(src); - skill_blown(src,bl,skill_get_blewcount(skill_id,skill_lv),dir,0x1); - clif_slide(src,src->x,src->y); - clif_fixpos(src); //Aegis sent this packet - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + case RA_WUGRIDER: + if( sd ) { + if( !pc_isridingwug(sd) && pc_iswug(sd) ) { + pc_setoption(sd,sd->sc.option&~OPTION_WUG); + pc_setoption(sd,sd->sc.option|OPTION_WUGRIDER); + } else if( pc_isridingwug(sd) ) { + pc_setoption(sd,sd->sc.option&~OPTION_WUGRIDER); + pc_setoption(sd,sd->sc.option|OPTION_WUG); + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case NC_SELFDESTRUCTION: - if( sd ) { - if( pc_ismadogear(sd) ) - pc_setmadogear(sd, 0); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - skill_castend_damage_id(src, src, skill_id, skill_lv, tick, flag); - status_set_sp(src, 0, 0); - } - break; + case RA_WUGDASH: + if( tsce ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,status_change_end(bl, type, INVALID_TIMER)); + map_freeblock_unlock(); + return 0; + } + if( sd && pc_isridingwug(sd) ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(bl,type,100,skill_lv,unit_getdir(bl),0,0,1)); + clif->walkok(sd); + } + break; - case NC_ANALYZE: - clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif_skill_nodamage(src, bl, skill_id, skill_lv, - sc_start(bl,type, 30 + 12 * skill_lv,skill_lv,skill_get_time(skill_id,skill_lv))); - if( sd ) pc_overheat(sd,1); - break; + case RA_SENSITIVEKEEN: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR|BL_SKILL,src,skill_id,skill_lv,tick,flag|BCT_ENEMY,skill->castend_damage_id); + break; + /** + * Mechanic + **/ + case NC_F_SIDESLIDE: + case NC_B_SIDESLIDE: + { + uint8 dir = (skill_id == NC_F_SIDESLIDE) ? (unit_getdir(src)+4)%8 : unit_getdir(src); + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),dir,0x1); + clif->slide(src,src->x,src->y); + clif->fixpos(src); //Aegis sent this packet + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; - case NC_MAGNETICFIELD: - if( (i = sc_start2(bl,type,100,skill_lv,src->id,skill_get_time(skill_id,skill_lv))) ) - { - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill_castend_damage_id);; - clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); - if (sd) pc_overheat(sd,1); - } - clif_skill_nodamage(src,src,skill_id,skill_lv,i); - break; + case NC_SELFDESTRUCTION: + if( sd ) { + if( pc_ismadogear(sd) ) + pc_setmadogear(sd, 0); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + skill->castend_damage_id(src, src, skill_id, skill_lv, tick, flag); + status_set_sp(src, 0, 0); + } + break; - case NC_REPAIR: - if( sd ) - { - int heal; - if( dstsd && pc_ismadogear(dstsd) ) + case NC_ANALYZE: + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(bl,type, 30 + 12 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv))); + if( sd ) pc_overheat(sd,1); + break; + + case NC_MAGNETICFIELD: + if( (i = sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))) ) { - heal = dstsd->status.max_hp * (3+3*skill_lv) / 100; - status_heal(bl,heal,0,2); - } else { - heal = sd->status.max_hp * (3+3*skill_lv) / 100; - status_heal(src,heal,0,2); + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|SD_SPLASH|1,skill->castend_damage_id);; + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + if (sd) pc_overheat(sd,1); } + clif->skill_nodamage(src,src,skill_id,skill_lv,i); + break; - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - clif_skill_nodamage(src, bl, skill_id, skill_lv, heal); - } - break; + case NC_REPAIR: + if( sd ) + { + int heal; + if( dstsd && pc_ismadogear(dstsd) ) + { + heal = dstsd->status.max_hp * (3+3*skill_lv) / 100; + status_heal(bl,heal,0,2); + } else { + heal = sd->status.max_hp * (3+3*skill_lv) / 100; + status_heal(src,heal,0,2); + } - case NC_DISJOINT: - { - if( bl->type != BL_MOB ) break; - md = map_id2md(bl->id); - if( md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND ) - status_kill(bl); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - } - break; - case SC_AUTOSHADOWSPELL: - if( sd ) { - if( sd->status.skill[sd->reproduceskill_id].id || sd->status.skill[sd->cloneskill_id].id ) { - sc_start(src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] - clif_autoshadowspell_list(sd); - clif_skill_nodamage(src,bl,skill_id,1,1); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + clif->skill_nodamage(src, bl, skill_id, skill_lv, heal); } - else - clif_skill_fail(sd,skill_id,USESKILL_FAIL_IMITATION_SKILL_NONE,0); - } - break; + break; - case SC_SHADOWFORM: - if( sd && dstsd && src != bl && !dstsd->shadowform_id ) { - if( clif_skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,type,100,skill_lv,bl->id,4+skill_lv,0,skill_get_time(skill_id, skill_lv))) ) - dstsd->shadowform_id = src->id; - } - else if( sd ) - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; + case NC_DISJOINT: + { + if( bl->type != BL_MOB ) break; + md = map_id2md(bl->id); + if( md && md->class_ >= MOBID_SILVERSNIPER && md->class_ <= MOBID_MAGICDECOY_WIND ) + status_kill(bl); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + } + break; + case SC_AUTOSHADOWSPELL: + if( sd ) { + int idx1 = skill->get_index(sd->reproduceskill_id), idx2 = skill->get_index(sd->cloneskill_id); + if( sd->status.skill[idx1].id || sd->status.skill[idx2].id ) { + sc_start(src,SC_STOP,100,skill_lv,-1);// The skill_lv is stored in val1 used in skill_select_menu to determine the used skill lvl [Xazax] + clif->autoshadowspell_list(sd); + clif->skill_nodamage(src,bl,skill_id,1,1); + } + else + clif->skill_fail(sd,skill_id,USESKILL_FAIL_IMITATION_SKILL_NONE,0); + } + break; - case SC_BODYPAINT: - if( flag&1 ) { - if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || - tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || - tsc->data[SC__INVISIBILITY]) ) { - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); + case SC_SHADOWFORM: + if( sd && dstsd && src != bl && !dstsd->shadowform_id ) { + if( clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start4(src,type,100,skill_lv,bl->id,4+skill_lv,0,skill->get_time(skill_id, skill_lv))) ) + dstsd->shadowform_id = src->id; + } + else if( sd ) + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - sc_start(bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill_get_time(skill_id,skill_lv)); + case SC_BODYPAINT: + if( flag&1 ) { + if( tsc && (tsc->data[SC_HIDING] || tsc->data[SC_CLOAKING] || + tsc->data[SC_CHASEWALK] || tsc->data[SC_CLOAKINGEXCEED] || + tsc->data[SC__INVISIBILITY]) ) { + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CHASEWALK, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); + + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,SC_BLIND,53 + 2 * skill_lv,skill_lv,skill->get_time(skill_id,skill_lv)); + } + } else { + clif->skill_nodamage(src, bl, skill_id, 0, 1); + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); } - } else { - clif_skill_nodamage(src, bl, skill_id, 0, 1); - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - } - break; + break; - case SC_ENERVATION: - case SC_GROOMY: - case SC_LAZINESS: - case SC_UNLUCKY: - case SC_WEAKNESS: - if( !(tsc && tsc->data[type]) ) { - //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3)) - int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 - - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); - rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); - clif_skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill_get_time(skill_id,skill_lv))); - } else if( sd ) - clif_skill_fail(sd,skill_id,0,0); - break; + case SC_ENERVATION: + case SC_GROOMY: + case SC_LAZINESS: + case SC_UNLUCKY: + case SC_WEAKNESS: + if( !(tsc && tsc->data[type]) ) { + //((rand(myDEX / 12, myDEX / 4) + myJobLevel + 10 * skLevel) + myLevel / 10) - (targetLevel / 10 + targetLUK / 10 + (targetMaxWeight - targetWeight) / 1000 + rand(targetAGI / 6, targetAGI / 3)) + int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 + - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); + rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); + clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv))); + } else if( sd ) + clif->skill_fail(sd,skill_id,0,0); + break; - case SC_IGNORANCE: - if( !(tsc && tsc->data[type]) ) { - int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 - - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); - rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); - if (clif_skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill_get_time(skill_id,skill_lv)))) { - int sp = 200 * skill_lv; - if( dstmd ) sp = dstmd->level * 2; - if( status_zap(bl,0,sp) ) - status_heal(src,0,sp/2,3); - } - else if( sd ) clif_skill_fail(sd,skill_id,0,0); - } else if( sd ) - clif_skill_fail(sd,skill_id,0,0); - break; + case SC_IGNORANCE: + if( !(tsc && tsc->data[type]) ) { + int rate = rnd_value(sstatus->dex/12,sstatus->dex/4) + 10*skill_lv + (sd?sd->status.job_level:0) + status_get_lv(src)/10 + - status_get_lv(bl)/10 - tstatus->luk/10 - (dstsd?(dstsd->max_weight-dstsd->weight)/10000:0) - rnd_value(tstatus->agi/6,tstatus->agi/3); + rate = cap_value(rate, skill_lv+sstatus->dex/20, 100); + if (clif->skill_nodamage(src,bl,skill_id,0,sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)))) { + int sp = 200 * skill_lv; + if( dstmd ) sp = dstmd->level * 2; + if( status_zap(bl,0,sp) ) + status_heal(src,0,sp/2,3); + } + else if( sd ) clif->skill_fail(sd,skill_id,0,0); + } else if( sd ) + clif->skill_fail(sd,skill_id,0,0); + break; - case LG_TRAMPLE: - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - map_foreachinrange(skill_destroy_trap,bl,skill_get_splash(skill_id,skill_lv),BL_SKILL,tick); - break; + case LG_TRAMPLE: + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + map_foreachinrange(skill->destroy_trap,bl,skill->get_splash(skill_id,skill_lv),BL_SKILL,tick); + break; - case LG_REFLECTDAMAGE: - if( tsc && tsc->data[type] ) - status_change_end(bl,type,INVALID_TIMER); - else - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - break; + case LG_REFLECTDAMAGE: + if( tsc && tsc->data[type] ) + status_change_end(bl,type,INVALID_TIMER); + else + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + break; - case LG_SHIELDSPELL: - if( flag&1 ) { - int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000; - sc_start(bl,SC_SILENCE,100,skill_lv,duration); - } else if( sd ) { - int opt = skill_lv; - int rate = rnd()%100; - int val, brate; - switch( skill_lv ) { - case 1: - { - struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; - if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield? - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; + case LG_SHIELDSPELL: + if( flag&1 ) { + int duration = (sd) ? sd->bonus.shieldmdef * 2000 : 10000; + sc_start(bl,SC_SILENCE,100,skill_lv,duration); + } else if( sd ) { + int opt = skill_lv; + int rate = rnd()%100; + int val, brate; + switch( skill_lv ) { + case 1: + { + struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]]; + if( !shield_data || shield_data->type != IT_ARMOR ) { // No shield? + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; + } + brate = shield_data->def * 10; + if( rate < 50 ) + opt = 1; + else if( rate < 75 ) + opt = 2; + else + opt = 3; + + switch( opt ) { + case 1: + sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( rate < brate ) + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); + break; + case 2: + val = shield_data->def / 10; // % Reflected damage. + sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000); + break; + case 3: + val = shield_data->def; // Attack increase. + sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000); + break; + } } - brate = shield_data->def * 10; - if( rate < 50 ) + break; + + case 2: + brate = sd->bonus.shieldmdef * 20; + if( rate < 30 ) opt = 1; - else if( rate < 75 ) + else if( rate < 60 ) opt = 2; else opt = 3; - switch( opt ) { case 1: - sc_start(bl,SC_SHIELDSPELL_DEF,100,opt,-1); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); if( rate < brate ) - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - status_change_end(bl,SC_SHIELDSPELL_DEF,INVALID_TIMER); + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|2,skill->castend_damage_id); + status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); break; case 2: - val = shield_data->def / 10; // % Reflected damage. - sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 1000); + sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( rate < brate ) + map_foreachinrange(skill->area_sub,src,skill->get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_nodamage_id); break; case 3: - val = shield_data->def; // Attack increase. - sc_start2(bl,SC_SHIELDSPELL_DEF,brate,opt,val,shield_data->def * 3000); + if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) ) + clif->skill_nodamage(src,bl,PR_MAGNIFICAT,skill_lv, + sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000)); break; } - } - break; + break; - case 2: - brate = sd->bonus.shieldmdef * 20; - if( rate < 30 ) - opt = 1; - else if( rate < 60 ) - opt = 2; - else - opt = 3; - switch( opt ) { - case 1: - sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rate < brate ) - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|2,skill_castend_damage_id); - status_change_end(bl,SC_SHIELDSPELL_MDEF,INVALID_TIMER); - break; - case 2: - sc_start(bl,SC_SHIELDSPELL_MDEF,100,opt,-1); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( rate < brate ) - map_foreachinrange(skill_area_sub,src,skill_get_splash(skill_id,skill_lv),BL_CHAR,src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_nodamage_id); - break; - case 3: - if( sc_start(bl,SC_SHIELDSPELL_MDEF,brate,opt,sd->bonus.shieldmdef * 30000) ) - clif_skill_nodamage(src,bl,PR_MAGNIFICAT,skill_lv, - sc_start(bl,SC_MAGNIFICAT,100,1,sd->bonus.shieldmdef * 30000)); + case 3: + { + struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; + if( !it ) { // No shield? + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; + } + brate = it->refine * 5; + if( rate < 25 ) + opt = 1; + else if( rate < 50 ) + opt = 2; + else + opt = 3; + switch( opt ) { + case 1: + val = 105 * it->refine / 10; + sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill->get_time(skill_id,skill_lv)); + break; + case 2: case 3: + if( rate < brate ) + { + val = sstatus->max_hp * (11 + it->refine) / 100; + status_heal(bl, val, 0, 3); + } + break; + /*case 3: + // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it. + break;*/ + } } break; - - case 3: - { - struct item *it = &sd->status.inventory[sd->equip_index[EQI_HAND_L]]; - if( !it ) { // No shield? - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; - } - brate = it->refine * 5; - if( rate < 25 ) - opt = 1; - else if( rate < 50 ) - opt = 2; - else - opt = 3; - switch( opt ) { - case 1: - val = 105 * it->refine / 10; - sc_start2(bl,SC_SHIELDSPELL_REF,brate,opt,val,skill_get_time(skill_id,skill_lv)); - break; - case 2: case 3: - if( rate < brate ) - { - val = sstatus->max_hp * (11 + it->refine) / 100; - status_heal(bl, val, 0, 3); - } - break; - /*case 3: - // Full protection. I need confirm what effect should be here. Moved to case 2 to until we got it. - break;*/ - } } - break; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; - - case LG_PIETY: - if( flag&1 ) - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - else { - skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub,bl,skill_get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + break; - case LG_INSPIRATION: - if( sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) { - sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * 1 / 100); // 1% penalty. - sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * 1 / 100); - clif_updatestatus(sd,SP_BASEEXP); - clif_updatestatus(sd,SP_JOBEXP); - } - clif_skill_nodamage(bl,src,skill_id,skill_lv, - sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv))); - break; - case SR_CURSEDCIRCLE: - if( flag&1 ) { - if( is_boss(bl) ) break; - if( sc_start2(bl, type, 100, skill_lv, src->id, skill_get_time(skill_id, skill_lv))) { - if( bl->type == BL_MOB ) - mob_unlocktarget((TBL_MOB*)bl,gettick()); - unit_stop_attack(bl); - clif_bladestop(src, bl->id, 1); - map_freeblock_unlock(); - return 1; + case LG_PIETY: + if( flag&1 ) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + else { + skill_area_temp[2] = 0; + map_foreachinrange(skill->area_sub,bl,skill->get_splash(skill_id,skill_lv),BL_PC,src,skill_id,skill_lv,tick,flag|SD_PREAMBLE|BCT_PARTY|BCT_SELF|1,skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - } else { - int count = 0; - clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - count = map_forcountinrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors - BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - if( sd ) pc_delspiritball(sd, count, 0); - clif_skill_nodamage(src, src, skill_id, skill_lv, - sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill_get_time(skill_id,skill_lv))); - } - break; - - case SR_RAISINGDRAGON: - if( sd ) { - short max = 5 + skill_lv; - sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - for( i = 0; i < max; i++ ) // Don't call more than max available spheres. - pc_addspiritball(sd, skill_get_time(skill_id, skill_lv), max); - clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv,skill_get_time(skill_id, skill_lv))); - } - break; + break; - case SR_ASSIMILATEPOWER: - if( flag&1 ) { - i = 0; - if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER ) - { - i = dstsd->spiritball; //1%sp per spiritball. - pc_delspiritball(dstsd, dstsd->spiritball, 0); + case LG_INSPIRATION: + if( sd && !map[sd->bl.m].flag.noexppenalty && sd->status.base_level != MAX_LEVEL ) { + sd->status.base_exp -= min(sd->status.base_exp, pc_nextbaseexp(sd) * 1 / 100); // 1% penalty. + sd->status.job_exp -= min(sd->status.job_exp, pc_nextjobexp(sd) * 1 / 100); + clif->updatestatus(sd,SP_BASEEXP); + clif->updatestatus(sd,SP_JOBEXP); } - if( i ) status_percent_heal(src, 0, i); - clif_skill_nodamage(src, bl, skill_id, skill_lv, i ? 1:0); - } else { - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill_castend_nodamage_id); - } - break; - - case SR_POWERVELOCITY: - if( !dstsd ) + clif->skill_nodamage(bl,src,skill_id,skill_lv, + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv))); break; - if( sd && dstsd->spiritball <= 5 ) { - for(i = 0; i <= 5; i++) { - pc_addspiritball(dstsd, skill_get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), i); - pc_delspiritball(sd, sd->spiritball, 0); + case SR_CURSEDCIRCLE: + if( flag&1 ) { + if( is_boss(bl) ) break; + if( sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id, skill_lv))) { + if( bl->type == BL_MOB ) + mob_unlocktarget((TBL_MOB*)bl,gettick()); + unit_stop_attack(bl); + clif->bladestop(src, bl->id, 1); + map_freeblock_unlock(); + return 1; + } + } else { + int count = 0; + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + count = map_forcountinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv), (sd)?sd->spiritball_old:15, // Assume 15 spiritballs in non-charactors + BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + if( sd ) pc_delspiritball(sd, count, 0); + clif->skill_nodamage(src, src, skill_id, skill_lv, + sc_start2(src, SC_CURSEDCIRCLE_ATKER, 100, skill_lv, count, skill->get_time(skill_id,skill_lv))); } - } - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - break; + break; - case SR_GENTLETOUCH_CURE: - { - int heal; + case SR_RAISINGDRAGON: + if( sd ) { + short max = 5 + skill_lv; + sc_start(bl, SC_EXPLOSIONSPIRITS, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + for( i = 0; i < max; i++ ) // Don't call more than max available spheres. + pc_addspiritball(sd, skill->get_time(skill_id, skill_lv), max); + clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv))); + } + break; - if( status_isimmune(bl) ) - { - clif_skill_nodamage(src,bl,skill_id,skill_lv,0); - break; + case SR_ASSIMILATEPOWER: + if( flag&1 ) { + i = 0; + if( dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m)) && (dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER ) + { + i = dstsd->spiritball; //1%sp per spiritball. + pc_delspiritball(dstsd, dstsd->spiritball, 0); + } + if( i ) status_percent_heal(src, 0, i); + clif->skill_nodamage(src, bl, skill_id, skill_lv, i ? 1:0); + } else { + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF|SD_SPLASH|1, skill->castend_nodamage_id); } + break; - heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100; - status_heal(bl, heal, 0, 0); + case SR_POWERVELOCITY: + if( !dstsd ) + break; + if( sd && dstsd->spiritball <= 5 ) { + for(i = 0; i <= 5; i++) { + pc_addspiritball(dstsd, skill->get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), i); + pc_delspiritball(sd, sd->spiritball, 0); + } + } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + break; - if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status_get_lv(src)) / 4) - (1 + (rnd() % 10))) ) + case SR_GENTLETOUCH_CURE: { - status_change_end(bl, SC_STONE, INVALID_TIMER); - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STUN, INVALID_TIMER); - status_change_end(bl, SC_POISON, INVALID_TIMER); - status_change_end(bl, SC_SILENCE, INVALID_TIMER); - status_change_end(bl, SC_BLIND, INVALID_TIMER); - status_change_end(bl, SC_HALLUCINATION, INVALID_TIMER); - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - } + int heal; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; - case SR_GENTLETOUCH_CHANGE: - case SR_GENTLETOUCH_REVITALIZE: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start2(bl,type,100,skill_lv,src->id,skill_get_time(skill_id,skill_lv))); - break; - case WA_SWING_DANCE: - case WA_MOONLIT_SERENADE: - if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - else if( sd ) { // Only shows effects on caster. - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } - break; + if( status_isimmune(bl) ) + { + clif->skill_nodamage(src,bl,skill_id,skill_lv,0); + break; + } - case WA_SYMPHONY_OF_LOVER: - case MI_RUSH_WINDMILL: - case MI_ECHOSONG: - if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) - sc_start4(bl,type,100,skill_lv,6*skill_lv,(sd?pc_checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill_get_time(skill_id,skill_lv)); - else if( sd ) { // Only shows effects on caster. - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - party_foreachsamemap(skill_area_sub, sd, skill_get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill_castend_nodamage_id); - } - break; + heal = 120 * skill_lv + status_get_max_hp(bl) * (2 + skill_lv) / 100; + status_heal(bl, heal, 0, 0); - case MI_HARMONIZE: - if( src != bl ) - clif_skill_nodamage(src, src, skill_id, skill_lv, sc_start(src, type, 100, skill_lv, skill_get_time(skill_id,skill_lv))); - clif_skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id,skill_lv))); - break; + if( (tsc && tsc->opt1) && (rnd()%100 < ((skill_lv * 5) + (status_get_dex(src) + status_get_lv(src)) / 4) - (1 + (rnd() % 10))) ) + { + status_change_end(bl, SC_STONE, INVALID_TIMER); + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STUN, INVALID_TIMER); + status_change_end(bl, SC_POISON, INVALID_TIMER); + status_change_end(bl, SC_SILENCE, INVALID_TIMER); + status_change_end(bl, SC_BLIND, INVALID_TIMER); + status_change_end(bl, SC_HALLUCINATION, INVALID_TIMER); + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + } - case WM_DEADHILLHERE: - if( bl->type == BL_PC ) { - if( !status_isdead(bl) ) - break; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; + case SR_GENTLETOUCH_CHANGE: + case SR_GENTLETOUCH_REVITALIZE: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start2(bl,type,100,skill_lv,src->id,skill->get_time(skill_id,skill_lv))); + break; + case WA_SWING_DANCE: + case WA_MOONLIT_SERENADE: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + else if( sd ) { // Only shows effects on caster. + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); + } + break; - if( rnd()%100 < 88 + 2 * skill_lv ) { - int heal = tstatus->sp; - if( heal <= 0 ) - heal = 1; - tstatus->hp = heal; - tstatus->sp -= tstatus->sp * ( 120 - 20 * skill_lv ) / 100; - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - pc_revive((TBL_PC*)bl,heal,0); - clif_resurrection(bl,1); + case WA_SYMPHONY_OF_LOVER: + case MI_RUSH_WINDMILL: + case MI_ECHOSONG: + if( sd == NULL || sd->status.party_id == 0 || (flag & 1) ) + sc_start4(bl,type,100,skill_lv,6*skill_lv,(sd?pc_checkskill(sd,WM_LESSON):0),(sd?sd->status.job_level:0),skill->get_time(skill_id,skill_lv)); + else if( sd ) { // Only shows effects on caster. + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + party_foreachsamemap(skill->area_sub, sd, skill->get_splash(skill_id, skill_lv), src, skill_id, skill_lv, tick, flag|BCT_PARTY|1, skill->castend_nodamage_id); } - } - break; + break; - case WM_SIRCLEOFNATURE: - flag |= BCT_SELF|BCT_PARTY|BCT_GUILD; - case WM_VOICEOFSIREN: - if( skill_id != WM_SIRCLEOFNATURE ) - flag &= ~BCT_SELF; - if( flag&1 ) { - sc_start2(bl,type,(skill_id==WM_VOICEOFSIREN)?20+10*skill_lv:100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill_get_time(skill_id,skill_lv)); - } else { - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + case MI_HARMONIZE: + if( src != bl ) + clif->skill_nodamage(src, src, skill_id, skill_lv, sc_start(src, type, 100, skill_lv, skill->get_time(skill_id,skill_lv))); + clif->skill_nodamage(src, bl, skill_id, skill_lv, sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id,skill_lv))); + break; - case WM_GLOOMYDAY: - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - if( dstsd && ( pc_checkskill(dstsd,KN_BRANDISHSPEAR) || pc_checkskill(dstsd,LK_SPIRALPIERCE) || - pc_checkskill(dstsd,CR_SHIELDCHARGE) || pc_checkskill(dstsd,CR_SHIELDBOOMERANG) || - pc_checkskill(dstsd,PA_SHIELDCHAIN) || pc_checkskill(dstsd,LG_SHIELDPRESS) ) ) - { - sc_start(bl,SC_GLOOMYDAY_SK,100,skill_lv,skill_get_time(skill_id,skill_lv)); - break; + case WM_DEADHILLHERE: + if( bl->type == BL_PC ) { + if( !status_isdead(bl) ) + break; + + if( rnd()%100 < 88 + 2 * skill_lv ) { + int heal = tstatus->sp; + if( heal <= 0 ) + heal = 1; + tstatus->hp = heal; + tstatus->sp -= tstatus->sp * ( 120 - 20 * skill_lv ) / 100; + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + pc_revive((TBL_PC*)bl,heal,0); + clif->resurrection(bl,1); + } } - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); - break; + break; - case WM_SATURDAY_NIGHT_FEVER: - if( flag&1 ) { // Affect to all targets arround the caster and caster too. - if( !(tsc && tsc->data[type]) ) - sc_start(bl, type, 100, skill_lv,skill_get_time(skill_id, skill_lv)); - } else if( flag&2 ) { - if( src->id != bl->id && battle_check_target(src,bl,BCT_ENEMY) > 0 ) - status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); - } else if( sd ) { - short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4; - if( !sd->status.party_id || (rnd()%100 > chance)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0); - break; + case WM_SIRCLEOFNATURE: + flag |= BCT_SELF|BCT_PARTY|BCT_GUILD; + case WM_VOICEOFSIREN: + if( skill_id != WM_SIRCLEOFNATURE ) + flag &= ~BCT_SELF; + if( flag&1 ) { + sc_start2(bl,type,(skill_id==WM_VOICEOFSIREN)?20+10*skill_lv:100,skill_lv,(skill_id==WM_VOICEOFSIREN)?src->id:0,skill->get_time(skill_id,skill_lv)); + } else { + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),(skill_id==WM_VOICEOFSIREN)?BL_CHAR|BL_SKILL:BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - if( map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id,skill_lv), - BL_PC, src, skill_id, skill_lv, tick, BCT_ENEMY, skill_area_sub_count) > 7 ) - flag |= 2; - else - flag |= 1; - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF, skill_castend_nodamage_id); - clif_skill_nodamage(src, bl, skill_id, skill_lv, - sc_start(src,SC_STOP,100,skill_lv,skill_get_time2(skill_id,skill_lv))); - if( flag&2 ) // Dealed here to prevent conflicts - status_fix_damage(src,bl,9999,clif_damage(src,bl,tick,0,0,9999,0,0,0)); - } - break; + break; - case WM_SONG_OF_MANA: - case WM_DANCE_WITH_WUG: - case WM_LERADS_DEW: - if( flag&1 ) { // These affect to to all party members near the caster. - struct status_change *sc = status_get_sc(src); - if( sc && sc->data[type] ) { - sc_start2(bl,type,100,skill_lv,sc->data[type]->val2,skill_get_time(skill_id,skill_lv)); - } - } else if( sd ) { - short lv = (short)skill_lv; - int count = skill_check_pc_partner(sd,skill_id,&lv,skill_get_splash(skill_id,skill_lv),1); - if( sc_start2(bl,type,100,skill_lv,count,skill_get_time(skill_id,skill_lv)) ) - party_foreachsamemap(skill_area_sub,sd,skill_get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); + case WM_GLOOMYDAY: + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + if( dstsd && ( pc_checkskill(dstsd,KN_BRANDISHSPEAR) || pc_checkskill(dstsd,LK_SPIRALPIERCE) || + pc_checkskill(dstsd,CR_SHIELDCHARGE) || pc_checkskill(dstsd,CR_SHIELDBOOMERANG) || + pc_checkskill(dstsd,PA_SHIELDCHAIN) || pc_checkskill(dstsd,LG_SHIELDPRESS) ) ) + { + sc_start(bl,SC_GLOOMYDAY_SK,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; + } + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + break; - } - break; + case WM_SATURDAY_NIGHT_FEVER: + if( flag&1 ) { // Affect to all targets arround the caster and caster too. + if( !(tsc && tsc->data[type]) ) + sc_start(bl, type, 100, skill_lv,skill->get_time(skill_id, skill_lv)); + } else if( flag&2 ) { + if( src->id != bl->id && battle->check_target(src,bl,BCT_ENEMY) > 0 ) + status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0)); + } else if( sd ) { + short chance = sstatus->int_/6 + sd->status.job_level/5 + skill_lv*4; + if( !sd->status.party_id || (rnd()%100 > chance)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0); + break; + } + if( map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id,skill_lv), + BL_PC, src, skill_id, skill_lv, tick, BCT_ENEMY, skill->area_sub_count) > 7 ) + flag |= 2; + else + flag |= 1; + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|BCT_SELF, skill->castend_nodamage_id); + clif->skill_nodamage(src, bl, skill_id, skill_lv, + sc_start(src,SC_STOP,100,skill_lv,skill->get_time2(skill_id,skill_lv))); + if( flag&2 ) // Dealed here to prevent conflicts + status_fix_damage(src,bl,9999,clif->damage(src,bl,tick,0,0,9999,0,0,0)); + } + break; - case WM_MELODYOFSINK: - case WM_BEYOND_OF_WARCRY: - case WM_UNLIMITED_HUMMING_VOICE: - if( flag&1 ) { - sc_start2(bl,type,100,skill_lv,skill_area_temp[0],skill_get_time(skill_id,skill_lv)); - } else { // These affect to all targets arround the caster. - short lv = (short)skill_lv; - skill_area_temp[0] = (sd) ? skill_check_pc_partner(sd,skill_id,&lv,skill_get_splash(skill_id,skill_lv),1) : 50; // 50% chance in non BL_PC (clones). - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + case WM_SONG_OF_MANA: + case WM_DANCE_WITH_WUG: + case WM_LERADS_DEW: + if( flag&1 ) { // These affect to to all party members near the caster. + struct status_change *sc = status_get_sc(src); + if( sc && sc->data[type] ) { + sc_start2(bl,type,100,skill_lv,sc->data[type]->val2,skill->get_time(skill_id,skill_lv)); + } + } else if( sd ) { + short lv = (short)skill_lv; + int count = skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1); + if( sc_start2(bl,type,100,skill_lv,count,skill->get_time(skill_id,skill_lv)) ) + party_foreachsamemap(skill->area_sub,sd,skill->get_splash(skill_id,skill_lv),src,skill_id,skill_lv,tick,flag|BCT_PARTY|1,skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); - case WM_RANDOMIZESPELL: { - int improv_skill_id = 0, improv_skill_lv; - do { - i = rnd() % MAX_SKILL_IMPROVISE_DB; - improv_skill_id = skill_improvise_db[i].skill_id; - } while( improv_skill_id == 0 || rnd()%10000 >= skill_improvise_db[i].per ); - improv_skill_lv = 4 + skill_lv; - clif_skill_nodamage (src, bl, skill_id, skill_lv, 1); + } + break; - if( sd ) { - sd->state.abra_flag = 2; - sd->skillitem = improv_skill_id; - sd->skillitemlv = improv_skill_lv; - clif_item_skill(sd, improv_skill_id, improv_skill_lv); - } else { - struct unit_data *ud = unit_bl2ud(src); - int inf = skill_get_inf(improv_skill_id); - int target_id = 0; - if (!ud) break; - if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { - if (src->type == BL_PET) - bl = (struct block_list*)((TBL_PET*)src)->msd; - if (!bl) bl = src; - unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv); + case WM_MELODYOFSINK: + case WM_BEYOND_OF_WARCRY: + case WM_UNLIMITED_HUMMING_VOICE: + if( flag&1 ) { + sc_start2(bl,type,100,skill_lv,skill_area_temp[0],skill->get_time(skill_id,skill_lv)); + } else { // These affect to all targets arround the caster. + short lv = (short)skill_lv; + skill_area_temp[0] = (sd) ? skill->check_pc_partner(sd,skill_id,&lv,skill->get_splash(skill_id,skill_lv),1) : 50; // 50% chance in non BL_PC (clones). + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),BL_PC, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; + + case WM_RANDOMIZESPELL: { + int improv_skill_id = 0, improv_skill_lv; + do { + i = rnd() % MAX_SKILL_IMPROVISE_DB; + improv_skill_id = skill_improvise_db[i].skill_id; + } while( improv_skill_id == 0 || rnd()%10000 >= skill_improvise_db[i].per ); + improv_skill_lv = 4 + skill_lv; + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + + if( sd ) { + sd->state.abra_flag = 2; + sd->skillitem = improv_skill_id; + sd->skillitemlv = improv_skill_lv; + clif->item_skill(sd, improv_skill_id, improv_skill_lv); } else { - if (ud->target) - target_id = ud->target; - else switch (src->type) { - case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; - case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; - } - if (!target_id) - break; - if (skill_get_casttype(improv_skill_id) == CAST_GROUND) { - bl = map_id2bl(target_id); + struct unit_data *ud = unit_bl2ud(src); + int inf = skill->get_inf(improv_skill_id); + if (!ud) break; + if (inf&INF_SELF_SKILL || inf&INF_SUPPORT_SKILL) { + if (src->type == BL_PET) + bl = (struct block_list*)((TBL_PET*)src)->msd; if (!bl) bl = src; - unit_skilluse_pos(src, bl->x, bl->y, improv_skill_id, improv_skill_lv); - } else - unit_skilluse_id(src, target_id, improv_skill_id, improv_skill_lv); + unit_skilluse_id(src, bl->id, improv_skill_id, improv_skill_lv); + } else { + int target_id = 0; + if (ud->target) + target_id = ud->target; + else switch (src->type) { + case BL_MOB: target_id = ((TBL_MOB*)src)->target_id; break; + case BL_PET: target_id = ((TBL_PET*)src)->target_id; break; + } + if (!target_id) + break; + if (skill->get_casttype(improv_skill_id) == CAST_GROUND) { + bl = map_id2bl(target_id); + if (!bl) bl = src; + unit_skilluse_pos(src, bl->x, bl->y, improv_skill_id, improv_skill_lv); + } else + unit_skilluse_id(src, target_id, improv_skill_id, improv_skill_lv); + } } } - } - break; - + break; - case RETURN_TO_ELDICASTES: - case ALL_GUARDIAN_RECALL: - if( sd ) - { - short x, y; // Destiny position. - unsigned short mapindex; - if( skill_id == RETURN_TO_ELDICASTES) - { - x = 198; - y = 187; - mapindex = mapindex_name2id(MAP_DICASTES); - } - else + case RETURN_TO_ELDICASTES: + case ALL_GUARDIAN_RECALL: + if( sd ) { - x = 44; - y = 151; - mapindex = mapindex_name2id(MAP_MORA); - } + short x, y; // Destiny position. + unsigned short mapindex; - if(!mapindex) - { //Given map not found? - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - map_freeblock_unlock(); - return 0; + if( skill_id == RETURN_TO_ELDICASTES) + { + x = 198; + y = 187; + mapindex = mapindex_name2id(MAP_DICASTES); + } + else + { + x = 44; + y = 151; + mapindex = mapindex_name2id(MAP_MORA); + } + + if(!mapindex) + { //Given map not found? + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + map_freeblock_unlock(); + return 0; + } + pc_setpos(sd, mapindex, x, y, CLR_TELEPORT); } - pc_setpos(sd, mapindex, x, y, CLR_TELEPORT); - } - break; + break; - case GM_SANDMAN: - if( tsc ) { - if( tsc->opt1 == OPT1_SLEEP ) - tsc->opt1 = 0; - else - tsc->opt1 = OPT1_SLEEP; - clif_changeoption(bl); - clif_skill_nodamage (src, bl, skill_id, skill_lv, 1); - } - break; + case GM_SANDMAN: + if( tsc ) { + if( tsc->opt1 == OPT1_SLEEP ) + tsc->opt1 = 0; + else + tsc->opt1 = OPT1_SLEEP; + clif->changeoption(bl); + clif->skill_nodamage (src, bl, skill_id, skill_lv, 1); + } + break; - case SO_ARRULLO: - { - // [(15 + 5 * Skill Level) + ( Caster’s INT / 5 ) + ( Caster’s Job Level / 5 ) - ( Target’s INT / 6 ) - ( Target’s LUK / 10 )] % - int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd)?sd->status.job_level:0; - rate -= status_get_int(bl)/6 - status_get_luk(bl)/10; - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - sc_start2(bl, type, rate, skill_lv, 1, skill_get_time(skill_id, skill_lv)); - } - break; + case SO_ARRULLO: + { + // [(15 + 5 * Skill Level) + ( Caster’s INT / 5 ) + ( Caster’s Job Level / 5 ) - ( Target’s INT / 6 ) - ( Target’s LUK / 10 )] % + int rate = (15 + 5 * skill_lv) + status_get_int(src)/5 + (sd ? sd->status.job_level : 0); + rate -= status_get_int(bl)/6 - status_get_luk(bl)/10; + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + sc_start2(bl, type, rate, skill_lv, 1, skill->get_time(skill_id, skill_lv)); + } + break; - case WM_LULLABY_DEEPSLEEP: - if( flag&1 ){ - //[(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Caster’s Base Level / 15) + (Caster’s Job Level / 5)] % - int rate = (4 * skill_lv) + ( (sd) ? pc_checkskill(sd,WM_LESSON)*2 + sd->status.job_level/5 : 0 ) + status_get_lv(src) / 15; - if( bl != src ) - sc_start(bl,type,rate,skill_lv,skill_get_time(skill_id,skill_lv)); - }else { - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ALL|1, skill_castend_nodamage_id); - } - break; + case WM_LULLABY_DEEPSLEEP: + if( flag&1 ){ + //[(Skill Level x 4) + (Voice Lessons Skill Level x 2) + (Caster’s Base Level / 15) + (Caster’s Job Level / 5)] % + int rate = (4 * skill_lv) + ( (sd) ? pc_checkskill(sd,WM_LESSON)*2 + sd->status.job_level/5 : 0 ) + status_get_lv(src) / 15; + if( bl != src ) + sc_start(bl,type,rate,skill_lv,skill->get_time(skill_id,skill_lv)); + }else { + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ALL|1, skill->castend_nodamage_id); + } + break; - case SO_SUMMON_AGNI: - case SO_SUMMON_AQUA: - case SO_SUMMON_VENTUS: - case SO_SUMMON_TERA: - if( sd ) { - int elemental_class = skill_get_elemental_type(skill_id,skill_lv); + case SO_SUMMON_AGNI: + case SO_SUMMON_AQUA: + case SO_SUMMON_VENTUS: + case SO_SUMMON_TERA: + if( sd ) { + int elemental_class = skill->get_elemental_type(skill_id,skill_lv); - // Remove previous elemental fisrt. - if( sd->ed ) - elemental_delete(sd->ed,0); + // Remove previous elemental fisrt. + if( sd->ed ) + elemental_delete(sd->ed,0); - // Summoning the new one. - if( !elemental_create(sd,elemental_class,skill_get_time(skill_id,skill_lv)) ) { - clif_skill_fail(sd,skill_id,0,0); - break; + // Summoning the new one. + if( !elemental_create(sd,elemental_class,skill->get_time(skill_id,skill_lv)) ) { + clif->skill_fail(sd,skill_id,0,0); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + break; - case SO_EL_CONTROL: - if( sd ) { - int mode = EL_MODE_PASSIVE; // Standard mode. + case SO_EL_CONTROL: + if( sd ) { + int mode = EL_MODE_PASSIVE; // Standard mode. - if( !sd->ed ) break; + if( !sd->ed ) break; - if( skill_lv == 4 ) {// At level 4 delete elementals. - elemental_delete(sd->ed, 0); - break; - } - switch( skill_lv ) {// Select mode bassed on skill level used. - case 2: mode = EL_MODE_ASSIST; break; - case 3: mode = EL_MODE_AGGRESSIVE; break; - } - if( !elemental_change_mode(sd->ed,mode) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( skill_lv == 4 ) {// At level 4 delete elementals. + elemental_delete(sd->ed, 0); + break; + } + switch( skill_lv ) {// Select mode bassed on skill level used. + case 2: mode = EL_MODE_ASSIST; break; + case 3: mode = EL_MODE_AGGRESSIVE; break; + } + if( !elemental_change_mode(sd->ed,mode) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; + break; - case SO_EL_ACTION: - if( sd ) { - int duration = 3000; - if( !sd->ed ) break; - sd->skill_id_old = skill_id; - elemental_action(sd->ed, bl, tick); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - switch(sd->ed->db->class_){ - case 2115:case 2124: - case 2118:case 2121: - duration = 6000; - break; - case 2116:case 2119: - case 2122:case 2125: - duration = 9000; - break; - } - skill_blockpc_start(sd, skill_id, duration); - } - break; + case SO_EL_ACTION: + if( sd ) { + int duration = 3000; + if( !sd->ed ) break; + sd->skill_id_old = skill_id; + elemental_action(sd->ed, bl, tick); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + switch(sd->ed->db->class_){ + case 2115:case 2124: + case 2118:case 2121: + duration = 6000; + break; + case 2116:case 2119: + case 2122:case 2125: + duration = 9000; + break; + } + skill->blockpc_start(sd, skill_id, duration, false); + } + break; - case SO_EL_CURE: - if( sd ) { - struct elemental_data *ed = sd->ed; - int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100; - int e_hp, e_sp; + case SO_EL_CURE: + if( sd ) { + struct elemental_data *ed = sd->ed; + int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100; + int e_hp, e_sp; - if( !ed ) break; - if( !status_charge(&sd->bl,s_hp,s_sp) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + if( !ed ) break; + if( !status_charge(&sd->bl,s_hp,s_sp) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + e_hp = ed->battle_status.max_hp * 10 / 100; + e_sp = ed->battle_status.max_sp * 10 / 100; + status_heal(&ed->bl,e_hp,e_sp,3); + clif->skill_nodamage(src,&ed->bl,skill_id,skill_lv,1); } - e_hp = ed->battle_status.max_hp * 10 / 100; - e_sp = ed->battle_status.max_sp * 10 / 100; - status_heal(&ed->bl,e_hp,e_sp,3); - clif_skill_nodamage(src,&ed->bl,skill_id,skill_lv,1); - } - break; + break; - case GN_CHANGEMATERIAL: - case SO_EL_ANALYSIS: - if( sd ) { - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - clif_skill_itemlistwindow(sd,skill_id,skill_lv); - } - break; + case GN_CHANGEMATERIAL: + case SO_EL_ANALYSIS: + if( sd ) { + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_itemlistwindow(sd,skill_id,skill_lv); + } + break; - case GN_BLOOD_SUCKER: - { - struct status_change *sc = status_get_sc(src); + case GN_BLOOD_SUCKER: + { + struct status_change *sc = status_get_sc(src); - if( sc && sc->bs_counter < skill_get_maxcount( skill_id , skill_lv) ) { - if( tsc && tsc->data[type] ){ - (sc->bs_counter)--; - status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer + if( sc && sc->bs_counter < skill->get_maxcount( skill_id , skill_lv) ) { + if( tsc && tsc->data[type] ){ + (sc->bs_counter)--; + status_change_end(src, type, INVALID_TIMER); // the first one cancels and the last one will take effect resetting the timer + } + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + sc_start2(bl, type, 100, skill_lv, src->id, skill->get_time(skill_id,skill_lv)); + (sc->bs_counter)++; + } else if( sd ) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + break; } - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - sc_start2(bl, type, 100, skill_lv, src->id, skill_get_time(skill_id,skill_lv)); - (sc->bs_counter)++; - } else if( sd ) { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); - break; } - } - break; + break; - case GN_MANDRAGORA: - if( flag&1 ) { - if ( clif_skill_nodamage(bl, src, skill_id, skill_lv, - sc_start(bl, type, 25 + 10 * skill_lv, skill_lv, skill_get_time(skill_id, skill_lv))) ) - status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skill_lv) / 100); - } else - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - break; + case GN_MANDRAGORA: + if( flag&1 ) { + if ( clif->skill_nodamage(bl, src, skill_id, skill_lv, + sc_start(bl, type, 25 + 10 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv))) ) + status_zap(bl, 0, status_get_max_sp(bl) * (25 + 5 * skill_lv) / 100); + } else + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + break; - case GN_SLINGITEM: - if( sd ) { - short ammo_id; - i = sd->equip_index[EQI_AMMO]; - if( i <= 0 ) - break; // No ammo. - ammo_id = sd->inventory_data[i]->nameid; - if( ammo_id <= 0 ) - break; - sd->itemid = ammo_id; - if( itemdb_is_GNbomb(ammo_id) ) { - if(battle_check_target(src,bl,BCT_ENEMY) > 0) {// Only attack if the target is an enemy. - if( ammo_id == 13263 ) - map_foreachincell(skill_area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - else - skill_attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag); - } else //Otherwise, it fails, shows animation and removes items. - clif_skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0); - } else if( itemdb_is_GNthrowable(ammo_id) ){ - struct script_code *script = sd->inventory_data[i]->script; - if( !script ) + case GN_SLINGITEM: + if( sd ) { + short ammo_id; + i = sd->equip_index[EQI_AMMO]; + if( i <= 0 ) + break; // No ammo. + ammo_id = sd->inventory_data[i]->nameid; + if( ammo_id <= 0 ) break; - if( dstsd ) - run_script(script,0,dstsd->bl.id,fake_nd->bl.id); - else - run_script(script,0,src->id,0); + sd->itemid = ammo_id; + if( itemdb_is_GNbomb(ammo_id) ) { + if(battle->check_target(src,bl,BCT_ENEMY) > 0) {// Only attack if the target is an enemy. + if( ammo_id == 13263 ) + map_foreachincell(skill->area_sub,bl->m,bl->x,bl->y,BL_CHAR,src,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + else + skill->attack(BF_WEAPON,src,src,bl,GN_SLINGITEM_RANGEMELEEATK,skill_lv,tick,flag); + } else //Otherwise, it fails, shows animation and removes items. + clif->skill_fail(sd,GN_SLINGITEM_RANGEMELEEATK,0xa,0); + } else if( itemdb_is_GNthrowable(ammo_id) ){ + struct script_code *script = sd->inventory_data[i]->script; + if( !script ) + break; + if( dstsd ) + run_script(script,0,dstsd->bl.id,fake_nd->bl.id); + else + run_script(script,0,src->id,0); + } } - } - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1);// This packet is received twice actually, I think it is to show the animation. - break; - - case GN_MIX_COOKING: - case GN_MAKEBOMB: - case GN_S_PHARMACY: - if( sd ) { - int qty = 1; - sd->skill_id_old = skill_id; - sd->skill_lv_old = skill_lv; - if( skill_id != GN_S_PHARMACY && skill_lv > 1 ) - qty = 10; - clif_cooking_list(sd,(skill_id - GN_MIX_COOKING) + 27,skill_id,qty,skill_id==GN_MAKEBOMB?5:6); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - } - break; - case EL_CIRCLE_OF_FIRE: - case EL_PYROTECHNIC: - case EL_HEATER: - case EL_TROPIC: - case EL_AQUAPLAY: - case EL_COOLER: - case EL_CHILLY_AIR: - case EL_GUST: - case EL_BLAST: - case EL_WILD_STORM: - case EL_PETROLOGY: - case EL_CURSED_SOIL: - case EL_UPHEAVAL: - case EL_FIRE_CLOAK: - case EL_WATER_DROP: - case EL_WIND_CURTAIN: - case EL_SOLID_SKIN: - case EL_STONE_SHIELD: - case EL_WIND_STEP: { - struct elemental_data *ele = BL_CAST(BL_ELEM, src); - if( ele ) { - sc_type type2 = type-1; - struct status_change *sc = status_get_sc(&ele->bl); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1);// This packet is received twice actually, I think it is to show the animation. + break; - if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); - } else { - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - clif_skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away. - skill_blown(src,bl,(rnd()%skill_get_blewcount(skill_id,skill_lv))+1,rand()%8,0); - sc_start(src,type2,100,skill_lv,skill_get_time(skill_id,skill_lv)); - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv)); + case GN_MIX_COOKING: + case GN_MAKEBOMB: + case GN_S_PHARMACY: + if( sd ) { + int qty = 1; + sd->skill_id_old = skill_id; + sd->skill_lv_old = skill_lv; + if( skill_id != GN_S_PHARMACY && skill_lv > 1 ) + qty = 10; + clif->cooking_list(sd,(skill_id - GN_MIX_COOKING) + 27,skill_id,qty,skill_id==GN_MAKEBOMB?5:6); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + } + break; + case EL_CIRCLE_OF_FIRE: + case EL_PYROTECHNIC: + case EL_HEATER: + case EL_TROPIC: + case EL_AQUAPLAY: + case EL_COOLER: + case EL_CHILLY_AIR: + case EL_GUST: + case EL_BLAST: + case EL_WILD_STORM: + case EL_PETROLOGY: + case EL_CURSED_SOIL: + case EL_UPHEAVAL: + case EL_FIRE_CLOAK: + case EL_WATER_DROP: + case EL_WIND_CURTAIN: + case EL_SOLID_SKIN: + case EL_STONE_SHIELD: + case EL_WIND_STEP: { + struct elemental_data *ele = BL_CAST(BL_ELEM, src); + if( ele ) { + sc_type type2 = type-1; + struct status_change *sc = status_get_sc(&ele->bl); + + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skill_id); + } else { + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away. + skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rand()%8,0); + sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)); + } } } - } - break; + break; - case EL_FIRE_MANTLE: - case EL_WATER_BARRIER: - case EL_ZEPHYR: - case EL_POWER_OF_GAIA: - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - clif_skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - skill_unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0); - break; + case EL_FIRE_MANTLE: + case EL_WATER_BARRIER: + case EL_ZEPHYR: + case EL_POWER_OF_GAIA: + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + clif->skill_damage(src, bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + skill->unitsetting(src,skill_id,skill_lv,bl->x,bl->y,0); + break; - case EL_WATER_SCREEN: { - struct elemental_data *ele = BL_CAST(BL_ELEM, src); - if( ele ) { - struct status_change *sc = status_get_sc(&ele->bl); - sc_type type2 = type-1; + case EL_WATER_SCREEN: { + struct elemental_data *ele = BL_CAST(BL_ELEM, src); + if( ele ) { + struct status_change *sc = status_get_sc(&ele->bl); + sc_type type2 = type-1; - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { - elemental_clean_single_effect(ele, skill_id); - } else { - // This not heals at the end. - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - sc_start(src,type2,100,skill_lv,skill_get_time(skill_id,skill_lv)); - sc_start(bl,type,100,src->id,skill_get_time(skill_id,skill_lv)); + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + if( (sc && sc->data[type2]) || (tsc && tsc->data[type]) ) { + elemental_clean_single_effect(ele, skill_id); + } else { + // This not heals at the end. + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + sc_start(src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv)); + sc_start(bl,type,100,src->id,skill->get_time(skill_id,skill_lv)); + } } } - } - break; + break; - case KO_KAHU_ENTEN: - case KO_HYOUHU_HUBUKI: - case KO_KAZEHU_SEIRAN: - case KO_DOHU_KOUKAI: - if(sd) { - int ttype = skill_get_ele(skill_id, skill_lv); - clif_skill_nodamage(src, bl, skill_id, skill_lv, 1); - pc_add_talisman(sd, skill_get_time(skill_id, skill_lv), 10, ttype); - } - break; + case KO_KAHU_ENTEN: + case KO_HYOUHU_HUBUKI: + case KO_KAZEHU_SEIRAN: + case KO_DOHU_KOUKAI: + if(sd) { + int ttype = skill->get_ele(skill_id, skill_lv); + clif->skill_nodamage(src, bl, skill_id, skill_lv, 1); + pc_add_talisman(sd, skill->get_time(skill_id, skill_lv), 10, ttype); + } + break; - case KO_ZANZOU: - if(sd){ - struct mob_data *md; + case KO_ZANZOU: + if(sd){ + struct mob_data *md; - md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "", SZ_SMALL, AI_NONE); - if( md ) - { - md->master_id = src->id; - md->special_state.ai = AI_ZANZOU; - if( md->deletetimer != INVALID_TIMER ) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer (gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); - mob_spawn( md ); - pc_setinvincibletimer(sd,500);// unlock target lock - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - skill_blown(src,bl,skill_get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); + md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), 2308, "", SZ_SMALL, AI_NONE); + if( md ) + { + md->master_id = src->id; + md->special_state.ai = AI_ZANZOU; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); + mob_spawn( md ); + pc_setinvincibletimer(sd,500);// unlock target lock + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + skill->blown(src,bl,skill->get_blewcount(skill_id,skill_lv),unit_getdir(bl),0); + } } - } - break; + break; - case KO_KYOUGAKU: - if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){ - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - }else if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case KO_KYOUGAKU: + if( dstsd && tsc && !tsc->data[type] && rand()%100 < tstatus->int_/2 ){ + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + }else if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; - case KO_JYUSATSU: - if( dstsd && tsc && !tsc->data[type] && - rand()%100 < ((45+5*skill_lv) + skill_lv*5 - status_get_int(bl)/2) ){//[(Base chance of success) + (Skill Level x 5) - (int / 2)]%. - clif_skill_nodamage(src,bl,skill_id,skill_lv, - status_change_start(bl,type,10000,skill_lv,0,0,0,skill_get_time(skill_id,skill_lv),1)); - status_zap(bl, tstatus->max_hp*skill_lv*5/100 , 0); - if( status_get_lv(bl) <= status_get_lv(src) ) - status_change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); - }else if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + case KO_JYUSATSU: + if( dstsd && tsc && !tsc->data[type] && + rand()%100 < ((45+5*skill_lv) + skill_lv*5 - status_get_int(bl)/2) ){//[(Base chance of success) + (Skill Level x 5) - (int / 2)]%. + clif->skill_nodamage(src,bl,skill_id,skill_lv, + status_change_start(bl,type,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),1)); + status_zap(bl, tstatus->max_hp*skill_lv*5/100 , 0); + if( status_get_lv(bl) <= status_get_lv(src) ) + status_change_start(bl,SC_COMA,10,skill_lv,0,src->id,0,0,0); + }else if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + + case KO_GENWAKU: + if ( !map_flag_gvg(src->m) && ( dstsd || dstmd ) && battle->check_target(src,bl,BCT_ENEMY) > 0 ) { + int x = src->x, y = src->y; + + if( sd && rnd()%100 > ((45+5*skill_lv) - status_get_int(bl)/10) ){//[(Base chance of success) - (Intelligence Objectives / 10)]%. + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } - case KO_GENWAKU: - if ( !map_flag_gvg(src->m) && ( dstsd || dstmd ) && battle_check_target(src,bl,BCT_ENEMY) > 0 ) { - int x = src->x, y = src->y; + if (unit_movepos(src,bl->x,bl->y,0,0)) { + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + clif->slide(src,bl->x,bl->y) ; + sc_start(src,SC_CONFUSION,80,skill_lv,skill->get_time(skill_id,skill_lv)); + if (unit_movepos(bl,x,y,0,0)) + { + clif->skill_damage(bl,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, -1, 6); + if( bl->type == BL_PC && pc_issit((TBL_PC*)bl)) + clif->sitting(bl); //Avoid sitting sync problem + clif->slide(bl,x,y) ; + sc_start(bl,SC_CONFUSION,80,skill_lv,skill->get_time(skill_id,skill_lv)); + } + } + } + break; - if( sd && rnd()%100 > ((45+5*skill_lv) - status_get_int(bl)/10) ){//[(Base chance of success) - (Intelligence Objectives / 10)]%. - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case OB_AKAITSUKI: + case OB_OBOROGENSOU: + if( sd && ( (skill_id == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters. + || is_boss(bl) ) ){ // Does not work on Boss monsters. + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; } + case KO_IZAYOI: + case OB_ZANGETSU: + case KG_KYOMU: + case KG_KAGEMUSYA: + clif->skill_nodamage(src,bl,skill_id,skill_lv, + sc_start(bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv))); + clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + break; - if (unit_movepos(src,bl->x,bl->y,0,0)) { - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - clif_slide(src,bl->x,bl->y) ; - sc_start(src,SC_CONFUSION,80,skill_lv,skill_get_time(skill_id,skill_lv)); - if (unit_movepos(bl,x,y,0,0)) - { - clif_skill_damage(bl,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, -1, 6); - if( bl->type == BL_PC && pc_issit((TBL_PC*)bl)) - clif_sitting(bl); //Avoid sitting sync problem - clif_slide(bl,x,y) ; - sc_start(bl,SC_CONFUSION,80,skill_lv,skill_get_time(skill_id,skill_lv)); + case KG_KAGEHUMI: + if( flag&1 ){ + if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) || + tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || + tsc->data[SC_MARIONETTE] || tsc->data[SC_HARMONIZE])){ + sc_start(src, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + status_change_end(bl, SC_HIDING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKING, INVALID_TIMER); + status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); + status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); + status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); + status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); + status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); + } + if( skill_area_temp[2] == 1 ){ + clif->skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + sc_start(src, SC_STOP, 100, skill_lv, skill->get_time(skill_id, skill_lv)); } + }else{ + skill_area_temp[2] = 0; + map_foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill->castend_nodamage_id); } - } - break; - - case OB_AKAITSUKI: - case OB_OBOROGENSOU: - if( sd && ( (skill_id == OB_OBOROGENSOU && bl->type == BL_MOB) // This skill does not work on monsters. - || is_boss(bl) ) ){ // Does not work on Boss monsters. - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); break; - } - case KO_IZAYOI: - case OB_ZANGETSU: - case KG_KYOMU: - case KG_KAGEMUSYA: - clif_skill_nodamage(src,bl,skill_id,skill_lv, - sc_start(bl,type,100,skill_lv,skill_get_time(skill_id,skill_lv))); - clif_skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - break; - case KG_KAGEHUMI: - if( flag&1 ){ - if(tsc && ( tsc->option&(OPTION_CLOAK|OPTION_HIDE) || - tsc->data[SC_CAMOUFLAGE] || tsc->data[SC__SHADOWFORM] || - tsc->data[SC_MARIONETTE] || tsc->data[SC_HARMONIZE])){ - sc_start(src, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - status_change_end(bl, SC_HIDING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); - status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); - status_change_end(bl, SC_MARIONETTE, INVALID_TIMER); - status_change_end(bl, SC_HARMONIZE, INVALID_TIMER); - } - if( skill_area_temp[2] == 1 ){ - clif_skill_damage(src,src,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - sc_start(src, SC_STOP, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - } - }else{ - skill_area_temp[2] = 0; - map_foreachinrange(skill_area_sub, bl, skill_get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|SD_SPLASH|1, skill_castend_nodamage_id); - } - break; + case MH_SILENT_BREEZE: { + struct status_change *ssc = status_get_sc(src); + struct block_list *m_bl = battle->get_master(src); + const enum sc_type scs[] = { + SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION + }; + int heal; + if(tsc){ + for (i = 0; i < ARRAYLENGTH(scs); i++) { + if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); + } + if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target + status_change_start(bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + } + heal = status_get_matk_min(src)*4; + status_heal(bl, heal, 0, 7); + + //now inflict silence on everyone + if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun + status_change_start(src, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + if(m_bl){ + struct status_change *msc = status_get_sc(m_bl); + if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master + status_change_start(m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill->get_time(skill_id, skill_lv),1|2|8); + } + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + } + break; + case MH_OVERED_BOOST: + if (hd){ + struct block_list *s_bl = battle->get_master(src); + if(hd->homunculus.hunger>50) //reduce hunger + hd->homunculus.hunger = hd->homunculus.hunger/2; + else + hd->homunculus.hunger = min(1,hd->homunculus.hunger); + if(s_bl && s_bl->type==BL_PC){ + status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp + clif->send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info + sc_start(s_bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); //gene bonus + } + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + } + break; + case MH_GRANITIC_ARMOR: + case MH_PYROCLASTIC: { + struct block_list *s_bl = battle->get_master(src); + if(s_bl) + sc_start2(s_bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); //start on master + sc_start2(bl, type, 100, skill_lv, hd->homunculus.level, skill->get_time(skill_id, skill_lv)); + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + } + break; - case MH_SILENT_BREEZE: { - struct status_change *ssc = status_get_sc(src); - struct block_list *m_bl = battle_get_master(src); - const enum sc_type scs[] = { - SC_MANDRAGORA, SC_HARMONIZE, SC_DEEPSLEEP, SC_VOICEOFSIREN, SC_SLEEP, SC_CONFUSION, SC_HALLUCINATION - }; - int heal; - if(tsc){ - for (i = 0; i < ARRAYLENGTH(scs); i++) { - if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); - } - if (!tsc->data[SC_SILENCE]) //put inavoidable silence on target - status_change_start(bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8); - } - heal = status_get_matk_min(src)*4; - status_heal(bl, heal, 0, 7); - - //now inflict silence on everyone - if(ssc && !ssc->data[SC_SILENCE]) //put inavoidable silence on homun - status_change_start(src, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8); - if(m_bl){ - struct status_change *msc = status_get_sc(m_bl); - if(msc && !msc->data[SC_SILENCE]) //put inavoidable silence on master - status_change_start(m_bl, SC_SILENCE, 100, skill_lv, 0,0,0, skill_get_time(skill_id, skill_lv),1|2|8); - } - if (hd) - skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv)); - } - break; - case MH_OVERED_BOOST: - if (hd){ - struct block_list *s_bl = battle_get_master(src); - if(hd->homunculus.hunger>50) //reduce hunger - hd->homunculus.hunger = hd->homunculus.hunger/2; - else - hd->homunculus.hunger = min(1,hd->homunculus.hunger); - if(s_bl && s_bl->type==BL_PC){ - status_set_sp(s_bl,status_get_max_sp(s_bl)/2,0); //master drain 50% sp - clif_send_homdata(((TBL_PC *)s_bl), SP_HUNGRY, hd->homunculus.hunger); //refresh hunger info - sc_start(s_bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)); //gene bonus - } - sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv)); - } - break; - case MH_GRANITIC_ARMOR: - case MH_PYROCLASTIC: { - struct block_list *s_bl = battle_get_master(src); - if(s_bl) sc_start2(s_bl, type, 100, skill_lv, hd->homunculus.level, skill_get_time(skill_id, skill_lv)); //start on master - sc_start2(bl, type, 100, skill_lv, hd->homunculus.level, skill_get_time(skill_id, skill_lv)); - if (hd) skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv)); - } - break; - - case MH_LIGHT_OF_REGENE: - if(hd){ - hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) - if(sd) clif_send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info - } - //don't break need to start status and start block timer - case MH_STYLE_CHANGE: - case MH_MAGMA_FLOW: - case MH_PAIN_KILLER: - sc_start(bl, type, 100, skill_lv, skill_get_time(skill_id, skill_lv)); - if (hd) - skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv)); - break; - case MH_SUMMON_LEGION: - { - int summons[5] = {1004, 1303, 1303, 1994, 1994}; - int qty[5] = {3 , 3 , 4 , 4 , 5}; - struct mob_data *md; - int i; - - for(i=0; i<qty[skill_lv - 1]; i++){ //easy way - md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK); - if (md) { - md->master_id = src->id; - if (md->deletetimer != INVALID_TIMER) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer(gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); - mob_spawn(md); //Now it is ready for spawning. - sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_ASSIST, 0, 60000); - } - } - if (hd) - skill_blockhomun_start(hd, skill_id, skill_get_cooldown(skill_id, skill_lv)); - } - break; - default: - ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skill_id); - clif_skill_nodamage(src,bl,skill_id,skill_lv,1); - map_freeblock_unlock(); - return 1; + case MH_LIGHT_OF_REGENE: + if(hd){ + hd->homunculus.intimacy = 251; //change to neutral (can't be cast if < 750) + if(sd) clif->send_homdata(sd, SP_INTIMATE, hd->homunculus.intimacy); //refresh intimacy info + } + //don't break need to start status and start block timer + case MH_STYLE_CHANGE: + case MH_MAGMA_FLOW: + case MH_PAIN_KILLER: + sc_start(bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)); + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + break; + case MH_SUMMON_LEGION: + { + int summons[5] = {1004, 1303, 1303, 1994, 1994}; + int qty[5] = {3 , 3 , 4 , 4 , 5}; + struct mob_data *md; + int i; + + for(i=0; i<qty[skill_lv - 1]; i++){ //easy way + md = mob_once_spawn_sub(src, src->m, src->x, src->y, status_get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK); + if (md) { + md->master_id = src->id; + if (md->deletetimer != INVALID_TIMER) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer(gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); + mob_spawn(md); //Now it is ready for spawning. + sc_start4(&md->bl, SC_MODECHANGE, 100, 1, 0, MD_ASSIST, 0, 60000); + } + } + if (hd) + skill->blockhomun_start(hd, skill_id, skill->get_cooldown(skill_id, skill_lv)); + } + break; + default: + ShowWarning("skill_castend_nodamage_id: Unknown skill used:%d\n",skill_id); + clif->skill_nodamage(src,bl,skill_id,skill_lv,1); + map_freeblock_unlock(); + return 1; } if(skill_id != SR_CURSEDCIRCLE){ @@ -9062,17 +9045,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, ui mobskill_event(dstmd, src, tick, MSC_SKILLUSED|(skill_id<<16)); } - if( sd && !(flag&1) ) - {// ensure that the skill last-cast tick is recorded + if( sd && !(flag&1) ) { // ensure that the skill last-cast tick is recorded sd->canskill_tick = gettick(); - if( sd->state.arrow_atk ) - {// consume arrow on last invocation to this skill. - battle_consume_ammo(sd, skill_id, skill_lv); + if( sd->state.arrow_atk ) { // consume arrow on last invocation to this skill. + battle->consume_ammo(sd, skill_id, skill_lv); } - skill_onskillusage(sd, bl, skill_id, tick); + skill->onskillusage(sd, bl, skill_id, tick); // perform skill requirement consumption - skill_consume_requirement(sd,skill_id,skill_lv,2); + skill->consume_requirement(sd,skill_id,skill_lv,2); } map_freeblock_unlock(); @@ -9143,13 +9124,13 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) switch (ud->skill_id) { //These should become skill_castend_pos case WE_CALLPARTNER: - if(sd) clif_callpartner(sd); + if(sd) clif->callpartner(sd); case WE_CALLPARENT: case WE_CALLBABY: case AM_RESURRECTHOMUN: case PF_SPIDERWEB: //Find a random spot to place the skill. [Skotlex] - inf2 = skill_get_splash(ud->skill_id, ud->skill_lv); + inf2 = skill->get_splash(ud->skill_id, ud->skill_lv); ud->skillx = target->x + inf2; ud->skilly = target->y + inf2; if (inf2 && !map_random_dir(target, &ud->skillx, &ud->skilly)) { @@ -9157,12 +9138,12 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) ud->skilly = target->y; } ud->skilltimer=tid; - return skill_castend_pos(tid,tick,id,data); + return skill->castend_pos(tid,tick,id,data); case GN_WALLOFTHORN: ud->skillx = target->x; ud->skilly = target->y; ud->skilltimer = tid; - return skill_castend_pos(tid,tick,id,data); + return skill->castend_pos(tid,tick,id,data); } if(ud->skill_id == RG_BACKSTAP) { @@ -9172,10 +9153,9 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) } } - if( ud->skill_id == PR_TURNUNDEAD ) - { + if( ud->skill_id == PR_TURNUNDEAD ) { struct status_data *tstatus = status_get_status_data(target); - if( !battle_check_undead(tstatus->race, tstatus->def_ele) ) + if( !battle->check_undead(tstatus->race, tstatus->def_ele) ) break; } @@ -9187,16 +9167,16 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) if( ud->skill_id == PR_LEXDIVINA || ud->skill_id == MER_LEXDIVINA ) { sc = status_get_sc(target); - if( battle_check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE]) ) + if( battle->check_target(src,target, BCT_ENEMY) <= 0 && (!sc || !sc->data[SC_SILENCE]) ) { //If it's not an enemy, and not silenced, you can't use the skill on them. [Skotlex] - clif_skill_nodamage (src, target, ud->skill_id, ud->skill_lv, 0); + clif->skill_nodamage (src, target, ud->skill_id, ud->skill_lv, 0); break; } } else { // Check target validity. - inf = skill_get_inf(ud->skill_id); - inf2 = skill_get_inf2(ud->skill_id); + inf = skill->get_inf(ud->skill_id); + inf2 = skill->get_inf2(ud->skill_id); if(inf&INF_ATTACK_SKILL || (inf&INF_SELF_SKILL && inf2&INF2_NO_TARGET_SELF) //Combo skills @@ -9216,20 +9196,25 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) inf &= ~BCT_NEUTRAL; } + if( sd && (inf2&INF2_CHORUS_SKILL) && skill->check_pc_partner(sd, ud->skill_id, &ud->skill_lv, 1, 0) < 1 ) { + clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_NEED_HELPER, 0); + break; + } + if( ud->skill_id >= SL_SKE && ud->skill_id <= SL_SKA && target->type == BL_MOB ) { if( ((TBL_MOB*)target)->class_ == MOBID_EMPERIUM ) break; } - else if (inf && battle_check_target(src, target, inf) <= 0){ - if (sd) clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + else if (inf && battle->check_target(src, target, inf) <= 0){ + if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); break; } if(inf&BCT_ENEMY && (sc = status_get_sc(target)) && sc->data[SC_FOGWALL] && rnd() % 100 < 75) { //Fogwall makes all offensive-type targetted skills fail at 75% - if (sd) clif_skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0); + if (sd) clif->skill_fail(sd, ud->skill_id, USESKILL_FAIL_LEVEL, 0); break; } } @@ -9241,36 +9226,35 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) if(md) { md->last_thinktime=tick +MIN_MOBTHINKTIME; if(md->skill_idx >= 0 && md->db->skill[md->skill_idx].emotion >= 0) - clif_emotion(src, md->db->skill[md->skill_idx].emotion); + clif->emotion(src, md->db->skill[md->skill_idx].emotion); } if(src != target && battle_config.skill_add_range && - !check_distance_bl(src, target, skill_get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range)) + !check_distance_bl(src, target, skill->get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range)) { if (sd) { - clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); if(battle_config.skill_out_range_consume) //Consume items anyway. [Skotlex] - skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,3); + skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,3); } break; } if( sd ) { - if( !skill_check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) + if( !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) break; else - skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,1); + skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1); } #ifdef OFFICIAL_WALKPATH if( !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) ) break; #endif - if( (src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) ) + if( (src->type == BL_MER || src->type == BL_HOM) && !skill->check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) ) break; - if (ud->state.running && ud->skill_id == TK_JUMPKICK) - { + if (ud->state.running && ud->skill_id == TK_JUMPKICK) { ud->state.running = 0; status_change_end(src, SC_RUN, INVALID_TIMER); flag = 1; @@ -9279,10 +9263,10 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) if (ud->walktimer != INVALID_TIMER && ud->skill_id != TK_RUN && ud->skill_id != RA_WUGDASH) unit_stop_walking(src,1); - if( !sd || sd->skillitem != ud->skill_id || skill_get_delay(ud->skill_id,ud->skill_lv) ) - ud->canact_tick = tick + skill_delayfix(src, ud->skill_id, ud->skill_lv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] + if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) + ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); //Tests show wings don't overwrite the delay but skill scrolls do. [Inkfish] if (sd) { //Cooldown application - int i, cooldown = skill_get_cooldown(ud->skill_id, ud->skill_lv); + int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv); for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. if (sd->skillcooldown[i].id == ud->skill_id){ cooldown += sd->skillcooldown[i].val; @@ -9290,31 +9274,31 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) } } if(cooldown) - skill_blockpc_start(sd, ud->skill_id, cooldown); + skill->blockpc_start(sd, ud->skill_id, cooldown, false); } if( battle_config.display_status_timers && sd ) - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); + clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); if( sd ) { switch( ud->skill_id ) { case GS_DESPERADO: - sd->canequip_tick = tick + skill_get_time(ud->skill_id, ud->skill_lv); + sd->canequip_tick = tick + skill->get_time(ud->skill_id, ud->skill_lv); break; case CR_GRANDCROSS: case NPC_GRANDDARKNESS: if( (sc = status_get_sc(src)) && sc->data[SC_STRIPSHIELD] ) { const struct TimerData *timer = get_timer(sc->data[SC_STRIPSHIELD]->timer); - if( timer && timer->func == status_change_timer && DIFF_TICK(timer->tick,gettick()+skill_get_time(ud->skill_id, ud->skill_lv)) > 0 ) + if( timer && timer->func == status_change_timer && DIFF_TICK(timer->tick,gettick()+skill->get_time(ud->skill_id, ud->skill_lv)) > 0 ) break; } - sc_start2(src, SC_STRIPSHIELD, 100, 0, 1, skill_get_time(ud->skill_id, ud->skill_lv)); + sc_start2(src, SC_STRIPSHIELD, 100, 0, 1, skill->get_time(ud->skill_id, ud->skill_lv)); break; } } - if (skill_get_state(ud->skill_id) != ST_MOVE_ENABLE) - unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skill_id, ud->skill_lv), 1); + if (skill->get_state(ud->skill_id) != ST_MOVE_ENABLE) + unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1); if(battle_config.skill_log && battle_config.skill_log&src->type) ShowInfo("Type %d, ID %d skill castend id [id =%d, lv=%d, target ID %d]\n", @@ -9323,14 +9307,14 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) map_freeblock_lock(); // SC_MAGICPOWER needs to switch states before any damage is actually dealt - skill_toggle_magicpower(src, ud->skill_id); + skill->toggle_magicpower(src, ud->skill_id); if( ud->skill_id != RA_CAMOUFLAGE ) // only normal attack and auto cast skills benefit from its bonuses status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER); - if (skill_get_casttype(ud->skill_id) == CAST_NODAMAGE) - skill_castend_nodamage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); + if (skill->get_casttype(ud->skill_id) == CAST_NODAMAGE) + skill->castend_nodamage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); else - skill_castend_damage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); + skill->castend_damage_id(src,target,ud->skill_id,ud->skill_lv,tick,flag); sc = status_get_sc(src); if(sc && sc->count) { @@ -9340,8 +9324,8 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) ud->skill_id != WZ_WATERBALL) sc->data[SC_SPIRIT]->val3 = 0; //Clear bounced spell check. - if( sc->data[SC_DANCING] && skill_get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd ) - skill_blockpc_start(sd,BD_ADAPTATION,3000); + if( sc->data[SC_DANCING] && skill->get_inf2(ud->skill_id)&INF2_SONG_DANCE && sd ) + skill->blockpc_start(sd,BD_ADAPTATION,3000, false); } if( sd && ud->skill_id != SA_ABRACADABRA && ud->skill_id != WM_RANDOMIZESPELL ) // they just set the data so leave it as it is.[Inkfish] @@ -9360,7 +9344,7 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) if (ud->skill_id == MO_EXTREMITYFIST && sd && !(sc && sc->data[SC_FOGWALL])) { //When Asura fails... (except when it fails from Fog of Wall) //Consume SP/spheres - skill_consume_requirement(sd,ud->skill_id, ud->skill_lv,1); + skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1); status_set_sp(src, 0, 0); sc = &sd->sc; if (sc->count) @@ -9368,22 +9352,30 @@ int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data) status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER); status_change_end(src, SC_BLADESTOP, INVALID_TIMER); #ifdef RENEWAL - sc_start(src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill_get_time(ud->skill_id, ud->skill_lv)); + sc_start(src, SC_EXTREMITYFIST2, 100, ud->skill_lv, skill->get_time(ud->skill_id, ud->skill_lv)); #endif } if (target && target->m == src->m) { //Move character to target anyway. - if (unit_movepos(src, src->x+3, src->y+3, 1, 1)) + int dir, x, y; + dir = map_calc_dir(src,target->x,target->y); + if( dir > 0 && dir < 4) x = -2; + else if( dir > 4 ) x = 2; + else x = 0; + if( dir > 2 && dir < 6 ) y = -2; + else if( dir == 7 || dir < 2 ) y = 2; + else y = 0; + if (unit_movepos(src, src->x+x, src->y+y, 1, 1)) { //Display movement + animation. - clif_slide(src,src->x,src->y); - clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skill_id, ud->skill_lv, 5); + clif->slide(src,src->x,src->y); + clif->skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skill_id, ud->skill_lv, 5); } - clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); } } ud->skill_id = ud->skill_lv = ud->skilltarget = 0; - if( !sd || sd->skillitem != ud->skill_id || skill_get_delay(ud->skill_id,ud->skill_lv) ) + if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) ud->canact_tick = tick; //You can't place a skill failed packet here because it would be //sent in ALL cases, even cases where skill_check_condition fails @@ -9435,23 +9427,23 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) break; if( !(src->type&battle_config.skill_reiteration) && - skill_get_unit_flag(ud->skill_id)&UF_NOREITERATION && - skill_check_unit_range(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv) + skill->get_unit_flag(ud->skill_id)&UF_NOREITERATION && + skill->check_unit_range(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv) ) { - if (sd) clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); break; } if( src->type&battle_config.skill_nofootset && - skill_get_unit_flag(ud->skill_id)&UF_NOFOOTSET && - skill_check_unit_range2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv) + skill->get_unit_flag(ud->skill_id)&UF_NOFOOTSET && + skill->check_unit_range2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv) ) { - if (sd) clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); break; } if( src->type&battle_config.land_skill_limit && - (maxcount = skill_get_maxcount(ud->skill_id, ud->skill_lv)) > 0 + (maxcount = skill->get_maxcount(ud->skill_id, ud->skill_lv)) > 0 ) { int i; for(i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i] && maxcount;i++) { @@ -9460,7 +9452,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) } if( maxcount == 0 ) { - if (sd) clif_skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); + if (sd) clif->skill_fail(sd,ud->skill_id,USESKILL_FAIL_LEVEL,0); break; } } @@ -9470,28 +9462,28 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) if (!status_check_skilluse(src, NULL, ud->skill_id, 1)) break; if(battle_config.skill_add_range && - !check_distance_blxy(src, ud->skillx, ud->skilly, skill_get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range)) { + !check_distance_blxy(src, ud->skillx, ud->skilly, skill->get_range2(src,ud->skill_id,ud->skill_lv)+battle_config.skill_add_range)) { if (sd && battle_config.skill_out_range_consume) //Consume items anyway. - skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,3); + skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,3); break; } } if( sd ) { - if( !skill_check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) + if( ud->skill_id != AL_WARP && !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) break; else - skill_consume_requirement(sd,ud->skill_id,ud->skill_lv,1); + skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1); } - if( (src->type == BL_MER || src->type == BL_HOM) && !skill_check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) ) + if( (src->type == BL_MER || src->type == BL_HOM) && !skill->check_condition_mercenary(src, ud->skill_id, ud->skill_lv, 1) ) break; if(md) { md->last_thinktime=tick +MIN_MOBTHINKTIME; if(md->skill_idx >= 0 && md->db->skill[md->skill_idx].emotion >= 0) - clif_emotion(src, md->db->skill[md->skill_idx].emotion); + clif->emotion(src, md->db->skill[md->skill_idx].emotion); } if(battle_config.skill_log && battle_config.skill_log&src->type) @@ -9501,10 +9493,10 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) if (ud->walktimer != INVALID_TIMER) unit_stop_walking(src,1); - if( !sd || sd->skillitem != ud->skill_id || skill_get_delay(ud->skill_id,ud->skill_lv) ) - ud->canact_tick = tick + skill_delayfix(src, ud->skill_id, ud->skill_lv); + if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) + ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv); if (sd) { //Cooldown application - int i, cooldown = skill_get_cooldown(ud->skill_id, ud->skill_lv); + int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv); for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses. if (sd->skillcooldown[i].id == ud->skill_id){ cooldown += sd->skillcooldown[i].val; @@ -9512,10 +9504,10 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) } } if(cooldown) - skill_blockpc_start(sd, ud->skill_id, cooldown); + skill->blockpc_start(sd, ud->skill_id, cooldown, false); } if( battle_config.display_status_timers && sd ) - clif_status_change(src, SI_ACTIONDELAY, 1, skill_delayfix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); + clif->status_change(src, SI_ACTIONDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0); // if( sd ) // { // switch( ud->skill_id ) @@ -9525,10 +9517,10 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) // break; // } // } - unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill_get_walkdelay(ud->skill_id, ud->skill_lv), 1); + unit_set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1); status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);// only normal attack and auto cast skills benefit from its bonuses map_freeblock_lock(); - skill_castend_pos2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,tick,0); + skill->castend_pos2(src,ud->skillx,ud->skilly,ud->skill_id,ud->skill_lv,tick,0); if( sd && sd->skillitem != AL_WARP ) // Warp-Portal thru items will clear data in skill_castend_map. [Inkfish] sd->skillitem = sd->skillitemlv = 0; @@ -9543,7 +9535,7 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) return 1; } while(0); - if( !sd || sd->skillitem != ud->skill_id || skill_get_delay(ud->skill_id,ud->skill_lv) ) + if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) ) ud->canact_tick = tick; ud->skill_id = ud->skill_lv = 0; if(sd) @@ -9553,7 +9545,14 @@ int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data) return 0; } - +/* skill count without self */ +static int skill_count_wos(struct block_list *bl,va_list ap) { + struct block_list* src = va_arg(ap, struct block_list*); + if( src->id != bl->id ) { + return 1; + } + return 0; +} /*========================================== * *------------------------------------------*/ @@ -9588,673 +9587,672 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui case LG_EARTHDRIVE: break; //Effect is displayed on respective switch case. default: - if(skill_get_inf(skill_id)&INF_SELF_SKILL) - clif_skill_nodamage(src,src,skill_id,skill_lv,1); + if(skill->get_inf(skill_id)&INF_SELF_SKILL) + clif->skill_nodamage(src,src,skill_id,skill_lv,1); else - clif_skill_poseffect(src,skill_id,skill_lv,x,y,tick); + clif->skill_poseffect(src,skill_id,skill_lv,x,y,tick); } // SC_MAGICPOWER needs to switch states before any damage is actually dealt - skill_toggle_magicpower(src, skill_id); + skill->toggle_magicpower(src, skill_id); - switch(skill_id) - { - case PR_BENEDICTIO: - skill_area_temp[1] = src->id; - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea(skill_area_sub, - src->m, x-i, y-i, x+i, y+i, BL_PC, - src, skill_id, skill_lv, tick, flag|BCT_ALL|1, - skill_castend_nodamage_id); - map_foreachinarea(skill_area_sub, - src->m, x-i, y-i, x+i, y+i, BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); - break; + switch(skill_id) { + case PR_BENEDICTIO: + skill_area_temp[1] = src->id; + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea(skill->area_sub, + src->m, x-i, y-i, x+i, y+i, BL_PC, + src, skill_id, skill_lv, tick, flag|BCT_ALL|1, + skill->castend_nodamage_id); + map_foreachinarea(skill->area_sub, + src->m, x-i, y-i, x+i, y+i, BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, + skill->castend_damage_id); + break; - case BS_HAMMERFALL: - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea (skill_area_sub, - src->m, x-i, y-i, x+i, y+i, BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|2, - skill_castend_nodamage_id); - break; + case BS_HAMMERFALL: + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea (skill->area_sub, + src->m, x-i, y-i, x+i, y+i, BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|2, + skill->castend_nodamage_id); + break; - case HT_DETECTING: - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea( status_change_timer_sub, - src->m, x-i, y-i, x+i,y+i,BL_CHAR, - src,NULL,SC_SIGHT,tick); - if(battle_config.traps_setting&1) - map_foreachinarea( skill_reveal_trap, - src->m, x-i, y-i, x+i,y+i,BL_SKILL); - break; + case HT_DETECTING: + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea( status_change_timer_sub, + src->m, x-i, y-i, x+i,y+i,BL_CHAR, + src,NULL,SC_SIGHT,tick); + if(battle_config.traps_setting&1) + map_foreachinarea( skill_reveal_trap, + src->m, x-i, y-i, x+i,y+i,BL_SKILL); + break; - case SR_RIDEINLIGHTNING: - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea(skill_area_sub, src->m, x-i, y-i, x+i, y+i, BL_CHAR, - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_damage_id); - break; + case SR_RIDEINLIGHTNING: + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea(skill->area_sub, src->m, x-i, y-i, x+i, y+i, BL_CHAR, + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id); + break; - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: - { //Does not consumes if the skill is already active. [Skotlex] - struct skill_unit_group *sg; - if ((sg= skill_locate_element_field(src)) != NULL && ( sg->skill_id == SA_VOLCANO || sg->skill_id == SA_DELUGE || sg->skill_id == SA_VIOLENTGALE )) - { - if (sg->limit - DIFF_TICK(gettick(), sg->tick) > 0) + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: + { //Does not consumes if the skill is already active. [Skotlex] + struct skill_unit_group *sg; + if ((sg= skill->locate_element_field(src)) != NULL && ( sg->skill_id == SA_VOLCANO || sg->skill_id == SA_DELUGE || sg->skill_id == SA_VIOLENTGALE )) { - skill_unitsetting(src,skill_id,skill_lv,x,y,0); - return 0; // not to consume items + if (sg->limit - DIFF_TICK(gettick(), sg->tick) > 0) { + skill->unitsetting(src,skill_id,skill_lv,x,y,0); + return 0; // not to consume items + } else + sg->limit = 0; //Disable it. } - else - sg->limit = 0; //Disable it. - } - skill_unitsetting(src,skill_id,skill_lv,x,y,0); - break; - } - case MG_SAFETYWALL: - case MG_FIREWALL: - case MG_THUNDERSTORM: - - case AL_PNEUMA: - case WZ_ICEWALL: - case WZ_FIREPILLAR: - case WZ_QUAGMIRE: - case WZ_VERMILION: - case WZ_STORMGUST: - case WZ_HEAVENDRIVE: - case PR_SANCTUARY: - case PR_MAGNUS: - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case MA_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_BLASTMINE: - case HT_CLAYMORETRAP: - case AS_VENOMDUST: - case AM_DEMONSTRATION: - case PF_FOGWALL: - case PF_SPIDERWEB: - case HT_TALKIEBOX: - case WE_CALLPARTNER: - case WE_CALLPARENT: - case WE_CALLBABY: - case AC_SHOWER: //Ground-placed skill implementation. - case MA_SHOWER: - case SA_LANDPROTECTOR: - case BD_LULLABY: - case BD_RICHMANKIM: - case BD_ETERNALCHAOS: - case BD_DRUMBATTLEFIELD: - case BD_RINGNIBELUNGEN: - case BD_ROKISWEIL: - case BD_INTOABYSS: - case BD_SIEGFRIED: - case BA_DISSONANCE: - case BA_POEMBRAGI: - case BA_WHISTLE: - case BA_ASSASSINCROSS: - case BA_APPLEIDUN: - case DC_UGLYDANCE: - case DC_HUMMING: - case DC_DONTFORGETME: - case DC_FORTUNEKISS: - case DC_SERVICEFORYOU: - case CG_MOONLIT: - case GS_DESPERADO: - case NJ_KAENSIN: - case NJ_BAKUENRYU: - case NJ_SUITON: - case NJ_HYOUSYOURAKU: - case NJ_RAIGEKISAI: - case NJ_KAMAITACHI: -#ifdef RENEWAL - case NJ_HUUMA: -#endif - case NPC_EVILLAND: - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - case SC_MANHOLE: - case SC_DIMENSIONDOOR: - case SC_CHAOSPANIC: - case SC_MAELSTROM: - case WM_REVERBERATION: - case WM_SEVERE_RAINSTORM: - case WM_POEMOFNETHERWORLD: - case SO_PSYCHIC_WAVE: - case SO_VACUUM_EXTREME: - case GN_WALLOFTHORN: - case GN_THORNS_TRAP: - case GN_DEMONIC_FIRE: - case GN_HELLS_PLANT: - case SO_EARTHGRAVE: - case SO_DIAMONDDUST: - case SO_FIRE_INSIGNIA: - case SO_WATER_INSIGNIA: - case SO_WIND_INSIGNIA: - case SO_EARTH_INSIGNIA: - case KO_HUUMARANKA: - case KO_MUCHANAGE: - case KO_BAKURETSU: - case KO_ZENKAI: - case MH_LAVA_SLIDE: - case MH_VOLCANIC_ASH: - case MH_POISON_MIST: - case MH_STEINWAND: - case MH_XENO_SLASHER: - flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). - case GS_GROUNDDRIFT: //Ammo should be deleted right away. - skill_unitsetting(src,skill_id,skill_lv,x,y,0); - break; - case RG_GRAFFITI: /* Graffiti [Valaris] */ - skill_clear_unitgroup(src); - skill_unitsetting(src,skill_id,skill_lv,x,y,0); - flag|=1; - break; - case HP_BASILICA: - if( sc->data[SC_BASILICA] ) - status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica - else - { // Create Basilica. Start SC on caster. Unit timer start SC on others. - skill_clear_unitgroup(src); - if( skill_unitsetting(src,skill_id,skill_lv,x,y,0) ) - sc_start4(src,type,100,skill_lv,0,0,src->id,skill_get_time(skill_id,skill_lv)); - flag|=1; + skill->unitsetting(src,skill_id,skill_lv,x,y,0); + break; } - break; - case CG_HERMODE: - skill_clear_unitgroup(src); - if ((sg = skill_unitsetting(src,skill_id,skill_lv,x,y,0))) - sc_start4(src,SC_DANCING,100, - skill_id,0,skill_lv,sg->group_id,skill_get_time(skill_id,skill_lv)); - flag|=1; - break; - case RG_CLEANER: // [Valaris] - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea(skill_graffitiremover,src->m,x-i,y-i,x+i,y+i,BL_SKILL); - break; - - case SO_WARMER: - flag|= 8; - case SO_CLOUD_KILL: - skill_unitsetting(src,skill_id,skill_lv,x,y,0); - break; - - case WZ_METEOR: { - int area = skill_get_splash(skill_id, skill_lv); - short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0; + case MG_SAFETYWALL: + case MG_FIREWALL: + case MG_THUNDERSTORM: - for( i = 0; i < 2 + (skill_lv>>1); i++ ) { - // Creates a random Cell in the Splash Area - tmpx = x - area + rnd()%(area * 2 + 1); - tmpy = y - area + rnd()%(area * 2 + 1); + case AL_PNEUMA: + case WZ_ICEWALL: + case WZ_FIREPILLAR: + case WZ_QUAGMIRE: + case WZ_VERMILION: + case WZ_STORMGUST: + case WZ_HEAVENDRIVE: + case PR_SANCTUARY: + case PR_MAGNUS: + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case MA_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_BLASTMINE: + case HT_CLAYMORETRAP: + case AS_VENOMDUST: + case AM_DEMONSTRATION: + case PF_FOGWALL: + case PF_SPIDERWEB: + case HT_TALKIEBOX: + case WE_CALLPARTNER: + case WE_CALLPARENT: + case WE_CALLBABY: + case AC_SHOWER: //Ground-placed skill implementation. + case MA_SHOWER: + case SA_LANDPROTECTOR: + case BD_LULLABY: + case BD_RICHMANKIM: + case BD_ETERNALCHAOS: + case BD_DRUMBATTLEFIELD: + case BD_RINGNIBELUNGEN: + case BD_ROKISWEIL: + case BD_INTOABYSS: + case BD_SIEGFRIED: + case BA_DISSONANCE: + case BA_POEMBRAGI: + case BA_WHISTLE: + case BA_ASSASSINCROSS: + case BA_APPLEIDUN: + case DC_UGLYDANCE: + case DC_HUMMING: + case DC_DONTFORGETME: + case DC_FORTUNEKISS: + case DC_SERVICEFORYOU: + case CG_MOONLIT: + case GS_DESPERADO: + case NJ_KAENSIN: + case NJ_BAKUENRYU: + case NJ_SUITON: + case NJ_HYOUSYOURAKU: + case NJ_RAIGEKISAI: + case NJ_KAMAITACHI: + #ifdef RENEWAL + case NJ_HUUMA: + #endif + case NPC_EVILLAND: + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + case SC_MANHOLE: + case SC_DIMENSIONDOOR: + case SC_CHAOSPANIC: + case SC_MAELSTROM: + case WM_REVERBERATION: + case WM_SEVERE_RAINSTORM: + case WM_POEMOFNETHERWORLD: + case SO_PSYCHIC_WAVE: + case SO_VACUUM_EXTREME: + case GN_WALLOFTHORN: + case GN_THORNS_TRAP: + case GN_DEMONIC_FIRE: + case GN_HELLS_PLANT: + case SO_EARTHGRAVE: + case SO_DIAMONDDUST: + case SO_FIRE_INSIGNIA: + case SO_WATER_INSIGNIA: + case SO_WIND_INSIGNIA: + case SO_EARTH_INSIGNIA: + case KO_HUUMARANKA: + case KO_MUCHANAGE: + case KO_BAKURETSU: + case KO_ZENKAI: + case MH_LAVA_SLIDE: + case MH_VOLCANIC_ASH: + case MH_POISON_MIST: + case MH_STEINWAND: + case MH_XENO_SLASHER: + flag|=1;//Set flag to 1 to prevent deleting ammo (it will be deleted on group-delete). + case GS_GROUNDDRIFT: //Ammo should be deleted right away. + skill->unitsetting(src,skill_id,skill_lv,x,y,0); + break; + case RG_GRAFFITI: /* Graffiti [Valaris] */ + skill->clear_unitgroup(src); + skill->unitsetting(src,skill_id,skill_lv,x,y,0); + flag|=1; + break; + case HP_BASILICA: + if( sc->data[SC_BASILICA] ) + status_change_end(src, SC_BASILICA, INVALID_TIMER); // Cancel Basilica + else { // Create Basilica. Start SC on caster. Unit timer start SC on others. + if( map_foreachinrange(skill_count_wos, src, 2, BL_MOB|BL_PC, src) ) { + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); + return 1; + } + + skill->clear_unitgroup(src); + if( skill->unitsetting(src,skill_id,skill_lv,x,y,0) ) + sc_start4(src,type,100,skill_lv,0,0,src->id,skill->get_time(skill_id,skill_lv)); + flag|=1; + } + break; + case CG_HERMODE: + skill->clear_unitgroup(src); + if ((sg = skill->unitsetting(src,skill_id,skill_lv,x,y,0))) + sc_start4(src,SC_DANCING,100, + skill_id,0,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv)); + flag|=1; + break; + case RG_CLEANER: // [Valaris] + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea(skill->graffitiremover,src->m,x-i,y-i,x+i,y+i,BL_SKILL); + break; - if( i == 0 && path_search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) ) - clif_skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick); + case SO_WARMER: + flag|= 8; + case SO_CLOUD_KILL: + skill->unitsetting(src,skill_id,skill_lv,x,y,0); + break; - if( i > 0 ) - skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skill_id,skill_lv,(x1<<16)|y1,0); + case WZ_METEOR: { + int area = skill->get_splash(skill_id, skill_lv); + short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0; - x1 = tmpx; - y1 = tmpy; - } + for( i = 0; i < 2 + (skill_lv>>1); i++ ) { + // Creates a random Cell in the Splash Area + tmpx = x - area + rnd()%(area * 2 + 1); + tmpy = y - area + rnd()%(area * 2 + 1); - skill_addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skill_id,skill_lv,-1,0); - } - break; + if( i == 0 && path_search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) ) + clif->skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick); - case AL_WARP: - if(sd) - { - clif_skill_warppoint(sd, skill_id, skill_lv, sd->status.save_point.map, - (skill_lv >= 2) ? sd->status.memo_point[0].map : 0, - (skill_lv >= 3) ? sd->status.memo_point[1].map : 0, - (skill_lv >= 4) ? sd->status.memo_point[2].map : 0 - ); - } - if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] ) //Should only remove after the skill has been casted. - status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); - return 0; // not to consume item. + if( i > 0 ) + skill->addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skill_id,skill_lv,(x1<<16)|y1,0); - case MO_BODYRELOCATION: - if (unit_movepos(src, x, y, 1, 1)) { -#if PACKETVER >= 20111005 - clif_snap(src, src->x, src->y); -#else - clif_skill_poseffect(src,skill_id,skill_lv,src->x,src->y,tick); -#endif - if (sd) - skill_blockpc_start (sd, MO_EXTREMITYFIST, 2000); - } - break; - case NJ_SHADOWJUMP: - if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground ) { //You don't move on GVG grounds. - unit_movepos(src, x, y, 1, 0); - clif_slide(src,x,y); - } - status_change_end(src, SC_HIDING, INVALID_TIMER); - break; - case AM_SPHEREMINE: - case AM_CANNIBALIZE: - { - int summons[5] = { 1589, 1579, 1575, 1555, 1590 }; - //int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; - int class_ = skill_id==AM_SPHEREMINE?1142:summons[skill_lv-1]; - struct mob_data *md; + x1 = tmpx; + y1 = tmpy; + } - // Correct info, don't change any of this! [celest] - md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); - if (md) { - md->master_id = src->id; - md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA; - if( md->deletetimer != INVALID_TIMER ) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer (gettick() + skill_get_time(skill_id,skill_lv), mob_timer_delete, md->bl.id, 0); - mob_spawn (md); //Now it is ready for spawning. + skill->addtimerskill(src,tick+i*1000,0,tmpx,tmpy,skill_id,skill_lv,-1,0); } - } - break; + break; - // Slim Pitcher [Celest] - case CR_SLIMPITCHER: - if (sd) { - int i = skill_lv%11 - 1; - int j = pc_search_inventory(sd,skill_db[skill_id].itemid[i]); - if( j < 0 || skill_db[skill_id].itemid[i] <= 0 || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill_db[skill_id].amount[i] ) + case AL_WARP: + if(sd) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 1; + clif->skill_warppoint(sd, skill_id, skill_lv, sd->status.save_point.map, + (skill_lv >= 2) ? sd->status.memo_point[0].map : 0, + (skill_lv >= 3) ? sd->status.memo_point[1].map : 0, + (skill_lv >= 4) ? sd->status.memo_point[2].map : 0 + ); } - potion_flag = 1; - potion_hp = 0; - potion_sp = 0; - run_script(sd->inventory_data[j]->script,0,sd->bl.id,0); - potion_flag = 0; - //Apply skill bonuses - i = pc_checkskill(sd,CR_SLIMPITCHER)*10 - + pc_checkskill(sd,AM_POTIONPITCHER)*10 - + pc_checkskill(sd,AM_LEARNINGPOTION)*5 - + pc_skillheal_bonus(sd, skill_id); - - potion_hp = potion_hp * (100+i)/100; - potion_sp = potion_sp * (100+i)/100; - - if(potion_hp > 0 || potion_sp > 0) { - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea(skill_area_sub, - src->m,x-i,y-i,x+i,y+i,BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1, - skill_castend_nodamage_id); + if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] ) //Should only remove after the skill has been casted. + status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); + return 0; // not to consume item. + + case MO_BODYRELOCATION: + if (unit_movepos(src, x, y, 1, 1)) { + #if PACKETVER >= 20111005 + clif->snap(src, src->x, src->y); + #else + clif->skill_poseffect(src,skill_id,skill_lv,src->x,src->y,tick); + #endif + if (sd) + skill->blockpc_start (sd, MO_EXTREMITYFIST, 2000, false); } - } else { - int i = skill_lv%11 - 1; - struct item_data *item; - i = skill_db[skill_id].itemid[i]; - item = itemdb_search(i); - potion_flag = 1; - potion_hp = 0; - potion_sp = 0; - run_script(item->script,0,src->id,0); - potion_flag = 0; - i = skill_get_max(CR_SLIMPITCHER)*10; - - potion_hp = potion_hp * (100+i)/100; - potion_sp = potion_sp * (100+i)/100; - - if(potion_hp > 0 || potion_sp > 0) { - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea(skill_area_sub, - src->m,x-i,y-i,x+i,y+i,BL_CHAR, - src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1, - skill_castend_nodamage_id); + break; + case NJ_SHADOWJUMP: + if( !map_flag_gvg(src->m) && !map[src->m].flag.battleground ) { //You don't move on GVG grounds. + unit_movepos(src, x, y, 1, 0); + clif->slide(src,x,y); } - } - break; - - case HW_GANBANTEIN: - if (rnd()%100 < 80) { - int dummy = 1; - clif_skill_poseffect(src,skill_id,skill_lv,x,y,tick); - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea(skill_cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src); - } else { - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 1; - } - break; + status_change_end(src, SC_HIDING, INVALID_TIMER); + break; + case AM_SPHEREMINE: + case AM_CANNIBALIZE: + { + int summons[5] = { 1589, 1579, 1575, 1555, 1590 }; + //int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; + int class_ = skill_id==AM_SPHEREMINE?1142:summons[skill_lv-1]; + struct mob_data *md; + + // Correct info, don't change any of this! [celest] + md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); + if (md) { + md->master_id = src->id; + md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + skill->get_time(skill_id,skill_lv), mob_timer_delete, md->bl.id, 0); + mob_spawn (md); //Now it is ready for spawning. + } + } + break; - case HW_GRAVITATION: - if ((sg = skill_unitsetting(src,skill_id,skill_lv,x,y,0))) - sc_start4(src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill_get_time(skill_id,skill_lv)); - flag|=1; - break; + // Slim Pitcher [Celest] + case CR_SLIMPITCHER: + if (sd) { + int i = skill_lv%11 - 1; + int j = pc_search_inventory(sd,skill_db[skill_id].itemid[i]); + if( j < 0 || skill_db[skill_id].itemid[i] <= 0 || sd->inventory_data[j] == NULL || sd->status.inventory[j].amount < skill_db[skill_id].amount[i] ) + { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 1; + } + potion_flag = 1; + potion_hp = 0; + potion_sp = 0; + run_script(sd->inventory_data[j]->script,0,sd->bl.id,0); + potion_flag = 0; + //Apply skill bonuses + i = pc_checkskill(sd,CR_SLIMPITCHER)*10 + + pc_checkskill(sd,AM_POTIONPITCHER)*10 + + pc_checkskill(sd,AM_LEARNINGPOTION)*5 + + pc_skillheal_bonus(sd, skill_id); + + potion_hp = potion_hp * (100+i)/100; + potion_sp = potion_sp * (100+i)/100; + + if(potion_hp > 0 || potion_sp > 0) { + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea(skill->area_sub, + src->m,x-i,y-i,x+i,y+i,BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1, + skill->castend_nodamage_id); + } + } else { + int i = skill_lv%11 - 1; + struct item_data *item; + i = skill_db[skill_id].itemid[i]; + item = itemdb_search(i); + potion_flag = 1; + potion_hp = 0; + potion_sp = 0; + run_script(item->script,0,src->id,0); + potion_flag = 0; + i = skill->get_max(CR_SLIMPITCHER)*10; + + potion_hp = potion_hp * (100+i)/100; + potion_sp = potion_sp * (100+i)/100; + + if(potion_hp > 0 || potion_sp > 0) { + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea(skill->area_sub, + src->m,x-i,y-i,x+i,y+i,BL_CHAR, + src,skill_id,skill_lv,tick,flag|BCT_PARTY|BCT_GUILD|1, + skill->castend_nodamage_id); + } + } + break; - // Plant Cultivation [Celest] - case CR_CULTIVATION: - if (sd) { - if( map_count_oncell(src->m,x,y,BL_CHAR) > 0 ) - { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case HW_GANBANTEIN: + if (rnd()%100 < 80) { + int dummy = 1; + clif->skill_poseffect(src,skill_id,skill_lv,x,y,tick); + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea(skill->cell_overlap, src->m, x-i, y-i, x+i, y+i, BL_SKILL, HW_GANBANTEIN, &dummy, src); + } else { + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 1; } - clif_skill_poseffect(src,skill_id,skill_lv,x,y,tick); - if (rnd()%100 < 50) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - } else { - TBL_MOB* md = mob_once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_SMALL, AI_NONE); - int i; - if (!md) break; - if ((i = skill_get_time(skill_id, skill_lv)) > 0) + break; + + case HW_GRAVITATION: + if ((sg = skill->unitsetting(src,skill_id,skill_lv,x,y,0))) + sc_start4(src,type,100,skill_lv,0,BCT_SELF,sg->group_id,skill->get_time(skill_id,skill_lv)); + flag|=1; + break; + + // Plant Cultivation [Celest] + case CR_CULTIVATION: + if (sd) { + if( map_count_oncell(src->m,x,y,BL_CHAR) > 0 ) { - if( md->deletetimer != INVALID_TIMER ) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer (tick + i, mob_timer_delete, md->bl.id, 0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 1; + } + clif->skill_poseffect(src,skill_id,skill_lv,x,y,tick); + if (rnd()%100 < 50) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + } else { + TBL_MOB* md = mob_once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_SMALL, AI_NONE); + int i; + if (!md) break; + if ((i = skill->get_time(skill_id, skill_lv)) > 0) + { + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (tick + i, mob_timer_delete, md->bl.id, 0); + } + mob_spawn (md); } - mob_spawn (md); } - } - break; - - case SG_SUN_WARM: - case SG_MOON_WARM: - case SG_STAR_WARM: - skill_clear_unitgroup(src); - if ((sg = skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0))) - sc_start4(src,type,100,skill_lv,0,0,sg->group_id,skill_get_time(skill_id,skill_lv)); - flag|=1; - break; + break; - case PA_GOSPEL: - if (sce && sce->val4 == BCT_SELF) - { - status_change_end(src, SC_GOSPEL, INVALID_TIMER); - return 0; - } - else - { - sg = skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0); - if (!sg) break; - if (sce) - status_change_end(src, type, INVALID_TIMER); //Was under someone else's Gospel. [Skotlex] - sc_start4(src,type,100,skill_lv,0,sg->group_id,BCT_SELF,skill_get_time(skill_id,skill_lv)); - clif_skill_poseffect(src, skill_id, skill_lv, 0, 0, tick); // PA_GOSPEL music packet - } - break; - case NJ_TATAMIGAESHI: - if (skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) - sc_start(src,type,100,skill_lv,skill_get_time2(skill_id,skill_lv)); - break; + case SG_SUN_WARM: + case SG_MOON_WARM: + case SG_STAR_WARM: + skill->clear_unitgroup(src); + if ((sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0))) + sc_start4(src,type,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv)); + flag|=1; + break; - case AM_RESURRECTHOMUN: //[orn] - if (sd) - { - if (!merc_resurrect_homunculus(sd, 20*skill_lv, x, y)) + case PA_GOSPEL: + if (sce && sce->val4 == BCT_SELF) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - break; + status_change_end(src, SC_GOSPEL, INVALID_TIMER); + return 0; } - } - break; + else + { + sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0); + if (!sg) break; + if (sce) + status_change_end(src, type, INVALID_TIMER); //Was under someone else's Gospel. [Skotlex] + sc_start4(src,type,100,skill_lv,0,sg->group_id,BCT_SELF,skill->get_time(skill_id,skill_lv)); + clif->skill_poseffect(src, skill_id, skill_lv, 0, 0, tick); // PA_GOSPEL music packet + } + break; + case NJ_TATAMIGAESHI: + if (skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) + sc_start(src,type,100,skill_lv,skill->get_time2(skill_id,skill_lv)); + break; - case RK_WINDCUTTER: - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - case NC_COLDSLOWER: - case NC_ARMSCANNON: - case RK_DRAGONBREATH: - i = skill_get_splash(skill_id,skill_lv); - map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; + case AM_RESURRECTHOMUN: //[orn] + if (sd) { + if (!homun->ressurect(sd, 20*skill_lv, x, y)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + break; + } + } + break; - case SO_ARRULLO: - i = skill_get_splash(skill_id,skill_lv); - map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), - src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill_castend_nodamage_id); - break; - /** - * Guilotine Cross - **/ - case GC_POISONSMOKE: - if( !(sc && sc->data[SC_POISONINGWEAPON]) ) { - if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_GC_POISONINGWEAPON,0); - return 0; - } - clif_skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); - skill_unitsetting(src, skill_id, skill_lv, x, y, flag); - //status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); // 08/31/2011 - When using poison smoke, you no longer lose the poisoning weapon effect. - break; - /** - * Arch Bishop - **/ - case AB_EPICLESIS: - if( (sg = skill_unitsetting(src, skill_id, skill_lv, x, y, 0)) ) { - i = sg->unit->range; - map_foreachinarea(skill_area_sub, src->m, x - i, y - i, x + i, y + i, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill_castend_nodamage_id); - } - break; - /** - * Warlock - **/ - case WL_COMET: - if( sc ) { - sc->comet_x = x; - sc->comet_y = y; - } - i = skill_get_splash(skill_id,skill_lv); - map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - break; + case RK_WINDCUTTER: + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + case NC_COLDSLOWER: + case NC_ARMSCANNON: + case RK_DRAGONBREATH: + i = skill->get_splash(skill_id,skill_lv); + map_foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + break; - case WL_EARTHSTRAIN: - { - int i, wave = skill_lv + 4, dir = map_calc_dir(src,x,y); - int sx = x = src->x, sy = y = src->y; // Store first caster's location to avoid glitch on unit setting + case SO_ARRULLO: + i = skill->get_splash(skill_id,skill_lv); + map_foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), + src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_nodamage_id); + break; + /** + * Guilotine Cross + **/ + case GC_POISONSMOKE: + if( !(sc && sc->data[SC_POISONINGWEAPON]) ) { + if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_POISONINGWEAPON,0); + return 0; + } + clif->skill_damage(src,src,tick,status_get_amotion(src),0,-30000,1,skill_id,skill_lv,6); + skill->unitsetting(src, skill_id, skill_lv, x, y, flag); + //status_change_end(src,SC_POISONINGWEAPON,INVALID_TIMER); // 08/31/2011 - When using poison smoke, you no longer lose the poisoning weapon effect. + break; + /** + * Arch Bishop + **/ + case AB_EPICLESIS: + if( (sg = skill->unitsetting(src, skill_id, skill_lv, x, y, 0)) ) { + i = sg->unit->range; + map_foreachinarea(skill->area_sub, src->m, x - i, y - i, x + i, y + i, BL_CHAR, src, ALL_RESURRECTION, 1, tick, flag|BCT_NOENEMY|1,skill->castend_nodamage_id); + } + break; + /** + * Warlock + **/ + case WL_COMET: + if( sc ) { + sc->comet_x = x; + sc->comet_y = y; + } + i = skill->get_splash(skill_id,skill_lv); + map_foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src),src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + break; - for( i = 1; i <= wave; i++ ) + case WL_EARTHSTRAIN: { - switch( dir ){ - case 0: case 1: case 7: sy = y + i; break; - case 3: case 4: case 5: sy = y - i; break; - case 2: sx = x - i; break; - case 6: sx = x + i; break; + int i, wave = skill_lv + 4, dir = map_calc_dir(src,x,y); + int sx = x = src->x, sy = y = src->y; // Store first caster's location to avoid glitch on unit setting + + for( i = 1; i <= wave; i++ ) + { + switch( dir ){ + case 0: case 1: case 7: sy = y + i; break; + case 3: case 4: case 5: sy = y - i; break; + case 2: sx = x - i; break; + case 6: sx = x + i; break; + } + skill->addtimerskill(src,gettick() + (150 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2); } - skill_addtimerskill(src,gettick() + (150 * i),0,sx,sy,skill_id,skill_lv,dir,flag&2); } - } - break; - /** - * Ranger - **/ - case RA_DETONATOR: - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea(skill_detonator, src->m, x-i, y-i, x+i, y+i, BL_SKILL, src); - clif_skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); - break; - /** - * Mechanic - **/ - case NC_NEUTRALBARRIER: - case NC_STEALTHFIELD: - skill_clear_unitgroup(src); // To remove previous skills - cannot used combined - if( (sg = skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) { - sc_start2(src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill_get_time(skill_id,skill_lv)); - if( sd ) pc_overheat(sd,1); - } - break; - - case NC_SILVERSNIPER: - { - int class_ = 2042; - struct mob_data *md; + break; + /** + * Ranger + **/ + case RA_DETONATOR: + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea(skill->detonator, src->m, x-i, y-i, x+i, y+i, BL_SKILL, src); + clif->skill_damage(src, src, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6); + break; + /** + * Mechanic + **/ + case NC_NEUTRALBARRIER: + case NC_STEALTHFIELD: + skill->clear_unitgroup(src); // To remove previous skills - cannot used combined + if( (sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) { + sc_start2(src,skill_id == NC_NEUTRALBARRIER ? SC_NEUTRALBARRIER_MASTER : SC_STEALTHFIELD_MASTER,100,skill_lv,sg->group_id,skill->get_time(skill_id,skill_lv)); + if( sd ) pc_overheat(sd,1); + } + break; - md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); - if( md ) + case NC_SILVERSNIPER: { - md->master_id = src->id; - md->special_state.ai = AI_FLORA; - if( md->deletetimer != INVALID_TIMER ) - delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer (gettick() + skill_get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); - mob_spawn( md ); - } - } - break; + int class_ = 2042; + struct mob_data *md; - case NC_MAGICDECOY: - if( sd ) clif_magicdecoy_list(sd,skill_lv,x,y); - break; + md = mob_once_spawn_sub(src, src->m, x, y, status_get_name(src), class_, "", SZ_SMALL, AI_NONE); + if( md ) + { + md->master_id = src->id; + md->special_state.ai = AI_FLORA; + if( md->deletetimer != INVALID_TIMER ) + delete_timer(md->deletetimer, mob_timer_delete); + md->deletetimer = add_timer (gettick() + skill->get_time(skill_id, skill_lv), mob_timer_delete, md->bl.id, 0); + mob_spawn( md ); + } + } + break; - case SC_FEINTBOMB: - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - skill_unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position - if( skill_blown(src,src,6,unit_getdir(src),0) ) - skill_castend_nodamage_id(src,src,TF_HIDING,1,tick,0); - break; + case NC_MAGICDECOY: + if( sd ) clif->magicdecoy_list(sd,skill_lv,x,y); + break; - case LG_OVERBRAND: - { - int width;//according to data from irowiki it actually is a square - for( width = 0; width < 7; width++ ) - for( i = 0; i < 7; i++ ) - map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, LG_OVERBRAND_BRANDISH, skill_lv, tick, flag|BCT_ENEMY,skill_castend_damage_id); - for( width = 0; width < 7; width++ ) - for( i = 0; i < 7; i++ ) - map_foreachincell(skill_area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY,skill_castend_damage_id); - } - break; + case SC_FEINTBOMB: + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + skill->unitsetting(src,skill_id,skill_lv,x,y,0); // Set bomb on current Position + if( skill->blown(src,src,6,unit_getdir(src),0) ) + skill->castend_nodamage_id(src,src,TF_HIDING,1,tick,0); + break; - case LG_BANDING: - if( sc && sc->data[SC_BANDING] ) - status_change_end(src,SC_BANDING,INVALID_TIMER); - else if( (sg = skill_unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) { - sc_start4(src,SC_BANDING,100,skill_lv,0,0,sg->group_id,skill_get_time(skill_id,skill_lv)); - if( sd ) pc_banding(sd,skill_lv); - } - clif_skill_nodamage(src,src,skill_id,skill_lv,1); - break; + case LG_OVERBRAND: + { + int width;//according to data from irowiki it actually is a square + for( width = 0; width < 7; width++ ) + for( i = 0; i < 7; i++ ) + map_foreachincell(skill->area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, LG_OVERBRAND_BRANDISH, skill_lv, tick, flag|BCT_ENEMY,skill->castend_damage_id); + for( width = 0; width < 7; width++ ) + for( i = 0; i < 7; i++ ) + map_foreachincell(skill->area_sub, src->m, x-2+i, y-2+width, splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY,skill->castend_damage_id); + } + break; - case LG_RAYOFGENESIS: - if( status_charge(src,status_get_max_hp(src)*3*skill_lv / 100,0) ) { - i = skill_get_splash(skill_id,skill_lv); - map_foreachinarea(skill_area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), - src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill_castend_damage_id); - } else if( sd ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL,0); - break; + case LG_BANDING: + if( sc && sc->data[SC_BANDING] ) + status_change_end(src,SC_BANDING,INVALID_TIMER); + else if( (sg = skill->unitsetting(src,skill_id,skill_lv,src->x,src->y,0)) != NULL ) { + sc_start4(src,SC_BANDING,100,skill_lv,0,0,sg->group_id,skill->get_time(skill_id,skill_lv)); + if( sd ) pc_banding(sd,skill_lv); + } + clif->skill_nodamage(src,src,skill_id,skill_lv,1); + break; - case WM_DOMINION_IMPULSE: - i = skill_get_splash(skill_id, skill_lv); - map_foreachinarea( skill_ative_reverberation, - src->m, x-i, y-i, x+i,y+i,BL_SKILL); - break; + case LG_RAYOFGENESIS: + if( status_charge(src,status_get_max_hp(src)*3*skill_lv / 100,0) ) { + i = skill->get_splash(skill_id,skill_lv); + map_foreachinarea(skill->area_sub,src->m,x-i,y-i,x+i,y+i,splash_target(src), + src,skill_id,skill_lv,tick,flag|BCT_ENEMY|1,skill->castend_damage_id); + } else if( sd ) + clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); + break; - case WM_GREAT_ECHO: - flag|=1; // Should counsume 1 item per skill usage. - map_foreachinrange(skill_area_sub, src, skill_get_splash(skill_id,skill_lv),splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill_castend_damage_id); - break; - case GN_CRAZYWEED: { - int area = skill_get_splash(GN_CRAZYWEED_ATK, skill_lv); - short x1 = 0, y1 = 0; + case WM_DOMINION_IMPULSE: + i = skill->get_splash(skill_id, skill_lv); + map_foreachinarea( skill->activate_reverberation, + src->m, x-i, y-i, x+i,y+i,BL_SKILL); + break; - for( i = 0; i < 3 + (skill_lv/2); i++ ) { - x1 = x - area + rnd()%(area * 2 + 1); - y1 = y - area + rnd()%(area * 2 + 1); - skill_addtimerskill(src,tick+i*150,0,x1,y1,GN_CRAZYWEED_ATK,skill_lv,-1,0); + case WM_GREAT_ECHO: + flag|=1; // Should counsume 1 item per skill usage. + map_foreachinrange(skill->area_sub, src, skill->get_splash(skill_id,skill_lv),splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->castend_damage_id); + break; + case GN_CRAZYWEED: { + int area = skill->get_splash(GN_CRAZYWEED_ATK, skill_lv); + short x1 = 0, y1 = 0; + + for( i = 0; i < 3 + (skill_lv/2); i++ ) { + x1 = x - area + rnd()%(area * 2 + 1); + y1 = y - area + rnd()%(area * 2 + 1); + skill->addtimerskill(src,tick+i*150,0,x1,y1,GN_CRAZYWEED_ATK,skill_lv,-1,0); + } } - } - break; - case GN_FIRE_EXPANSION: { - int i; - struct unit_data *ud = unit_bl2ud(src); + break; + case GN_FIRE_EXPANSION: { + int i; + struct unit_data *ud = unit_bl2ud(src); - if( !ud ) break; + if( !ud ) break; - for( i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i ++ ) { - if( ud->skillunit[i]->skill_id == GN_DEMONIC_FIRE && - distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 4 ) { - switch( skill_lv ) { - case 3: - ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_SMOKE_POWDER; - clif_changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_SMOKE_POWDER); - break; - case 4: - ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_TEAR_GAS; - clif_changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_TEAR_GAS); - break; - case 5: - map_foreachinarea(skill_area_sub, src->m, - ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3, - ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR, - src, CR_ACIDDEMONSTRATION, sd ? pc_checkskill(sd, CR_ACIDDEMONSTRATION) : skill_lv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill_castend_damage_id); - skill_delunit(ud->skillunit[i]->unit); - break; - default: - ud->skillunit[i]->unit->val2 = skill_lv; - ud->skillunit[i]->unit->group->val2 = skill_lv; - break; + for( i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i ++ ) { + if( ud->skillunit[i]->skill_id == GN_DEMONIC_FIRE && + distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 4 ) { + switch( skill_lv ) { + case 3: + ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_SMOKE_POWDER; + clif->changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_SMOKE_POWDER); + break; + case 4: + ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_TEAR_GAS; + clif->changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_TEAR_GAS); + break; + case 5: + map_foreachinarea(skill->area_sub, src->m, + ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3, + ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR, + src, CR_ACIDDEMONSTRATION, sd ? pc_checkskill(sd, CR_ACIDDEMONSTRATION) : skill_lv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id); + skill->delunit(ud->skillunit[i]->unit); + break; + default: + ud->skillunit[i]->unit->val2 = skill_lv; + ud->skillunit[i]->unit->group->val2 = skill_lv; + break; + } } } } - } - break; + break; - case SO_FIREWALK: - case SO_ELECTRICWALK: - if( sc && sc->data[type] ) - status_change_end(src,type,INVALID_TIMER); - clif_skill_nodamage(src, src ,skill_id, skill_lv, - sc_start2(src, type, 100, skill_id, skill_lv, skill_get_time(skill_id, skill_lv))); - break; + case SO_FIREWALK: + case SO_ELECTRICWALK: + if( sc && sc->data[type] ) + status_change_end(src,type,INVALID_TIMER); + clif->skill_nodamage(src, src ,skill_id, skill_lv, + sc_start2(src, type, 100, skill_id, skill_lv, skill->get_time(skill_id, skill_lv))); + break; - case SC_BLOODYLUST: //set in another group so instance will move if recasted - flag |= 33; - skill_unitsetting(src, skill_id, skill_lv, x, y, 0); - break; + case SC_BLOODYLUST: //set in another group so instance will move if recasted + flag |= 33; + skill->unitsetting(src, skill_id, skill_lv, x, y, 0); + break; - case KO_MAKIBISHI: - for( i = 0; i < (skill_lv+2); i++ ) { - x = src->x - 1 + rnd()%3; - y = src->y - 1 + rnd()%3; - skill_unitsetting(src,skill_id,skill_lv,x,y,0); - } - break; + case KO_MAKIBISHI: + for( i = 0; i < (skill_lv+2); i++ ) { + x = src->x - 1 + rnd()%3; + y = src->y - 1 + rnd()%3; + skill->unitsetting(src,skill_id,skill_lv,x,y,0); + } + break; - default: - ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skill_id); - return 1; + default: + ShowWarning("skill_castend_pos2: Unknown skill used:%d\n",skill_id); + return 1; } if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] ) //Should only remove after the skill has been casted. status_change_end(src,SC_CURSEDCIRCLE_ATKER,INVALID_TIMER); - if( sd ) - {// ensure that the skill last-cast tick is recorded + if( sd ) {// ensure that the skill last-cast tick is recorded sd->canskill_tick = gettick(); - if( sd->state.arrow_atk && !(flag&1) ) - {// consume arrow if this is a ground skill - battle_consume_ammo(sd, skill_id, skill_lv); + if( sd->state.arrow_atk && !(flag&1) ) { + // consume arrow if this is a ground skill + battle->consume_ammo(sd, skill_id, skill_lv); } // perform skill requirement consumption - skill_consume_requirement(sd,skill_id,skill_lv,2); + skill->consume_requirement(sd,skill_id,skill_lv,2); } return 0; @@ -10291,8 +10289,8 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char sd->sc.data[SC_BASILICA] || sd->sc.data[SC_MARIONETTE] || sd->sc.data[SC_WHITEIMPRISON] || - (sd->sc.data[SC_STASIS] && skill_block_check(&sd->bl, SC_STASIS, skill_id)) || - (sd->sc.data[SC_KAGEHUMI] && skill_block_check(&sd->bl, SC_KAGEHUMI, skill_id)) || + (sd->sc.data[SC_STASIS] && skill->block_check(&sd->bl, SC_STASIS, skill_id)) || + (sd->sc.data[SC_KAGEHUMI] && skill->block_check(&sd->bl, SC_KAGEHUMI, skill_id)) || sd->sc.data[SC_OBLIVIONCURSE] || sd->sc.data[SC__MANHOLE] || (sd->sc.data[SC_ASH] && rnd()%2) //50% fail chance under ASH @@ -10312,84 +10310,82 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char return 0; } - switch(skill_id) - { - case AL_TELEPORT: - if(strcmp(map,"Random")==0) - pc_randomwarp(sd,CLR_TELEPORT); - else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. - pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); - break; - - case AL_WARP: - { - const struct point *p[4]; - struct skill_unit_group *group; - int i, lv, wx, wy; - int maxcount=0; - int x,y; - unsigned short mapindex; - - mapindex = mapindex_name2id((char*)map); - if(!mapindex) { //Given map not found? - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - skill_failed(sd); - return 0; - } - p[0] = &sd->status.save_point; - p[1] = &sd->status.memo_point[0]; - p[2] = &sd->status.memo_point[1]; - p[3] = &sd->status.memo_point[2]; + switch(skill_id) { + case AL_TELEPORT: + if(strcmp(map,"Random")==0) + pc_randomwarp(sd,CLR_TELEPORT); + else if (sd->menuskill_val > 1) //Need lv2 to be able to warp here. + pc_setpos(sd,sd->status.save_point.map,sd->status.save_point.x,sd->status.save_point.y,CLR_TELEPORT); + break; - if((maxcount = skill_get_maxcount(skill_id, sd->menuskill_val)) > 0) { - for(i=0;i<MAX_SKILLUNITGROUP && sd->ud.skillunit[i] && maxcount;i++) { - if(sd->ud.skillunit[i]->skill_id == skill_id) - maxcount--; - } - if(!maxcount) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + case AL_WARP: + { + const struct point *p[4]; + struct skill_unit_group *group; + int i, lv, wx, wy; + int maxcount=0; + int x,y; + unsigned short mapindex; + + mapindex = mapindex_name2id((char*)map); + if(!mapindex) { //Given map not found? + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); skill_failed(sd); return 0; } - } + p[0] = &sd->status.save_point; + p[1] = &sd->status.memo_point[0]; + p[2] = &sd->status.memo_point[1]; + p[3] = &sd->status.memo_point[2]; + + if((maxcount = skill->get_maxcount(skill_id, sd->menuskill_val)) > 0) { + for(i=0;i<MAX_SKILLUNITGROUP && sd->ud.skillunit[i] && maxcount;i++) { + if(sd->ud.skillunit[i]->skill_id == skill_id) + maxcount--; + } + if(!maxcount) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + skill_failed(sd); + return 0; + } + } - lv = sd->skillitem==skill_id?sd->skillitemlv:pc_checkskill(sd,skill_id); - wx = sd->menuskill_val>>16; - wy = sd->menuskill_val&0xffff; + lv = sd->skillitem==skill_id?sd->skillitemlv:pc_checkskill(sd,skill_id); + wx = sd->menuskill_val>>16; + wy = sd->menuskill_val&0xffff; - if( lv <= 0 ) return 0; - if( lv > 4 ) lv = 4; // crash prevention + if( lv <= 0 ) return 0; + if( lv > 4 ) lv = 4; // crash prevention - // check if the chosen map exists in the memo list - ARR_FIND( 0, lv, i, mapindex == p[i]->map ); - if( i < lv ) { - x=p[i]->x; - y=p[i]->y; - } else { - skill_failed(sd); - return 0; - } + // check if the chosen map exists in the memo list + ARR_FIND( 0, lv, i, mapindex == p[i]->map ); + if( i < lv ) { + x=p[i]->x; + y=p[i]->y; + } else { + skill_failed(sd); + return 0; + } - if(!skill_check_condition_castend(sd, sd->menuskill_id, lv)) - { // This checks versus skill_id/skill_lv... - skill_failed(sd); - return 0; - } + if(!skill->check_condition_castend(sd, sd->menuskill_id, lv)) { // This checks versus skill_id/skill_lv... + skill_failed(sd); + return 0; + } - skill_consume_requirement(sd,sd->menuskill_id,lv,2); - sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] + skill->consume_requirement(sd,sd->menuskill_id,lv,2); + sd->skillitem = sd->skillitemlv = 0; // Clear data that's skipped in 'skill_castend_pos' [Inkfish] - if((group=skill_unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) { - skill_failed(sd); - return 0; - } + if((group=skill->unitsetting(&sd->bl,skill_id,lv,wx,wy,0))==NULL) { + skill_failed(sd); + return 0; + } - group->val1 = (group->val1<<16)|(short)0; - // record the destination coordinates - group->val2 = (x<<16)|y; - group->val3 = mapindex; - } - break; + group->val1 = (group->val1<<16)|(short)0; + // record the destination coordinates + group->val2 = (x<<16)|y; + group->val3 = mapindex; + } + break; } sd->menuskill_id = sd->menuskill_val = 0; @@ -10398,8 +10394,7 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char } /// transforms 'target' skill unit into dissonance (if conditions are met) -static int skill_dance_overlap_sub(struct block_list* bl, va_list ap) -{ +int skill_dance_overlap_sub(struct block_list* bl, va_list ap) { struct skill_unit* target = (struct skill_unit*)bl; struct skill_unit* src = va_arg(ap, struct skill_unit*); int flag = va_arg(ap, int); @@ -10416,7 +10411,7 @@ static int skill_dance_overlap_sub(struct block_list* bl, va_list ap) else //Remove dissonance target->val2 &= ~UF_ENSEMBLE; - clif_skill_setunit(target); //Update look of affected cell. + clif->skill_setunit(target); //Update look of affected cell. return 1; } @@ -10424,28 +10419,26 @@ static int skill_dance_overlap_sub(struct block_list* bl, va_list ap) //Does the song/dance overlapping -> dissonance check. [Skotlex] //When flag is 0, this unit is about to be removed, cancel the dissonance effect //When 1, this unit has been positioned, so start the cancel effect. -int skill_dance_overlap(struct skill_unit* unit, int flag) -{ +int skill_dance_overlap(struct skill_unit* unit, int flag) { if (!unit || !unit->group || !(unit->group->state.song_dance&0x1)) return 0; if (!flag && !(unit->val2&UF_ENSEMBLE)) return 0; //Nothing to remove, this unit is not overlapped. - if (unit->val1 != unit->group->skill_id) - { //Reset state + if (unit->val1 != unit->group->skill_id) { + //Reset state unit->val1 = unit->group->skill_id; unit->val2 &= ~UF_ENSEMBLE; } - return map_foreachincell(skill_dance_overlap_sub, unit->bl.m,unit->bl.x,unit->bl.y,BL_SKILL, unit,flag); + return map_foreachincell(skill->dance_overlap_sub, unit->bl.m,unit->bl.x,unit->bl.y,BL_SKILL, unit,flag); } /*========================================== * Converts this group information so that it is handled as a Dissonance or Ugly Dance cell. * Flag: 0 - Convert, 1 - Revert. *------------------------------------------*/ -static bool skill_dance_switch(struct skill_unit* unit, int flag) -{ +bool skill_dance_switch(struct skill_unit* unit, int flag) { static int prevflag = 1; // by default the backup is empty static struct skill_unit_group backup; struct skill_unit_group* group = unit->group; @@ -10454,8 +10447,8 @@ static bool skill_dance_switch(struct skill_unit* unit, int flag) if ( !(group->state.song_dance&0x1 && unit->val2&UF_ENSEMBLE) ) return false; - if( flag == prevflag ) - {// protection against attempts to read an empty backup / write to a full backup + if( flag == prevflag ) { + // protection against attempts to read an empty backup / write to a full backup ShowError("skill_dance_switch: Attempted to %s (skill_id=%d, skill_lv=%d, src_id=%d).\n", flag ? "read an empty backup" : "write to a full backup", group->skill_id, group->skill_lv, group->src_id); @@ -10463,8 +10456,7 @@ static bool skill_dance_switch(struct skill_unit* unit, int flag) } prevflag = flag; - if( !flag ) - { //Transform + if( !flag ) { //Transform uint16 skill_id = unit->val2&UF_SONG ? BA_DISSONANCE : DC_UGLYDANCE; // backup @@ -10478,13 +10470,11 @@ static bool skill_dance_switch(struct skill_unit* unit, int flag) // replace group->skill_id = skill_id; group->skill_lv = 1; - group->unit_id = skill_get_unit_id(skill_id,0); - group->target_flag = skill_get_unit_target(skill_id); - group->bl_flag = skill_get_unit_bl_target(skill_id); - group->interval = skill_get_unit_interval(skill_id); - } - else - { //Restore + group->unit_id = skill->get_unit_id(skill_id,0); + group->target_flag = skill->get_unit_target(skill_id); + group->bl_flag = skill->get_unit_bl_target(skill_id); + group->interval = skill->get_unit_interval(skill_id); + } else { //Restore group->skill_id = backup.skill_id; group->skill_lv = backup.skill_lv; group->unit_id = backup.unit_id; @@ -10498,7 +10488,7 @@ static bool skill_dance_switch(struct skill_unit* unit, int flag) /** * Upon Ice Wall cast it checks all nearby mobs to find any who may be blocked by the IW **/ -static int skill_icewall_block(struct block_list *bl,va_list ap) { +int skill_icewall_block(struct block_list *bl,va_list ap) { struct block_list *target = NULL; struct mob_data *md = ((TBL_MOB*)bl); @@ -10535,321 +10525,331 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill nullpo_retr(NULL, src); - limit = skill_get_time(skill_id,skill_lv); - range = skill_get_unit_range(skill_id,skill_lv); - interval = skill_get_unit_interval(skill_id); - target = skill_get_unit_target(skill_id); - unit_flag = skill_get_unit_flag(skill_id); - layout = skill_get_unit_layout(skill_id,skill_lv,src,x,y); + limit = skill->get_time(skill_id,skill_lv); + range = skill->get_unit_range(skill_id,skill_lv); + interval = skill->get_unit_interval(skill_id); + target = skill->get_unit_target(skill_id); + unit_flag = skill->get_unit_flag(skill_id); + layout = skill->get_unit_layout(skill_id,skill_lv,src,x,y); + if( map[src->m].unit_count ) { + ARR_FIND(0, map[src->m].unit_count, i, map[src->m].units[i]->skill_id == skill_id ); + + if( i < map[src->m].unit_count ) { + limit = limit * map[src->m].units[i]->modifier / 100; + } + } + sd = BL_CAST(BL_PC, src); status = status_get_status_data(src); sc = status_get_sc(src); // for traps, firewall and fogwall - celest switch( skill_id ) { - case MH_STEINWAND: - val2 = 4 + skill_lv; //nb of attack blocked - break; - case MG_SAFETYWALL: - #ifdef RENEWAL - /** - * According to data provided in RE, SW life is equal to 3 times caster's health - **/ - val2 = status_get_max_hp(src) * 3; - #else - val2 = skill_lv+1; - #endif - break; - case MG_FIREWALL: - if(sc && sc->data[SC_VIOLENTGALE]) - limit = limit*3/2; - val2=4+skill_lv; - break; + case MH_STEINWAND: + val2 = 4 + skill_lv; //nb of attack blocked + break; + case MG_SAFETYWALL: + #ifdef RENEWAL + /** + * According to data provided in RE, SW life is equal to 3 times caster's health + **/ + val2 = status_get_max_hp(src) * 3; + #else + val2 = skill_lv+1; + #endif + break; + case MG_FIREWALL: + if(sc && sc->data[SC_VIOLENTGALE]) + limit = limit*3/2; + val2=4+skill_lv; + break; - case AL_WARP: - val1=skill_lv+6; - if(!(flag&1)) - limit=2000; - else // previous implementation (not used anymore) - { //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex] - if( src->type != BL_SKILL ) return NULL; - group = ((TBL_SKILL*)src)->group; - src = map_id2bl(group->src_id); - if( !src ) return NULL; - val2 = group->val2; //Copy the (x,y) position you warp to - val3 = group->val3; //as well as the mapindex to warp to. - } - break; - case HP_BASILICA: - val1 = src->id; // Store caster id. - break; + case AL_WARP: + val1=skill_lv+6; + if(!(flag&1)) + limit=2000; + else // previous implementation (not used anymore) + { //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex] + if( src->type != BL_SKILL ) return NULL; + group = ((TBL_SKILL*)src)->group; + src = map_id2bl(group->src_id); + if( !src ) return NULL; + val2 = group->val2; //Copy the (x,y) position you warp to + val3 = group->val3; //as well as the mapindex to warp to. + } + break; + case HP_BASILICA: + val1 = src->id; // Store caster id. + break; - case PR_SANCTUARY: - case NPC_EVILLAND: - val1=(skill_lv+3)*2; - break; + case PR_SANCTUARY: + case NPC_EVILLAND: + val1=(skill_lv+3)*2; + break; - case WZ_FIREPILLAR: - if((flag&1)!=0) - limit=1000; - val1=skill_lv+2; - break; - case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] - case AM_DEMONSTRATION: - case GN_HELLS_PLANT: - if (map_flag_vs(src->m) && battle_config.vs_traps_bctall - && (src->type&battle_config.vs_traps_bctall)) - target = BCT_ALL; - break; - case HT_SHOCKWAVE: - val1=skill_lv*15+10; - case HT_SANDMAN: - case MA_SANDMAN: - case HT_CLAYMORETRAP: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_BLASTMINE: - /** - * Ranger - **/ - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - { - struct skill_condition req = skill_get_requirement(sd,skill_id,skill_lv); - ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY)); - if( req.itemid[i] ) - req_item = req.itemid[i]; - if( map_flag_gvg(src->m) || map[src->m].flag.battleground ) - limit *= 4; // longer trap times in WOE [celest] - if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) ) + case WZ_FIREPILLAR: + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + return NULL; + if((flag&1)!=0) + limit=1000; + val1=skill_lv+2; + break; + case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex] + case AM_DEMONSTRATION: + case GN_HELLS_PLANT: + if (map_flag_vs(src->m) && battle_config.vs_traps_bctall + && (src->type&battle_config.vs_traps_bctall)) target = BCT_ALL; - } - break; + break; + case HT_SHOCKWAVE: + val1=skill_lv*15+10; + case HT_SANDMAN: + case MA_SANDMAN: + case HT_CLAYMORETRAP: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_BLASTMINE: + /** + * Ranger + **/ + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + { + struct skill_condition req = skill->get_requirement(sd,skill_id,skill_lv); + ARR_FIND(0, MAX_SKILL_ITEM_REQUIRE, i, req.itemid[i] && (req.itemid[i] == ITEMID_TRAP || req.itemid[i] == ITEMID_TRAP_ALLOY)); + if( req.itemid[i] ) + req_item = req.itemid[i]; + if( map_flag_gvg(src->m) || map[src->m].flag.battleground ) + limit *= 4; // longer trap times in WOE [celest] + if( battle_config.vs_traps_bctall && map_flag_vs(src->m) && (src->type&battle_config.vs_traps_bctall) ) + target = BCT_ALL; + } + break; - case SA_LANDPROTECTOR: - case SA_VOLCANO: - case SA_DELUGE: - case SA_VIOLENTGALE: - { - struct skill_unit_group *old_sg; - if ((old_sg = skill_locate_element_field(src)) != NULL) - { //HelloKitty confirmed that these are interchangeable, - //so you can change element and not consume gemstones. - if (( - old_sg->skill_id == SA_VOLCANO || - old_sg->skill_id == SA_DELUGE || - old_sg->skill_id == SA_VIOLENTGALE - ) && old_sg->limit > 0) - { //Use the previous limit (minus the elapsed time) [Skotlex] - limit = old_sg->limit - DIFF_TICK(gettick(), old_sg->tick); - if (limit < 0) //This can happen... - limit = skill_get_time(skill_id,skill_lv); - } - skill_clear_group(src,1); + case SA_LANDPROTECTOR: + case SA_VOLCANO: + case SA_DELUGE: + case SA_VIOLENTGALE: + { + struct skill_unit_group *old_sg; + if ((old_sg = skill->locate_element_field(src)) != NULL) + { //HelloKitty confirmed that these are interchangeable, + //so you can change element and not consume gemstones. + if (( + old_sg->skill_id == SA_VOLCANO || + old_sg->skill_id == SA_DELUGE || + old_sg->skill_id == SA_VIOLENTGALE + ) && old_sg->limit > 0) + { //Use the previous limit (minus the elapsed time) [Skotlex] + limit = old_sg->limit - DIFF_TICK(gettick(), old_sg->tick); + if (limit < 0) //This can happen... + limit = skill->get_time(skill_id,skill_lv); + } + skill->clear_group(src,1); + } + break; } - break; - } - case BA_DISSONANCE: - case DC_UGLYDANCE: - val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex] - break; - case BA_WHISTLE: - val1 = skill_lv +status->agi/10; // Flee increase - val2 = ((skill_lv+1)/2)+status->luk/10; // Perfect dodge increase - if(sd){ - val1 += pc_checkskill(sd,BA_MUSICALLESSON); - val2 += pc_checkskill(sd,BA_MUSICALLESSON); - } - break; - case DC_HUMMING: - val1 = 2*skill_lv+status->dex/10; // Hit increase + case BA_DISSONANCE: + case DC_UGLYDANCE: + val1 = 10; //FIXME: This value is not used anywhere, what is it for? [Skotlex] + break; + case BA_WHISTLE: + val1 = skill_lv +status->agi/10; // Flee increase + val2 = ((skill_lv+1)/2)+status->luk/10; // Perfect dodge increase + if(sd){ + val1 += pc_checkskill(sd,BA_MUSICALLESSON); + val2 += pc_checkskill(sd,BA_MUSICALLESSON); + } + break; + case DC_HUMMING: + val1 = 2*skill_lv+status->dex/10; // Hit increase + #ifdef RENEWAL + val1 *= 2; + #endif + if(sd) + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + break; + case BA_POEMBRAGI: + val1 = 3*skill_lv+status->dex/10; // Casting time reduction + //For some reason at level 10 the base delay reduction is 50%. + val2 = (skill_lv<10?3*skill_lv:50)+status->int_/5; // After-cast delay reduction + if(sd){ + val1 += 2*pc_checkskill(sd,BA_MUSICALLESSON); + val2 += 2*pc_checkskill(sd,BA_MUSICALLESSON); + } + break; + case DC_DONTFORGETME: + val1 = status->dex/10 + 3*skill_lv + 5; // ASPD decrease + val2 = status->agi/10 + 3*skill_lv + 5; // Movement speed adjustment. + if(sd){ + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + val2 += pc_checkskill(sd,DC_DANCINGLESSON); + } + break; + case BA_APPLEIDUN: + val1 = 5+2*skill_lv+status->vit/10; // MaxHP percent increase + if(sd) + val1 += pc_checkskill(sd,BA_MUSICALLESSON); + break; + case DC_SERVICEFORYOU: + val1 = 15+skill_lv+(status->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed + val2 = 20+3*skill_lv+(status->int_/10); // SP cost reduction + if(sd){ + val1 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO This bonus value is guessed + val2 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value + } + break; + case BA_ASSASSINCROSS: + val1 = 100+(10*skill_lv)+(status->agi/10); // ASPD increase + if(sd) + val1 += 5*pc_checkskill(sd,BA_MUSICALLESSON); + break; + case DC_FORTUNEKISS: + val1 = 10+skill_lv+(status->luk/10); // Critical increase + if(sd) + val1 += pc_checkskill(sd,DC_DANCINGLESSON); + val1*=10; //Because every 10 crit is an actual cri point. + break; + case BD_DRUMBATTLEFIELD: #ifdef RENEWAL - val1 *= 2; + val1 = (skill_lv+5)*25; //Watk increase + val2 = skill_lv*10; //Def increase + #else + val1 = (skill_lv+1)*25; //Watk increase + val2 = (skill_lv+1)*2; //Def increase #endif - if(sd) - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - break; - case BA_POEMBRAGI: - val1 = 3*skill_lv+status->dex/10; // Casting time reduction - //For some reason at level 10 the base delay reduction is 50%. - val2 = (skill_lv<10?3*skill_lv:50)+status->int_/5; // After-cast delay reduction - if(sd){ - val1 += 2*pc_checkskill(sd,BA_MUSICALLESSON); - val2 += 2*pc_checkskill(sd,BA_MUSICALLESSON); - } - break; - case DC_DONTFORGETME: - val1 = status->dex/10 + 3*skill_lv + 5; // ASPD decrease - val2 = status->agi/10 + 3*skill_lv + 5; // Movement speed adjustment. - if(sd){ - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - val2 += pc_checkskill(sd,DC_DANCINGLESSON); - } - break; - case BA_APPLEIDUN: - val1 = 5+2*skill_lv+status->vit/10; // MaxHP percent increase - if(sd) - val1 += pc_checkskill(sd,BA_MUSICALLESSON); - break; - case DC_SERVICEFORYOU: - val1 = 15+skill_lv+(status->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed - val2 = 20+3*skill_lv+(status->int_/10); // SP cost reduction - if(sd){ - val1 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO This bonus value is guessed - val2 += pc_checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value - } - break; - case BA_ASSASSINCROSS: - val1 = 100+(10*skill_lv)+(status->agi/10); // ASPD increase - if(sd) - val1 += 5*pc_checkskill(sd,BA_MUSICALLESSON); - break; - case DC_FORTUNEKISS: - val1 = 10+skill_lv+(status->luk/10); // Critical increase - if(sd) - val1 += pc_checkskill(sd,DC_DANCINGLESSON); - val1*=10; //Because every 10 crit is an actual cri point. - break; - case BD_DRUMBATTLEFIELD: - #ifdef RENEWAL - val1 = (skill_lv+5)*25; //Watk increase - val2 = skill_lv*10; //Def increase - #else - val1 = (skill_lv+1)*25; //Watk increase - val2 = (skill_lv+1)*2; //Def increase - #endif - break; - case BD_RINGNIBELUNGEN: - val1 = (skill_lv+2)*25; //Watk increase - break; - case BD_RICHMANKIM: - val1 = 25 + 11*skill_lv; //Exp increase bonus. - break; - case BD_SIEGFRIED: - val1 = 55 + skill_lv*5; //Elemental Resistance - val2 = skill_lv*10; //Status ailment resistance - break; - case WE_CALLPARTNER: - if (sd) val1 = sd->status.partner_id; - break; - case WE_CALLPARENT: - if (sd) { - val1 = sd->status.father; - val2 = sd->status.mother; - } - break; - case WE_CALLBABY: - if (sd) val1 = sd->status.child; - break; - case NJ_KAENSIN: - skill_clear_group(src, 1); //Delete previous Kaensins/Suitons - val2 = (skill_lv+1)/2 + 4; - break; - case NJ_SUITON: - skill_clear_group(src, 1); - break; + break; + case BD_RINGNIBELUNGEN: + val1 = (skill_lv+2)*25; //Watk increase + break; + case BD_RICHMANKIM: + val1 = 25 + 11*skill_lv; //Exp increase bonus. + break; + case BD_SIEGFRIED: + val1 = 55 + skill_lv*5; //Elemental Resistance + val2 = skill_lv*10; //Status ailment resistance + break; + case WE_CALLPARTNER: + if (sd) val1 = sd->status.partner_id; + break; + case WE_CALLPARENT: + if (sd) { + val1 = sd->status.father; + val2 = sd->status.mother; + } + break; + case WE_CALLBABY: + if (sd) val1 = sd->status.child; + break; + case NJ_KAENSIN: + skill->clear_group(src, 1); //Delete previous Kaensins/Suitons + val2 = (skill_lv+1)/2 + 4; + break; + case NJ_SUITON: + skill->clear_group(src, 1); + break; - case GS_GROUNDDRIFT: - { - int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE}; + case GS_GROUNDDRIFT: + { + int element[5]={ELE_WIND,ELE_DARK,ELE_POISON,ELE_WATER,ELE_FIRE}; - val1 = status->rhw.ele; - if (!val1) - val1=element[rnd()%5]; + val1 = status->rhw.ele; + if (!val1) + val1=element[rnd()%5]; - switch (val1) - { - case ELE_FIRE: - subunt++; - case ELE_WATER: - subunt++; - case ELE_POISON: - subunt++; - case ELE_DARK: - subunt++; - case ELE_WIND: - break; - default: - subunt=rnd()%5; - break; - } + switch (val1) + { + case ELE_FIRE: + subunt++; + case ELE_WATER: + subunt++; + case ELE_POISON: + subunt++; + case ELE_DARK: + subunt++; + case ELE_WIND: + break; + default: + subunt=rnd()%5; + break; + } - break; - } - case GC_POISONSMOKE: - if( !(sc && sc->data[SC_POISONINGWEAPON]) ) - return NULL; - val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison - val3 = sc->data[SC_POISONINGWEAPON]->val1; - limit = 4000 + 2000 * skill_lv; - break; - case GD_LEADERSHIP: - case GD_GLORYWOUNDS: - case GD_SOULCOLD: - case GD_HAWKEYES: - limit = 1000000;//it doesn't matter - break; - case LG_BANDING: - limit = -1; - break; - case WM_REVERBERATION: - interval = limit; - val2 = 1; - case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. - if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) - return NULL; - break; - case SO_CLOUD_KILL: - skill_clear_group(src, 4); - break; - case SO_WARMER: - skill_clear_group(src, 8); - break; - case SO_VACUUM_EXTREME: - range++; + break; + } + case GC_POISONSMOKE: + if( !(sc && sc->data[SC_POISONINGWEAPON]) ) + return NULL; + val2 = sc->data[SC_POISONINGWEAPON]->val2; // Type of Poison + val3 = sc->data[SC_POISONINGWEAPON]->val1; + limit = 4000 + 2000 * skill_lv; + break; + case GD_LEADERSHIP: + case GD_GLORYWOUNDS: + case GD_SOULCOLD: + case GD_HAWKEYES: + limit = 1000000;//it doesn't matter + break; + case LG_BANDING: + limit = -1; + break; + case WM_REVERBERATION: + interval = limit; + val2 = 1; + case WM_POEMOFNETHERWORLD: // Can't be placed on top of Land Protector. + if( map_getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) ) + return NULL; + break; + case SO_CLOUD_KILL: + skill->clear_group(src, 4); + break; + case SO_WARMER: + skill->clear_group(src, 8); + break; + case SO_VACUUM_EXTREME: + range++; - break; - case SC_BLOODYLUST: - skill_clear_group(src, 32); - break; - case GN_WALLOFTHORN: - if( flag&1 ) - limit = 3000; - val3 = (x<<16)|y; - break; - case KO_ZENKAI: - if( sd ){ - ARR_FIND(1, 6, i, sd->talisman[i] > 0); - if( i < 5 ){ - val1 = sd->talisman[i]; // no. of aura - val2 = i; // aura type - limit += val1 * 1000; - subunt = i - 1; - pc_del_talisman(sd, sd->talisman[i], i); + break; + case SC_BLOODYLUST: + skill->clear_group(src, 32); + break; + case GN_WALLOFTHORN: + if( flag&1 ) + limit = 3000; + val3 = (x<<16)|y; + break; + case KO_ZENKAI: + if( sd ){ + ARR_FIND(1, 6, i, sd->talisman[i] > 0); + if( i < 5 ){ + val1 = sd->talisman[i]; // no. of aura + val2 = i; // aura type + limit += val1 * 1000; + subunt = i - 1; + pc_del_talisman(sd, sd->talisman[i], i); + } } - } - break; + break; } - nullpo_retr(NULL, group=skill_initunitgroup(src,layout->count,skill_id,skill_lv,skill_get_unit_id(skill_id,flag&1)+subunt, limit, interval)); + nullpo_retr(NULL, group=skill->init_unitgroup(src,layout->count,skill_id,skill_lv,skill->get_unit_id(skill_id,flag&1)+subunt, limit, interval)); group->val1=val1; group->val2=val2; group->val3=val3; group->target_flag=target; - group->bl_flag= skill_get_unit_bl_target(skill_id); + group->bl_flag= skill->get_unit_bl_target(skill_id); group->state.ammo_consume = (sd && sd->state.arrow_atk && skill_id != GS_GROUNDDRIFT); //Store if this skill needs to consume ammo. group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet group->state.guildaura = ( skill_id >= GD_LEADERSHIP && skill_id <= GD_HAWKEYES )?1:0; @@ -10876,12 +10876,11 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill (group->state.song_dance&2?BCT_SELF:0), limit+1000) && sd && group->state.song_dance&2 && skill_id != CG_HERMODE //Hermod is a encore with a warp! ) - skill_check_pc_partner(sd, skill_id, &skill_lv, 1, 1); + skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 1); } limit = group->limit; - for( i = 0; i < layout->count; i++ ) - { + for( i = 0; i < layout->count; i++ ) { struct skill_unit *unit; int ux = x + layout->dx[i]; int uy = y + layout->dy[i]; @@ -10891,102 +10890,97 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill if( !group->state.song_dance && !map_getcell(src->m,ux,uy,CELL_CHKREACH) ) continue; // don't place skill units on walls (except for songs/dances/encores) - if( battle_config.skill_wall_check && skill_get_unit_flag(skill_id)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) ) + if( battle_config.skill_wall_check && skill->get_unit_flag(skill_id)&UF_PATHCHECK && !path_search_long(NULL,src->m,ux,uy,x,y,CELL_CHKWALL) ) continue; // no path between cell and center of casting. - switch( skill_id ) - { - case MG_FIREWALL: - case NJ_KAENSIN: - val2=group->val2; - break; - case WZ_ICEWALL: - val1 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv; - val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); - break; - case HT_LANDMINE: - case MA_LANDMINE: - case HT_ANKLESNARE: - case HT_SHOCKWAVE: - case HT_SANDMAN: - case MA_SANDMAN: - case HT_FLASHER: - case HT_FREEZINGTRAP: - case MA_FREEZINGTRAP: - case HT_TALKIEBOX: - case HT_SKIDTRAP: - case MA_SKIDTRAP: - case HT_CLAYMORETRAP: - case HT_BLASTMINE: - /** - * Ranger - **/ - case RA_ELECTRICSHOCKER: - case RA_CLUSTERBOMB: - case RA_MAGENTATRAP: - case RA_COBALTTRAP: - case RA_MAIZETRAP: - case RA_VERDURETRAP: - case RA_FIRINGTRAP: - case RA_ICEBOUNDTRAP: - val1 = 3500; - break; - case GS_DESPERADO: - val1 = abs(layout->dx[i]); - val2 = abs(layout->dy[i]); - if (val1 < 2 || val2 < 2) { //Nearby cross, linear decrease with no diagonals - if (val2 > val1) val1 = val2; - if (val1) val1--; - val1 = 36 -12*val1; - } else //Diagonal edges - val1 = 28 -4*val1 -4*val2; - if (val1 < 1) val1 = 1; - val2 = 0; - break; - case WM_REVERBERATION: - val1 = 1 + skill_lv; - break; - case GN_WALLOFTHORN: - val1 = 1000 * skill_lv; // Need official value. [LimitLine] - break; - default: - if (group->state.song_dance&0x1) - val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance - break; + switch( skill_id ) { + case MG_FIREWALL: + case NJ_KAENSIN: + val2=group->val2; + break; + case WZ_ICEWALL: + val1 = (skill_lv <= 1) ? 500 : 200 + 200*skill_lv; + val2 = map_getcell(src->m, ux, uy, CELL_GETTYPE); + break; + case HT_LANDMINE: + case MA_LANDMINE: + case HT_ANKLESNARE: + case HT_SHOCKWAVE: + case HT_SANDMAN: + case MA_SANDMAN: + case HT_FLASHER: + case HT_FREEZINGTRAP: + case MA_FREEZINGTRAP: + case HT_TALKIEBOX: + case HT_SKIDTRAP: + case MA_SKIDTRAP: + case HT_CLAYMORETRAP: + case HT_BLASTMINE: + case RA_ELECTRICSHOCKER: + case RA_CLUSTERBOMB: + case RA_MAGENTATRAP: + case RA_COBALTTRAP: + case RA_MAIZETRAP: + case RA_VERDURETRAP: + case RA_FIRINGTRAP: + case RA_ICEBOUNDTRAP: + val1 = 3500; + break; + case GS_DESPERADO: + val1 = abs(layout->dx[i]); + val2 = abs(layout->dy[i]); + if (val1 < 2 || val2 < 2) { //Nearby cross, linear decrease with no diagonals + if (val2 > val1) val1 = val2; + if (val1) val1--; + val1 = 36 -12*val1; + } else //Diagonal edges + val1 = 28 -4*val1 -4*val2; + if (val1 < 1) val1 = 1; + val2 = 0; + break; + case WM_REVERBERATION: + val1 = 1 + skill_lv; + break; + case GN_WALLOFTHORN: + val1 = 1000 * skill_lv; // Need official value. [LimitLine] + break; + default: + if (group->state.song_dance&0x1) + val2 = unit_flag&(UF_DANCE|UF_SONG); //Store whether this is a song/dance + break; } - if (skill_get_unit_flag(skill_id) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2)) + if (skill->get_unit_flag(skill_id) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2)) val2 |= UF_RANGEDSINGLEUNIT; // center. if( range <= 0 ) - map_foreachincell(skill_cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src); + map_foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src); if( !alive ) continue; - nullpo_retr(NULL, unit=skill_initunit(group,i,ux,uy,val1,val2)); + nullpo_retr(NULL, unit=skill->initunit(group,i,ux,uy,val1,val2)); unit->limit=limit; unit->range=range; - if (skill_id == PF_FOGWALL && alive == 2) - { //Double duration of cells on top of Deluge/Suiton + if (skill_id == PF_FOGWALL && alive == 2) { + //Double duration of cells on top of Deluge/Suiton unit->limit *= 2; group->limit = unit->limit; } // execute on all targets standing on this cell if (range==0 && active_flag) - map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); + map_foreachincell(skill->unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); } - if (!group->alive_count) - { //No cells? Something that was blocked completely by Land Protector? - skill_delunitgroup(group); + if (!group->alive_count) { //No cells? Something that was blocked completely by Land Protector? + skill->del_unitgroup(group,ALC_MARK); return NULL; } //success, unit created. switch( skill_id ) { case WZ_ICEWALL: - map_foreachinrange(skill_icewall_block, src, AREA_SIZE, BL_MOB); + map_foreachinrange(skill->icewall_block, src, AREA_SIZE, BL_MOB); break; case NJ_TATAMIGAESHI: //Store number of tiles. group->val1 = group->alive_count; @@ -10999,9 +10993,7 @@ struct skill_unit_group* skill_unitsetting (struct block_list *src, uint16 skill /*========================================== * *------------------------------------------*/ -void ext_skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsigned int tick){skill_unit_onplace(src, bl, tick);} -static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick) -{ +int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, unsigned int tick) { struct skill_unit_group *sg; struct block_list *ss; struct status_change *sc; @@ -11018,7 +11010,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un nullpo_ret(sg=src->group); nullpo_ret(ss=map_id2bl(sg->src_id)); - if( skill_get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR ) + if( skill->get_type(sg->skill_id) == BF_MAGIC && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR ) return 0; //AoE skills are ineffective. [Skotlex] sc = status_get_sc(bl); @@ -11029,195 +11021,191 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un type = status_skill2sc(sg->skill_id); sce = (sc && type != -1)?sc->data[type]:NULL; skill_id = sg->skill_id; //In case the group is deleted, we need to return the correct skill id, still. - switch (sg->unit_id) - { - case UNT_SPIDERWEB: - if( sc && sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1 > 0 ) - { // If you are fiberlocked and can't move, it will only increase your fireweakness level. [Inkfish] - sc->data[SC_SPIDERWEB]->val2++; - break; - } - else if( sc ) - { - int sec = skill_get_time2(sg->skill_id,sg->skill_lv); - if( status_change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) - { - const struct TimerData* td = sc->data[type]?get_timer(sc->data[type]->timer):NULL; - if( td ) - sec = DIFF_TICK(td->tick, tick); - map_moveblock(bl, src->bl.x, src->bl.y, tick); - clif_fixpos(bl); - sg->val2 = bl->id; + switch (sg->unit_id) { + case UNT_SPIDERWEB: + if( sc && sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1 > 0 ) { + // If you are fiberlocked and can't move, it will only increase your fireweakness level. [Inkfish] + sc->data[SC_SPIDERWEB]->val2++; + break; + } else if( sc && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) { + int sec = skill->get_time2(sg->skill_id,sg->skill_lv); + if( status_change_start(bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) { + const struct TimerData* td = sc->data[type]?get_timer(sc->data[type]->timer):NULL; + if( td ) + sec = DIFF_TICK(td->tick, tick); + map_moveblock(bl, src->bl.x, src->bl.y, tick); + clif->fixpos(bl); + sg->val2 = bl->id; + } + else + sec = 3000; //Couldn't trap it? + sg->limit = DIFF_TICK(tick,sg->tick)+sec; } - else - sec = 3000; //Couldn't trap it? - sg->limit = DIFF_TICK(tick,sg->tick)+sec; - } - break; - case UNT_SAFETYWALL: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); - break; + break; + case UNT_SAFETYWALL: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->skill_id,sg->group_id,0,sg->limit); + break; - case UNT_PNEUMA: - case UNT_CHAOSPANIC: - case UNT_MAELSTROM: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); - break; - case UNT_BLOODYLUST: - if (sg->src_id == bl->id) - break; //Does not affect the caster. - if (!sce) { - TBL_PC *sd = BL_CAST(BL_PC, bl); //prevent fullheal exploit - if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill_get_time2(SC_BLOODYLUST, 1)) - clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, - sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); - else { - if (sd) sd->bloodylust_tick = gettick(); - clif_skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, - sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill_get_time(LK_BERSERK, sg->skill_lv))); + case UNT_PNEUMA: + case UNT_CHAOSPANIC: + case UNT_MAELSTROM: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); + break; + case UNT_BLOODYLUST: + if (sg->src_id == bl->id) + break; //Does not affect the caster. + if (!sce) { + TBL_PC *sd = BL_CAST(BL_PC, bl); //prevent fullheal exploit + if (sd && sd->bloodylust_tick && DIFF_TICK(gettick(), sd->bloodylust_tick) < skill->get_time2(SC_BLOODYLUST, 1)) + clif->skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, + sc_start4(bl, type, 100, sg->skill_lv, 1, 0, 0, skill->get_time(LK_BERSERK, sg->skill_lv))); + else { + if (sd) sd->bloodylust_tick = gettick(); + clif->skill_nodamage(&src->bl,bl,sg->skill_id,sg->skill_lv, + sc_start4(bl, type, 100, sg->skill_lv, 0, 0, 0, skill->get_time(LK_BERSERK, sg->skill_lv))); + } } - } - break; + break; - case UNT_WARP_WAITING: { - int working = sg->val1&0xffff; + case UNT_WARP_WAITING: { + int working = sg->val1&0xffff; - if(bl->type==BL_PC && !working){ - struct map_session_data *sd = (struct map_session_data *)bl; - if((!sd->chatID || battle_config.chat_warpportal) - && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) - { - int x = sg->val2>>16; - int y = sg->val2&0xffff; - int count = sg->val1>>16; - unsigned short m = sg->val3; + if(bl->type==BL_PC && !working){ + struct map_session_data *sd = (struct map_session_data *)bl; + if((!sd->chatID || battle_config.chat_warpportal) + && sd->ud.to_x == src->bl.x && sd->ud.to_y == src->bl.y) + { + int x = sg->val2>>16; + int y = sg->val2&0xffff; + int count = sg->val1>>16; + unsigned short m = sg->val3; - if( --count <= 0 ) - skill_delunitgroup(sg); + if( --count <= 0 ) + skill->del_unitgroup(sg,ALC_MARK); - if ( map_mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y ) - working = 1;/* we break it because officials break it, lovely stuff. */ + if ( map_mapindex2mapid(sg->val3) == sd->bl.m && x == sd->bl.x && y == sd->bl.y ) + working = 1;/* we break it because officials break it, lovely stuff. */ - sg->val1 = (count<<16)|working; + sg->val1 = (count<<16)|working; - pc_setpos(sd,m,x,y,CLR_TELEPORT); + pc_setpos(sd,m,x,y,CLR_TELEPORT); + } + } else if(bl->type == BL_MOB && battle_config.mob_warp&2) { + int16 m = map_mapindex2mapid(sg->val3); + if (m < 0) break; //Map not available on this map-server. + unit_warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT); } - } else if(bl->type == BL_MOB && battle_config.mob_warp&2) { - int16 m = map_mapindex2mapid(sg->val3); - if (m < 0) break; //Map not available on this map-server. - unit_warp(bl,m,sg->val2>>16,sg->val2&0xffff,CLR_TELEPORT); } - } - break; + break; - case UNT_QUAGMIRE: - if( !sce && battle_check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) - sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); - break; + case UNT_QUAGMIRE: + if( !sce && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) + sc_start4(bl,type,100,sg->skill_lv,sg->group_id,0,0,sg->limit); + break; - case UNT_VOLCANO: - case UNT_DELUGE: - case UNT_VIOLENTGALE: - if(!sce) - sc_start(bl,type,100,sg->skill_lv,sg->limit); - break; + case UNT_VOLCANO: + case UNT_DELUGE: + case UNT_VIOLENTGALE: + if(!sce) + sc_start(bl,type,100,sg->skill_lv,sg->limit); + break; - case UNT_SUITON: - if(!sce) - sc_start4(bl,type,100,sg->skill_lv, - map_flag_vs(bl->m) || battle_check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. - 0,0,sg->limit); - break; + case UNT_SUITON: + if(!sce) + sc_start4(bl,type,100,sg->skill_lv, + map_flag_vs(bl->m) || battle->check_target(&src->bl,bl,BCT_ENEMY)>0?1:0, //Send val3 =1 to reduce agi. + 0,0,sg->limit); + break; - case UNT_HERMODE: - if (sg->src_id!=bl->id && battle_check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0) - status_change_clear_buffs(bl,1); //Should dispell only allies. - case UNT_RICHMANKIM: - case UNT_ETERNALCHAOS: - case UNT_DRUMBATTLEFIELD: - case UNT_RINGNIBELUNGEN: - case UNT_ROKISWEIL: - case UNT_INTOABYSS: - case UNT_SIEGFRIED: - //Needed to check when a dancer/bard leaves their ensemble area. - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) - return skill_id; - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - break; - case UNT_WHISTLE: - case UNT_ASSASSINCROSS: - case UNT_POEMBRAGI: - case UNT_APPLEIDUN: - case UNT_HUMMING: - case UNT_DONTFORGETME: - case UNT_FORTUNEKISS: - case UNT_SERVICEFORYOU: - if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) - return 0; + case UNT_HERMODE: + if (sg->src_id!=bl->id && battle->check_target(&src->bl,bl,BCT_PARTY|BCT_GUILD) > 0) + status_change_clear_buffs(bl,1); //Should dispell only allies. + case UNT_RICHMANKIM: + case UNT_ETERNALCHAOS: + case UNT_DRUMBATTLEFIELD: + case UNT_RINGNIBELUNGEN: + case UNT_ROKISWEIL: + case UNT_INTOABYSS: + case UNT_SIEGFRIED: + //Needed to check when a dancer/bard leaves their ensemble area. + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + return skill_id; + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + break; + case UNT_WHISTLE: + case UNT_ASSASSINCROSS: + case UNT_POEMBRAGI: + case UNT_APPLEIDUN: + case UNT_HUMMING: + case UNT_DONTFORGETME: + case UNT_FORTUNEKISS: + case UNT_SERVICEFORYOU: + if (sg->src_id==bl->id && !(sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_BARDDANCER)) + return 0; - if (!sc) return 0; - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); - else if (sce->val4 == 1) { - //Readjust timers since the effect will not last long. - sce->val4 = 0; - delete_timer(sce->timer, status_change_timer); - sce->timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); - } - break; + if (!sc) return 0; + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit); + else if (sce->val4 == 1) { + //Readjust timers since the effect will not last long. + sce->val4 = 0; + delete_timer(sce->timer, status_change_timer); + sce->timer = add_timer(tick+sg->limit, status_change_timer, bl->id, type); + } + break; - case UNT_FOGWALL: - if (!sce) - { - sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); - if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) - skill_additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick); - } - break; + case UNT_FOGWALL: + if (!sce) + { + sc_start4(bl, type, 100, sg->skill_lv, sg->val1, sg->val2, sg->group_id, sg->limit); + if (battle->check_target(&src->bl,bl,BCT_ENEMY)>0) + skill->additional_effect (ss, bl, sg->skill_id, sg->skill_lv, BF_MISC, ATK_DEF, tick); + } + break; - case UNT_GRAVITATION: - if (!sce) - sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); - break; + case UNT_GRAVITATION: + if (!sce) + sc_start4(bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit); + break; -// officially, icewall has no problems existing on occupied cells [ultramage] -// case UNT_ICEWALL: //Destroy the cell. [Skotlex] -// src->val1 = 0; -// if(src->limit + sg->tick > tick + 700) -// src->limit = DIFF_TICK(tick+700,sg->tick); -// break; + // officially, icewall has no problems existing on occupied cells [ultramage] + // case UNT_ICEWALL: //Destroy the cell. [Skotlex] + // src->val1 = 0; + // if(src->limit + sg->tick > tick + 700) + // src->limit = DIFF_TICK(tick+700,sg->tick); + // break; - case UNT_MOONLIT: - //Knockback out of area if affected char isn't in Moonlit effect - if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT) - break; - if (ss == bl) //Also needed to prevent infinite loop crash. + case UNT_MOONLIT: + //Knockback out of area if affected char isn't in Moonlit effect + if (sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT) + break; + if (ss == bl) //Also needed to prevent infinite loop crash. + break; + skill->blown(ss,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); break; - skill_blown(ss,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); - break; - case UNT_WALLOFTHORN: - if( status_get_mode(bl)&MD_BOSS ) - break; // iRO Wiki says that this skill don't affect to Boss monsters. - if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle_check_target(&src->bl,bl, BCT_ENEMY) == 1 ) - skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - break; + case UNT_WALLOFTHORN: + if( status_get_mode(bl)&MD_BOSS ) + break; // iRO Wiki says that this skill don't affect to Boss monsters. + if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle->check_target(&src->bl,bl, BCT_ENEMY) == 1 ) + skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + break; - case UNT_VOLCANIC_ASH: - if (!sce) - sc_start(bl, SC_ASH, 100, sg->skill_lv, skill_get_time(MH_VOLCANIC_ASH, sg->skill_lv)); - break; + case UNT_VOLCANIC_ASH: + if (!sce) + sc_start(bl, SC_ASH, 100, sg->skill_lv, skill->get_time(MH_VOLCANIC_ASH, sg->skill_lv)); + break; - case UNT_GD_LEADERSHIP: - case UNT_GD_GLORYWOUNDS: - case UNT_GD_SOULCOLD: - case UNT_GD_HAWKEYES: - if ( !sce ) - sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000); - break; + case UNT_GD_LEADERSHIP: + case UNT_GD_GLORYWOUNDS: + case UNT_GD_SOULCOLD: + case UNT_GD_HAWKEYES: + if ( !sce ) + sc_start4(bl,type,100,sg->skill_lv,0,0,0,1000); + break; } return skill_id; } @@ -11225,8 +11213,7 @@ static int skill_unit_onplace (struct skill_unit *src, struct block_list *bl, un /*========================================== * *------------------------------------------*/ -int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, unsigned int tick) -{ +int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, unsigned int tick) { struct skill_unit_group *sg; struct block_list *ss; TBL_PC* tsd; @@ -11268,8 +11255,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns } } - if ((ts = skill_unitgrouptickset_search(bl,sg,tick))) - { //Not all have it, eg: Traps don't have it even though they can be hit by Heaven's Drive [Skotlex] + if ((ts = skill->unitgrouptickset_search(bl,sg,tick))) { + //Not all have it, eg: Traps don't have it even though they can be hit by Heaven's Drive [Skotlex] diff = DIFF_TICK(tick,ts->tick); if (diff < 0) return 0; @@ -11279,11 +11266,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns ts->tick += sg->interval*(map_count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1); } - switch (sg->unit_id) - { + switch (sg->unit_id) { case UNT_FIREWALL: - case UNT_KAEN: - { + case UNT_KAEN: { int count=0; const int x = bl->x, y = bl->y; @@ -11292,24 +11277,22 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns //Take into account these hit more times than the timer interval can handle. do - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0); + skill->attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0); while(--src->val2 && x == bl->x && y == bl->y && ++count < SKILLUNITTIMER_INTERVAL/sg->interval && !status_isdead(bl)); if (src->val2<=0) - skill_delunit(src); + skill->delunit(src); } break; case UNT_SANCTUARY: - if( battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race==RC_DEMON ) + if( battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race==RC_DEMON ) { //Only damage enemies with offensive Sanctuary. [Skotlex] - if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 && skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0) ) + if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 && skill->attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0) ) sg->val1 -= 2; // reduce healing count if this was meant for damaging [hekate] - } - else - { - int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); + } else { + int heal = skill->calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); struct mob_data *md = BL_CAST(BL_MOB, bl); #ifdef RENEWAL if( md && md->class_ == MOBID_EMPERIUM ) @@ -11321,7 +11304,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns break; if( status_isimmune(bl) ) heal = 0; - clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); if( tsc && tsc->data[SC_AKAITSUKI] && heal ) heal = ~heal + 1; status_heal(bl, heal, 0, 0); @@ -11329,30 +11312,30 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns sg->val1--; } if( sg->val1 <= 0 ) - skill_delunitgroup(sg); + skill->del_unitgroup(sg,ALC_MARK); break; case UNT_EVILLAND: //Will heal demon and undead element monsters, but not players. - if ((bl->type == BL_PC) || (!battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race!=RC_DEMON)) + if ((bl->type == BL_PC) || (!battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race!=RC_DEMON)) { //Damage enemies - if(battle_check_target(&src->bl,bl,BCT_ENEMY)>0) - skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + if(battle->check_target(&src->bl,bl,BCT_ENEMY)>0) + skill->attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); } else { - int heal = skill_calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); + int heal = skill->calc_heal(ss,bl,sg->skill_id,sg->skill_lv,true); if (tstatus->hp >= tstatus->max_hp) break; if (status_isimmune(bl)) heal = 0; - clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); status_heal(bl, heal, 0, 0); } break; case UNT_MAGNUS: - if (!battle_check_undead(tstatus->race,tstatus->def_ele) && tstatus->race!=RC_DEMON) + if (!battle->check_undead(tstatus->race,tstatus->def_ele) && tstatus->race!=RC_DEMON) break; - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case UNT_DUMMYSKILL: @@ -11373,7 +11356,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns else // mobs if( status_charge(ss, 0, 2) ) // costs 2 SP per hit { - if( !skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0) ) + if( !skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick+count*sg->interval,0) ) status_charge(ss, 0, 8); //costs additional 8 SP if miss } else @@ -11392,35 +11375,35 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case WZ_STORMGUST: //SG counter does not reset per stormgust. IE: One hit from a SG and two hits from another will freeze you. if (tsc) tsc->sg_counter++; //SG hit counter. - if (skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc) + if (skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0) <= 0 && tsc) tsc->sg_counter=0; //Attack absorbed. break; #endif case GS_DESPERADO: if (rnd()%100 < src->val1) - skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case GN_CRAZYWEED_ATK: if( bl->type == BL_SKILL ){ struct skill_unit *su = (struct skill_unit *)bl; - if( su && !(skill_get_inf2(su->group->skill_id)&INF2_TRAP) ) + if( su && !(skill->get_inf2(su->group->skill_id)&INF2_TRAP) ) break; } default: - skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); } break; case UNT_FIREPILLAR_WAITING: - skill_unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); - skill_delunit(src); + skill->unitsetting(ss,sg->skill_id,sg->skill_lv,src->bl.x,src->bl.y,1); + skill->delunit(src); break; case UNT_SKIDTRAP: { - skill_blown(&src->bl,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); + skill->blown(&src->bl,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),unit_getdir(bl),0); sg->unit_id = UNT_USED_TRAPS; - clif_changetraplook(&src->bl, UNT_USED_TRAPS); + clif->changetraplook(&src->bl, UNT_USED_TRAPS); sg->limit=DIFF_TICK(tick,sg->tick)+1500; } break; @@ -11428,24 +11411,26 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_ANKLESNARE: case UNT_MANHOLE: if( sg->val2 == 0 && tsc && (sg->unit_id == UNT_ANKLESNARE || bl->id != sg->src_id) ) { - int sec = skill_get_time2(sg->skill_id,sg->skill_lv); + int sec = skill->get_time2(sg->skill_id,sg->skill_lv); if( status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) { const struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; if( td ) sec = DIFF_TICK(td->tick, tick); - unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); - clif_fixpos(bl); + if( sg->unit_id == UNT_MANHOLE || battle_config.skill_trap_type || !map_flag_gvg(src->bl.m) ) { + unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); + clif->fixpos(bl); + } sg->val2 = bl->id; } else sec = 3000; //Couldn't trap it? if( sg->unit_id == UNT_ANKLESNARE ) { - clif_skillunit_update(&src->bl); + clif->skillunit_update(&src->bl); /** * If you're snared from a trap that was invisible this makes the trap be * visible again -- being you stepped on it (w/o this the trap remains invisible and you go "WTF WHY I CANT MOVE") * bugreport:3961 **/ - clif_changetraplook(&src->bl, UNT_ANKLESNARE); + clif->changetraplook(&src->bl, UNT_ANKLESNARE); } sg->limit = DIFF_TICK(tick,sg->tick)+sec; sg->interval = -1; @@ -11457,21 +11442,21 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if( bl->id != ss->id ) { if( status_get_mode(bl)&MD_BOSS ) break; - if( status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id, sg->skill_lv), 8) ) { + if( status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 8) ) { map_moveblock(bl, src->bl.x, src->bl.y, tick); - clif_fixpos(bl); + clif->fixpos(bl); } - map_foreachinrange(skill_trap_splash, &src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick); + map_foreachinrange(skill->trap_splash, &src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl, tick); sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. } break; case UNT_VENOMDUST: if(tsc && !tsc->data[type]) - status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),0); + status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0); break; @@ -11494,9 +11479,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_FLASHER: case UNT_FREEZINGTRAP: case UNT_FIREPILLAR_ACTIVE: - map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + map_foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); if (sg->unit_id != UNT_FIREPILLAR_ACTIVE) - clif_changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); + clif->changetraplook(&src->bl, sg->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); sg->limit=DIFF_TICK(tick,sg->tick)+1500 + (sg->unit_id== UNT_CLUSTERBOMB || sg->unit_id== UNT_ICEBOUNDTRAP?1000:0);// Cluster Bomb/Icebound has 1s to disappear once activated. sg->unit_id = UNT_USED_TRAPS; //Changed ID so it does not invoke a for each in area again. @@ -11506,9 +11491,9 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns if (sg->src_id == bl->id) break; if (sg->val2 == 0){ - clif_talkiebox(&src->bl, sg->valstr); + clif->talkiebox(&src->bl, sg->valstr); sg->unit_id = UNT_USED_TRAPS; - clif_changetraplook(&src->bl, UNT_USED_TRAPS); + clif->changetraplook(&src->bl, UNT_USED_TRAPS); sg->limit = DIFF_TICK(tick, sg->tick) + 5000; sg->val2 = -1; } @@ -11517,16 +11502,16 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_LULLABY: if (ss->id == bl->id) break; - skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); + skill->additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); break; case UNT_UGLYDANCE: //Ugly Dance [Skotlex] if (ss->id != bl->id) - skill_additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); + skill->additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick); break; case UNT_DISSONANCE: - skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + skill->attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); break; case UNT_APPLEIDUN: //Apple of Idun [Skotlex] @@ -11539,53 +11524,53 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns #endif if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SPIRIT] && tsc->data[SC_SPIRIT]->val2 == SL_BARDDANCER) ) break; // affects self only when soullinked - heal = skill_calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); + heal = skill->calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true); if( tsc->data[SC_AKAITSUKI] && heal ) heal = ~heal + 1; - clif_skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); + clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1); status_heal(bl, heal, 0, 0); break; } case UNT_TATAMIGAESHI: case UNT_DEMONSTRATION: - skill_attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case UNT_GOSPEL: if (rnd()%100 > sg->skill_lv*10 || ss == bl) break; - if (battle_check_target(ss,bl,BCT_PARTY)>0) + if (battle->check_target(ss,bl,BCT_PARTY)>0) { // Support Effect only on party, not guild int heal; int i = rnd()%13; // Positive buff count - int time = skill_get_time2(sg->skill_id, sg->skill_lv); //Duration + int time = skill->get_time2(sg->skill_id, sg->skill_lv); //Duration switch (i) { case 0: // Heal 1~9999 HP heal = rnd() %9999+1; - clif_skill_nodamage(ss,bl,AL_HEAL,heal,1); + clif->skill_nodamage(ss,bl,AL_HEAL,heal,1); status_heal(bl,heal,0,0); break; case 1: // End all negative status status_change_clear_buffs(bl,6); - if (tsd) clif_gospel_info(tsd, 0x15); + if (tsd) clif->gospel_info(tsd, 0x15); break; case 2: // Immunity to all status sc_start(bl,SC_SCRESIST,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x16); + if (tsd) clif->gospel_info(tsd, 0x16); break; case 3: // MaxHP +100% sc_start(bl,SC_INCMHPRATE,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x17); + if (tsd) clif->gospel_info(tsd, 0x17); break; case 4: // MaxSP +100% sc_start(bl,SC_INCMSPRATE,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x18); + if (tsd) clif->gospel_info(tsd, 0x18); break; case 5: // All stats +20 sc_start(bl,SC_INCALLSTATUS,100,20,time); - if (tsd) clif_gospel_info(tsd, 0x19); + if (tsd) clif->gospel_info(tsd, 0x19); break; case 6: // Level 10 Blessing sc_start(bl,SC_BLESSING,100,10,time); @@ -11595,35 +11580,35 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns break; case 8: // Enchant weapon with Holy element sc_start(bl,SC_ASPERSIO,100,1,time); - if (tsd) clif_gospel_info(tsd, 0x1c); + if (tsd) clif->gospel_info(tsd, 0x1c); break; case 9: // Enchant armor with Holy element sc_start(bl,SC_BENEDICTIO,100,1,time); - if (tsd) clif_gospel_info(tsd, 0x1d); + if (tsd) clif->gospel_info(tsd, 0x1d); break; case 10: // DEF +25% sc_start(bl,SC_INCDEFRATE,100,25,time); - if (tsd) clif_gospel_info(tsd, 0x1e); + if (tsd) clif->gospel_info(tsd, 0x1e); break; case 11: // ATK +100% sc_start(bl,SC_INCATKRATE,100,100,time); - if (tsd) clif_gospel_info(tsd, 0x1f); + if (tsd) clif->gospel_info(tsd, 0x1f); break; case 12: // HIT/Flee +50 sc_start(bl,SC_INCHIT,100,50,time); sc_start(bl,SC_INCFLEE,100,50,time); - if (tsd) clif_gospel_info(tsd, 0x20); + if (tsd) clif->gospel_info(tsd, 0x20); break; } } - else if (battle_check_target(&src->bl,bl,BCT_ENEMY)>0) + else if (battle->check_target(&src->bl,bl,BCT_ENEMY)>0) { // Offensive Effect int i = rnd()%9; // Negative buff count - int time = skill_get_time2(sg->skill_id, sg->skill_lv); + int time = skill->get_time2(sg->skill_id, sg->skill_lv); switch (i) { case 0: // Deal 1~9999 damage - skill_attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(BF_MISC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case 1: // Curse sc_start(bl,SC_CURSE,100,1,time); @@ -11655,11 +11640,11 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_BASILICA: { - int i = battle_check_target(&src->bl, bl, BCT_ENEMY); + int i = battle->check_target(&src->bl, bl, BCT_ENEMY); if( i > 0 && !(status_get_mode(bl)&MD_BOSS) ) { // knock-back any enemy except Boss - skill_blown(&src->bl, bl, 2, unit_getdir(bl), 0); - clif_fixpos(bl); + skill->blown(&src->bl, bl, 2, unit_getdir(bl), 0); + clif->fixpos(bl); } if( sg->src_id != bl->id && i <= 0 ) @@ -11672,7 +11657,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_FIREWALK: case UNT_ELECTRICWALK: case UNT_PSYCHIC_WAVE: - skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case UNT_GROUNDDRIFT_WIND: @@ -11680,28 +11665,26 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_GROUNDDRIFT_POISON: case UNT_GROUNDDRIFT_WATER: case UNT_GROUNDDRIFT_FIRE: - map_foreachinrange(skill_trap_splash,&src->bl, - skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, + map_foreachinrange(skill->trap_splash,&src->bl, + skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); sg->unit_id = UNT_USED_TRAPS; - //clif_changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE); + //clif->changetraplook(&src->bl, UNT_FIREPILLAR_ACTIVE); sg->limit=DIFF_TICK(tick,sg->tick)+1500; break; /** * 3rd stuff **/ case UNT_POISONSMOKE: - if( battle_check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 20 ) - sc_start(bl,sg->val2,100,sg->val3,skill_get_time2(GC_POISONINGWEAPON, 1)); + if( battle->check_target(ss,bl,BCT_ENEMY) > 0 && !(tsc && tsc->data[sg->val2]) && rnd()%100 < 20 ) + sc_start(bl,sg->val2,100,sg->val3,skill->get_time2(GC_POISONINGWEAPON, 1)); break; case UNT_EPICLESIS: - if( bl->type == BL_PC && !battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) - { + if( bl->type == BL_PC && !battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) { if( ++sg->val2 % 3 == 0 ) { int hp, sp; - switch( sg->skill_lv ) - { + switch( sg->skill_lv ) { case 1: case 2: hp = 3; sp = 2; break; case 3: case 4: hp = 4; sp = 3; break; case 5: default: hp = 5; sp = 4; break; @@ -11719,8 +11702,8 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns } } /* Enable this if kRO fix the current skill. Currently no damage on undead and demon monster. [Jobbie] - else if( battle_check_target(ss, bl, BCT_ENEMY) > 0 && battle_check_undead(tstatus->race, tstatus->def_ele) ) - skill_castend_damage_id(&src->bl, bl, sg->skill_id, sg->skill_lv, 0, 0);*/ + else if( battle->check_target(ss, bl, BCT_ENEMY) > 0 && battle_check_undead(tstatus->race, tstatus->def_ele) ) + skill->castend_damage_id(&src->bl, bl, sg->skill_id, sg->skill_lv, 0, 0);*/ break; case UNT_STEALTHFIELD: @@ -11738,20 +11721,20 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns break; case UNT_REVERBERATION: - clif_changetraplook(&src->bl,UNT_USED_TRAPS); - map_foreachinrange(skill_trap_splash,&src->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); + clif->changetraplook(&src->bl,UNT_USED_TRAPS); + map_foreachinrange(skill->trap_splash,&src->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &src->bl,tick); sg->limit = DIFF_TICK(tick,sg->tick)+1000; sg->unit_id = UNT_USED_TRAPS; break; case UNT_SEVERE_RAINSTORM: - if( battle_check_target(&src->bl, bl, BCT_ENEMY) ) - skill_attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0); + if( battle->check_target(&src->bl, bl, BCT_ENEMY) > 0 ) + skill->attack(BF_WEAPON,ss,&src->bl,bl,WM_SEVERE_RAINSTORM_MELEE,sg->skill_lv,tick,0); break; case UNT_NETHERWORLD: - if( !(status_get_mode(bl)&MD_BOSS) && ss != bl && battle_check_target(&src->bl, bl, BCT_PARTY) ) { + if( !(status_get_mode(bl)&MD_BOSS) && ss != bl && battle->check_target(&src->bl, bl, BCT_PARTY) > 0 ) { if( !(tsc && tsc->data[type]) ){ - sc_start(bl, type, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); + sc_start(bl, type, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv)); sg->limit = DIFF_TICK(tick,sg->tick); sg->unit_id = UNT_USED_TRAPS; } @@ -11760,19 +11743,19 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_THORNS_TRAP: if( tsc ) { if( !sg->val2 ) { - int sec = skill_get_time2(sg->skill_id, sg->skill_lv); + int sec = skill->get_time2(sg->skill_id, sg->skill_lv); if( sc_start(bl, type, 100, sg->skill_lv, sec) ) { const struct TimerData* td = tsc->data[type]?get_timer(tsc->data[type]->timer):NULL; if( td ) sec = DIFF_TICK(td->tick, tick); ///map_moveblock(bl, src->bl.x, src->bl.y, tick); // in official server it doesn't behave like this. [malufett] - clif_fixpos(bl); + clif->fixpos(bl); sg->val2 = bl->id; } else sec = 3000; // Couldn't trap it? sg->limit = DIFF_TICK(tick, sg->tick) + sec; } else if( tsc->data[SC_THORNSTRAP] && bl->id == sg->val2 ) - skill_attack(skill_get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION); + skill->attack(skill->get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION); } break; @@ -11783,12 +11766,12 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case 2: default: sc_start(bl, SC_BURNING, 4 + 4 * sg->skill_lv, sg->skill_lv, - skill_get_time2(sg->skill_id, sg->skill_lv)); - skill_attack(skill_get_type(sg->skill_id), ss, &src->bl, bl, + skill->get_time2(sg->skill_id, sg->skill_lv)); + skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv + 10 * sg->val2, tick, 0); break; case 3: - skill_attack(skill_get_type(CR_ACIDDEMONSTRATION), ss, &src->bl, bl, + skill->attack(skill->get_type(CR_ACIDDEMONSTRATION), ss, &src->bl, bl, CR_ACIDDEMONSTRATION, sd ? pc_checkskill(sd, CR_ACIDDEMONSTRATION) : sg->skill_lv, tick, 0); break; @@ -11805,30 +11788,30 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns break; case UNT_HELLS_PLANT: - if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 ) - skill_attack(skill_get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0); + if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 ) + skill->attack(skill->get_type(GN_HELLS_PLANT_ATK), ss, &src->bl, bl, GN_HELLS_PLANT_ATK, sg->skill_lv, tick, 0); if( ss != bl) //The caster is the only one who can step on the Plants, without destroying them sg->limit = DIFF_TICK(tick, sg->tick) + 100; break; case UNT_CLOUD_KILL: if(tsc && !tsc->data[type]) - status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill_get_time2(sg->skill_id,sg->skill_lv),8); - skill_attack(skill_get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + status_change_start(bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),8); + skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case UNT_WARMER: - if( bl->type == BL_PC && !battle_check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) { + if( bl->type == BL_PC && !battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) { int hp = 125 * sg->skill_lv; // Officially is 125 * skill_lv. struct status_change *ssc = status_get_sc(ss); if( ssc && ssc->data[SC_HEATER_OPTION] ) hp += hp * ssc->data[SC_HEATER_OPTION]->val3 / 100; if( tstatus->hp != tstatus->max_hp ) - clif_skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0); + clif->skill_nodamage(&src->bl, bl, AL_HEAL, hp, 0); if( tsc && tsc->data[SC_AKAITSUKI] && hp ) hp = ~hp + 1; status_heal(bl, hp, 0, 0); - sc_start(bl, SC_WARMER, 100, sg->skill_lv, skill_get_time2(sg->skill_id,sg->skill_lv)); + sc_start(bl, SC_WARMER, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv)); } break; @@ -11838,10 +11821,10 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_EARTH_INSIGNIA: case UNT_ZEPHYR: sc_start(bl,type, 100, sg->skill_lv, sg->interval); - if (sg->unit_id != UNT_ZEPHYR && !battle_check_undead(tstatus->race, tstatus->def_ele)) { + if (sg->unit_id != UNT_ZEPHYR && !battle->check_undead(tstatus->race, tstatus->def_ele)) { int hp = tstatus->max_hp / 100; //+1% each 5s if ((sg->val3) % 5) { //each 5s - if (tstatus->def_ele == skill_get_ele(sg->skill_id,sg->skill_lv)){ + if (tstatus->def_ele == skill->get_ele(sg->skill_id,sg->skill_lv)){ status_heal(bl, hp, 0, 2); } else if((sg->unit_id == UNT_FIRE_INSIGNIA && tstatus->def_ele == ELE_EARTH) ||(sg->unit_id == UNT_WATER_INSIGNIA && tstatus->def_ele == ELE_FIRE) @@ -11859,7 +11842,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns case UNT_VACUUM_EXTREME: {// TODO: official behavior in gvg area. [malufett] int sec = sg->limit - DIFF_TICK(tick, sg->tick); - int range = skill_get_unit_range(sg->skill_id, sg->skill_lv); + int range = skill->get_unit_range(sg->skill_id, sg->skill_lv); if( tsc && !tsc->data[type] && distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range)// don't consider outer bounderies @@ -11880,58 +11863,58 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns distance_xy(src->bl.x, src->bl.y, bl->x, bl->y) <= range && // only snap if the target is inside the range or src->bl.x != bl->x && src->bl.y != bl->y){// diagonal position parallel to VE's center unit_movepos(bl, src->bl.x, src->bl.y, 0, 0); - clif_fixpos(bl); + clif->fixpos(bl); } } break; case UNT_FIRE_MANTLE: - if( battle_check_target(&src->bl, bl, BCT_ENEMY) ) - skill_attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); + if( battle->check_target(&src->bl, bl, BCT_ENEMY) > 0 ) + skill->attack(BF_MAGIC,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0); break; case UNT_ZENKAI_WATER: case UNT_ZENKAI_LAND: case UNT_ZENKAI_FIRE: case UNT_ZENKAI_WIND: - if( battle_check_target(&src->bl,bl,BCT_ENEMY) > 0 ){ + if( battle->check_target(&src->bl,bl,BCT_ENEMY) > 0 ){ switch( sg->unit_id ){ case UNT_ZENKAI_WATER: - sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_FREEZING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_CRYSTALIZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_FREEZE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_FREEZING, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_LAND: - sc_start(bl, SC_STONE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_POISON, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_STONE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_POISON, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_FIRE: - sc_start(bl, SC_BURNING, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_BURNING, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_ZENKAI_WIND: - sc_start(bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); - sc_start(bl, SC_DEEPSLEEP, sg->val1*5, sg->skill_lv, skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_SILENCE, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_SLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); + sc_start(bl, SC_DEEPSLEEP, sg->val1*5, sg->skill_lv, skill->get_time2(sg->skill_id, sg->skill_lv)); break; } }else - sc_start2(bl,type,100,sg->val1,sg->val2,skill_get_time2(sg->skill_id, sg->skill_lv)); + sc_start2(bl,type,100,sg->val1,sg->val2,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_MAKIBISHI: - skill_attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + skill->attack(BF_MISC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); sg->limit = DIFF_TICK(tick, sg->tick); sg->unit_id = UNT_USED_TRAPS; break; case UNT_LAVA_SLIDE: - skill_attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + skill->attack(BF_WEAPON, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); if(++sg->val1 > 4) //after 5 stop hit and destroy me sg->limit = DIFF_TICK(tick, sg->tick); break; case UNT_POISON_MIST: - skill_attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); - status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill_get_time2(sg->skill_id, sg->skill_lv), 2|8); + skill->attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0); + status_change_start(bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2|8); break; } @@ -11943,8 +11926,7 @@ int skill_unit_onplace_timer (struct skill_unit *src, struct block_list *bl, uns /*========================================== * Triggered when a char steps out of a skill cell *------------------------------------------*/ -int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned int tick) -{ +int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned int tick) { struct skill_unit_group *sg; struct status_change *sc; struct status_change_entry *sce; @@ -11962,35 +11944,34 @@ int skill_unit_onout (struct skill_unit *src, struct block_list *bl, unsigned in return 0; switch(sg->unit_id){ - case UNT_SAFETYWALL: - case UNT_PNEUMA: - case UNT_EPICLESIS://Arch Bishop - case UNT_NEUTRALBARRIER: - case UNT_STEALTHFIELD: - if (sce) - status_change_end(bl, type, INVALID_TIMER); - break; + case UNT_SAFETYWALL: + case UNT_PNEUMA: + case UNT_EPICLESIS://Arch Bishop + case UNT_NEUTRALBARRIER: + case UNT_STEALTHFIELD: + if (sce) + status_change_end(bl, type, INVALID_TIMER); + break; - case UNT_BASILICA: - if( sce && sce->val4 == src->bl.id ) - status_change_end(bl, type, INVALID_TIMER); - break; - case UNT_HERMODE: //Clear Hermode if the owner moved. - if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id) - status_change_end(bl, type, INVALID_TIMER); - break; + case UNT_BASILICA: + if( sce && sce->val4 == src->bl.id ) + status_change_end(bl, type, INVALID_TIMER); + break; + case UNT_HERMODE: //Clear Hermode if the owner moved. + if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id) + status_change_end(bl, type, INVALID_TIMER); + break; - case UNT_SPIDERWEB: - { - struct block_list *target = map_id2bl(sg->val2); - if (target && target==bl) - { - if (sce && sce->val3 == sg->group_id) - status_change_end(bl, type, INVALID_TIMER); - sg->limit = DIFF_TICK(tick,sg->tick)+1000; + case UNT_SPIDERWEB: { + struct block_list *target = map_id2bl(sg->val2); + if (target && target==bl) + { + if (sce && sce->val3 == sg->group_id) + status_change_end(bl, type, INVALID_TIMER); + sg->limit = DIFF_TICK(tick,sg->tick)+1000; + } + break; } - break; - } } return sg->skill_id; } @@ -12011,8 +11992,7 @@ static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned i type = status_skill2sc(skill_id); sce = (sc && type != -1)?sc->data[type]:NULL; - switch (skill_id) - { + switch (skill_id) { case WZ_QUAGMIRE: if (bl->type==BL_MOB) break; @@ -12072,21 +12052,18 @@ static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned i case DC_DONTFORGETME: case DC_FORTUNEKISS: case DC_SERVICEFORYOU: - if (sce) - { + if (sce) { delete_timer(sce->timer, status_change_timer); //NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas... //not possible on our current implementation. sce->val4 = 1; //Store the fact that this is a "reduced" duration effect. - sce->timer = add_timer(tick+skill_get_time2(skill_id,1), status_change_timer, bl->id, type); + sce->timer = add_timer(tick+skill->get_time2(skill_id,1), status_change_timer, bl->id, type); } break; case PF_FOGWALL: - if (sce) - { + if (sce) { status_change_end(bl, type, INVALID_TIMER); - if ((sce=sc->data[SC_BLIND])) - { + if ((sce=sc->data[SC_BLIND])) { if (bl->type == BL_PC) //Players get blind ended inmediately, others have it still for 30 secs. [Skotlex] status_change_end(bl, SC_BLIND, INVALID_TIMER); else { @@ -12114,8 +12091,7 @@ static int skill_unit_onleft (uint16 skill_id, struct block_list *bl, unsigned i * flag&1: Invoke onplace function (otherwise invoke onout) * flag&4: Invoke a onleft call (the unit might be scheduled for deletion) *------------------------------------------*/ -static int skill_unit_effect (struct block_list* bl, va_list ap) -{ +int skill_unit_effect (struct block_list* bl, va_list ap) { struct skill_unit* unit = va_arg(ap,struct skill_unit*); struct skill_unit_group* group = unit->group; unsigned int tick = va_arg(ap,unsigned int); @@ -12128,25 +12104,25 @@ static int skill_unit_effect (struct block_list* bl, va_list ap) nullpo_ret(group); - dissonance = skill_dance_switch(unit, 0); + dissonance = skill->dance_switch(unit, 0); //Necessary in case the group is deleted after calling on_place/on_out [Skotlex] skill_id = group->skill_id; //Target-type check. - if( !(group->bl_flag&bl->type && battle_check_target(&unit->bl,bl,group->target_flag)>0) && (flag&4) ) { + if( !(group->bl_flag&bl->type && battle->check_target(&unit->bl,bl,group->target_flag)>0) && (flag&4) ) { if( group->state.song_dance&0x1 || (group->src_id == bl->id && group->state.song_dance&0x2) ) - skill_unit_onleft(skill_id, bl, tick);//Ensemble check to terminate it. + skill->unit_onleft(skill_id, bl, tick);//Ensemble check to terminate it. } else { if( flag&1 ) - skill_unit_onplace(unit,bl,tick); + skill->unit_onplace(unit,bl,tick); else - skill_unit_onout(unit,bl,tick); + skill->unit_onout(unit,bl,tick); if( flag&4 ) - skill_unit_onleft(skill_id, bl, tick); + skill->unit_onleft(skill_id, bl, tick); } - if( dissonance ) skill_dance_switch(unit, 1); + if( dissonance ) skill->dance_switch(unit, 1); return 0; } @@ -12187,8 +12163,7 @@ int skill_unit_ondamaged (struct skill_unit *src, struct block_list *bl, int dam /*========================================== * *------------------------------------------*/ -static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) -{ +int skill_check_condition_char_sub (struct block_list *bl, va_list ap) { int *c, skill_id; struct block_list *src; struct map_session_data *sd; @@ -12204,7 +12179,7 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) p_sd = va_arg(ap, int *); skill_id = va_arg(ap,int); - if ( ((skill_id != PR_BENEDICTIO && *c >=1) || *c >=2) && !(skill_get_inf2(skill_id)&INF2_CHORUS_SKILL) ) + if ( ((skill_id != PR_BENEDICTIO && *c >=1) || *c >=2) && !(skill->get_inf2(skill_id)&INF2_CHORUS_SKILL) ) return 0; //Partner found for ensembles, or the two companions for Benedictio. [Skotlex] if (bl == src) @@ -12216,7 +12191,7 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) if (tsd->sc.data[SC_SILENCE] || ( tsd->sc.opt1 && tsd->sc.opt1 != OPT1_BURNING )) return 0; - if( skill_get_inf2(skill_id)&INF2_CHORUS_SKILL ) { + if( skill->get_inf2(skill_id)&INF2_CHORUS_SKILL ) { if( tsd->status.party_id == sd->status.party_id && (tsd->class_&MAPID_THIRDMASK) == MAPID_MINSTRELWANDERER ) p_sd[(*c)++] = tsd->bl.id; return 1; @@ -12275,12 +12250,11 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) /*========================================== * Checks and stores partners for ensemble skills [Skotlex] *------------------------------------------*/ -int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short* skill_lv, int range, int cast_flag) -{ +int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short* skill_lv, int range, int cast_flag) { static int c=0; static int p_sd[2] = { 0, 0 }; int i; - bool is_chorus = ( skill_get_inf2(skill_id)&INF2_CHORUS_SKILL ); + bool is_chorus = ( skill->get_inf2(skill_id)&INF2_CHORUS_SKILL ); if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL)) return is_chorus ? MAX_PARTY : 99; //As if there were infinite partners. @@ -12303,7 +12277,7 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short* case WM_GREAT_ECHO: for( i = 0; i < c; i++ ) { if( (tsd = map_id2sd(p_sd[i])) != NULL ) - status_zap(&tsd->bl,0,skill_get_sp(skill_id,*skill_lv)/c); + status_zap(&tsd->bl,0,skill->get_sp(skill_id,*skill_lv)/c); } break; default: //Warning: Assuming Ensemble skills here (for speed) @@ -12311,8 +12285,8 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short* break;//Chorus skills are not to be parsed as ensambles if (c > 0 && sd->sc.data[SC_DANCING] && (tsd = map_id2sd(p_sd[0])) != NULL) { sd->sc.data[SC_DANCING]->val4 = tsd->bl.id; - sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill_get_time(skill_id,*skill_lv)+1000); - clif_skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1); + sc_start4(&tsd->bl,SC_DANCING,100,skill_id,sd->sc.data[SC_DANCING]->val2,*skill_lv,sd->bl.id,skill->get_time(skill_id,*skill_lv)+1000); + clif->skill_nodamage(&tsd->bl, &sd->bl, skill_id, *skill_lv, 1); tsd->skill_id_dance = skill_id; tsd->skill_lv_dance = *skill_lv; } @@ -12324,9 +12298,9 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short* c = 0; memset (p_sd, 0, sizeof(p_sd)); if( is_chorus ) - i = party_foreachsamemap(skill_check_condition_char_sub,sd,AREA_SIZE,&sd->bl, &c, &p_sd, skill_id, *skill_lv); + i = party_foreachsamemap(skill->check_condition_char_sub,sd,AREA_SIZE,&sd->bl, &c, &p_sd, skill_id, *skill_lv); else - i = map_foreachinrange(skill_check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id); + i = map_foreachinrange(skill->check_condition_char_sub, &sd->bl, range, BL_PC, &sd->bl, &c, &p_sd, skill_id); if ( skill_id != PR_BENEDICTIO && skill_id != AB_ADORAMUS && skill_id != WL_COMET ) //Apply the average lv to encore skills. *skill_lv = (i+(*skill_lv))/(c+1); //I know c should be one, but this shows how it could be used for the average of n partners. @@ -12336,8 +12310,7 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, short* /*========================================== * *------------------------------------------*/ -static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) -{ +int skill_check_condition_mob_master_sub (struct block_list *bl, va_list ap) { int *c,src_id,mob_class,skill; struct mob_data *md; @@ -12360,15 +12333,15 @@ static int skill_check_condition_mob_master_sub (struct block_list *bl, va_list * Determines if a given skill should be made to consume ammo * when used by the player. [Skotlex] *------------------------------------------*/ -int skill_isammotype (struct map_session_data *sd, int skill) +int skill_isammotype (struct map_session_data *sd, int skill_id) { return ( battle_config.arrow_decrement==2 && (sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) && - skill != HT_PHANTASMIC && - skill_get_type(skill) == BF_WEAPON && - !(skill_get_nk(skill)&NK_NO_DAMAGE) && - !skill_get_spiritball(skill,1) //Assume spirit spheres are used as ammo instead. + skill_id != HT_PHANTASMIC && + skill->get_type(skill_id) == BF_WEAPON && + !(skill->get_nk(skill_id)&NK_NO_DAMAGE) && + !skill->get_spiritball(skill_id,1) //Assume spirit spheres are used as ammo instead. ); } @@ -12384,7 +12357,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id ) { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] - sd->state.arrow_atk = skill_get_ammotype(skill_id)?1:0; //Need to do arrow state check. + sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check. sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. return 1; } @@ -12414,12 +12387,11 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id if( !sc->count ) sc = NULL; - if( sd->skillitem == skill_id ) - { + if( sd->skillitem == skill_id ) { if( sd->state.abra_flag ) // Hocus-Pocus was used. [Inkfish] sd->state.abra_flag = 0; - else - { // When a target was selected, consume items that were skipped in pc_use_item [Skotlex] + else { + // When a target was selected, consume items that were skipped in pc_use_item [Skotlex] if( (i = sd->itemindex) == -1 || sd->status.inventory[i].nameid != sd->itemid || sd->inventory_data[i] == NULL || @@ -12440,9 +12412,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id return 1; } - if( pc_is90overweight(sd) ) - { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_WEIGHTOVER,0); + if( pc_is90overweight(sd) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_WEIGHTOVER,0); return 0; } @@ -12483,7 +12454,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case BS_ADRENALINE2: case NC_POWERSWING: case BS_UNFAIRLYTRICK: case NC_AXETORNADO: case BS_GREED: - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; default: //Only Mechanic exlcusive skill can be used. break; @@ -12491,8 +12462,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) return 0; - - require = skill_get_requirement(sd,skill_id,skill_lv); + + require = skill->get_requirement(sd,skill_id,skill_lv); //Can only update state when weapon/arrow info is checked. sd->state.arrow_atk = require.ammo?1:0; @@ -12501,19 +12472,19 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id switch( skill_id ) { case SO_SPELLFIST: if(sd->skill_id_old != MG_FIREBOLT && sd->skill_id_old != MG_COLDBOLT && sd->skill_id_old != MG_LIGHTNINGBOLT){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } case SA_CASTCANCEL: if(sd->ud.skilltimer == INVALID_TIMER) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case AL_WARP: if(!battle_config.duel_allow_teleport && sd->duel_group) { // duel restriction [LuzZza] - char output[128]; sprintf(output, msg_txt(365), skill_get_name(AL_WARP)); - clif_displaymessage(sd->fd, output); //"Duel: Can't use %s in duel." + char output[128]; sprintf(output, msg_txt(365), skill->get_name(AL_WARP)); + clif->message(sd->fd, output); //"Duel: Can't use %s in duel." return 0; } break; @@ -12521,7 +12492,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id if(sc && sc->data[SC_RAISINGDRAGON]) skill_lv += sc->data[SC_RAISINGDRAGON]->val1; if(sd->spiritball >= skill_lv) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12561,8 +12532,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id // return 0; if( sc && (sc->data[SC_BLADESTOP] || sc->data[SC_CURSEDCIRCLE_ATKER]) ) break; - if( sc && sc->data[SC_COMBO] ) - { + if( sc && sc->data[SC_COMBO] ) { switch(sc->data[SC_COMBO]->val1) { case MO_COMBOFINISH: case CH_TIGERFIST: @@ -12574,15 +12544,15 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id } else if( !unit_can_move(&sd->bl) ) { //Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex] - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case TK_MISSION: - if( (sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON ) - {// Cannot be used by Non-Taekwon classes - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( (sd->class_&MAPID_UPPERMASK) != MAPID_TAEKWON ) { + // Cannot be used by Non-Taekwon classes + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12592,9 +12562,9 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case TK_READYSTORM: case TK_READYTURN: case TK_JUMPKICK: - if( (sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER ) - {// Soul Linkers cannot use this skill - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if( (sd->class_&MAPID_UPPERMASK) == MAPID_SOUL_LINKER ) { + // Soul Linkers cannot use this skill + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12625,25 +12595,25 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id int time; if(!(sc && sc->data[SC_DANCING])) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } time = 1000*(sc->data[SC_DANCING]->val3>>16); - if (skill_get_time( + if (skill->get_time( (sc->data[SC_DANCING]->val1&0xFFFF), //Dance Skill ID (sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV - - time < skill_get_time2(skill_id,skill_lv)) + - time < skill->get_time2(skill_id,skill_lv)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } } break; case PR_BENEDICTIO: - if (skill_check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 2) + if (skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 2) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12659,21 +12629,21 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case CG_HERMODE: - if(!npc_check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill_get_splash(skill_id, skill_lv))) + if(!npc_check_areanpc(1,sd->bl.m,sd->bl.x,sd->bl.y,skill->get_splash(skill_id, skill_lv))) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case CG_MOONLIT: //Check there's no wall in the range+1 area around the caster. [Skotlex] { - int i,x,y,range = skill_get_splash(skill_id, skill_lv)+1; + int i,x,y,range = skill->get_splash(skill_id, skill_lv)+1; int size = range*2+1; for (i=0;i<size*size;i++) { x = sd->bl.x+(i%size-range); y = sd->bl.y+(i/size-range); if (map_getcell(sd->bl.m,x,y,CELL_CHKWALL)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } } @@ -12684,7 +12654,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id int exp; if( ((exp = pc_nextbaseexp(sd)) > 0 && get_percentage(sd->status.base_exp, exp) < 1) || ((exp = pc_nextjobexp(sd)) > 0 && get_percentage(sd->status.job_exp, exp) < 1)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); //Not enough exp. + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); //Not enough exp. return 0; } break; @@ -12693,7 +12663,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case AM_TWILIGHT3: if (!party_skill_check(sd, sd->status.party_id, skill_id, skill_lv)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12705,7 +12675,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id i = skill_id-SG_SUN_WARM; if (sd->bl.m == sd->feel_map[i].m) break; - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; break; case SG_SUN_COMFORT: @@ -12717,7 +12687,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id if (sd->bl.m == sd->feel_map[i].m && (battle_config.allow_skill_without_day || sg_info[i].day_func())) break; - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; case SG_FUSION: if (sc && sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_STAR) @@ -12727,7 +12697,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id if( require.sp > 0 ) { if (status->sp < (unsigned int)require.sp) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0); else status_zap(&sd->bl, 0, require.sp); } @@ -12736,7 +12706,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case GD_REGENERATION: case GD_RESTORE: if (!map_flag_gvg2(sd->bl.m)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } case GD_EMERGENCYCALL: @@ -12747,7 +12717,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case GS_GLITTERING: if(sd->spiritball >= 10) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12758,12 +12728,12 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id #else if (status->hp < 2) { #endif - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } case NJ_BUNSINJYUTSU: if (!(sc && sc->data[SC_NEN])) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12771,7 +12741,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case NJ_ZENYNAGE: case KO_MUCHANAGE: if(sd->status.zeny < require.zeny) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_MONEY,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_MONEY,0); return 0; } break; @@ -12781,14 +12751,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id break; case AM_CALLHOMUN: //Can't summon if a hom is already out if (sd->status.hom_id && sd->hd && !sd->hd->homunculus.vaporize) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case AM_REST: //Can't vapo homun if you don't have an active homunc or it's hp is < 80% - if (!merc_is_hom_active(sd->hd) || sd->hd->battle_status.hp < (sd->hd->battle_status.max_hp*80/100)) + if (!homun_alive(sd->hd) || sd->hd->battle_status.hp < (sd->hd->battle_status.max_hp*80/100)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12802,7 +12772,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id if( sd->status.inventory[i].nameid == ITEMID_ANCILLA ) count += sd->status.inventory[i].amount; if( count >= 3 ) { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_ANCILLA_NUMOVER, 0); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_ANCILLA_NUMOVER, 0); return 0; } } @@ -12814,7 +12784,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id //case AB_LAUDAAGNUS: //case AB_LAUDARAMUS: // if( !sd->status.party_id ) { - // clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + // clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); // return 0; // } // break; @@ -12824,10 +12794,10 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id * Warlock **/ case WL_COMET: - if( skill_check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0 && ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[i].amount < require.amount[0]) ) + if( skill->check_pc_partner(sd,skill_id,&skill_lv,1,0) <= 0 && ((i = pc_search_inventory(sd,require.itemid[0])) < 0 || sd->status.inventory[i].amount < require.amount[0]) ) { - //clif_skill_fail(sd,skill_id,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]); - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + //clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_ITEM,require.amount[0],require.itemid[0]); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12840,7 +12810,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id ARR_FIND(SC_SPHERE_1,SC_SPHERE_5+1,i,!sc->data[i]); if( i == SC_SPHERE_5+1 ) { // No more free slots - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0); return 0; } } @@ -12850,14 +12820,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id **/ case GC_HALLUCINATIONWALK: if( sc && (sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HALLUCINATIONWALK_POSTDELAY]) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case GC_COUNTERSLASH: case GC_WEAPONCRUSH: if( !(sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == GC_WEAPONBLOCKING) ) { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_WEAPONBLOCKING, 0); return 0; } break; @@ -12866,25 +12836,25 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id **/ case RA_WUGMASTERY: if( pc_isfalcon(sd) || pc_isridingwug(sd) || sd->sc.data[SC__GROOMY]) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case RA_WUGSTRIKE: if( !pc_iswug(sd) && !pc_isridingwug(sd) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case RA_WUGRIDER: if( pc_isfalcon(sd) || ( !pc_isridingwug(sd) && !pc_iswug(sd) ) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case RA_WUGDASH: if(!pc_isridingwug(sd)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12893,19 +12863,19 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id **/ case LG_BANDING: if( sc && sc->data[SC_INSPIRATION] ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case LG_PRESTIGE: if( sc && (sc->data[SC_BANDING] || sc->data[SC_INSPIRATION]) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case LG_RAGEBURST: if( sd->spiritball == 0 ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SKILLINTERVAL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SKILLINTERVAL,0); return 0; } sd->spiritball_old = require.spiritball = sd->spiritball; @@ -12914,14 +12884,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id if( sc && sc->data[SC_INSPIRATION] ) return 1; // Don't check for partner. if( !(sc && sc->data[SC_BANDING]) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL,0); return 0; - } else if( skill_check_pc_partner(sd,skill_id,&skill_lv,skill_get_range(skill_id,skill_lv),0) < 1 ) + } else if( skill->check_pc_partner(sd,skill_id,&skill_lv,skill->get_range(skill_id,skill_lv),0) < 1 ) return 0; // Just fails, no msg here. break; case LG_HESPERUSLIT: if( !sc || !sc->data[SC_BANDING] ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -12932,24 +12902,24 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case SR_CRESCENTELBOW: if( sc && sc->data[SC_CRESCENTELBOW] ) { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_DUPLICATE, 0); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_DUPLICATE, 0); return 0; } break; case SR_CURSEDCIRCLE: if (map_flag_gvg(sd->bl.m)) { - if (map_foreachinrange(mob_count_sub, &sd->bl, skill_get_splash(skill_id, skill_lv), BL_MOB, + if (map_foreachinrange(mob_count_sub, &sd->bl, skill->get_splash(skill_id, skill_lv), BL_MOB, MOBID_EMPERIUM, MOBID_GUARIDAN_STONE1, MOBID_GUARIDAN_STONE2)) { char output[128]; sprintf(output, "You're too close to a stone or emperium to do this skill"); - clif_colormes(sd, COLOR_RED, output); + clif->colormes(sd->fd, COLOR_RED, output); return 0; } } if( sd->spiritball > 0 ) sd->spiritball_old = require.spiritball = sd->spiritball; else { - clif_skill_fail(sd,skill_id,0,0); + clif->skill_fail(sd,skill_id,0,0); return 0; } break; @@ -12960,15 +12930,15 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case SC_MANHOLE: case SC_DIMENSIONDOOR: if( sc && sc->data[SC_MAGNETICFIELD] ) { - clif_skill_fail(sd,skill_id,0,0); + clif->skill_fail(sd,skill_id,0,0); return 0; } break; case WM_GREAT_ECHO: { int count; - count = skill_check_pc_partner(sd, skill_id, &skill_lv, skill_get_splash(skill_id,skill_lv), 0); + count = skill->check_pc_partner(sd, skill_id, &skill_lv, skill->get_splash(skill_id,skill_lv), 0); if( count < 1 ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_NEED_HELPER,0); return 0; } else require.sp -= require.sp * 20 * count / 100; // -20% each W/M in the party. @@ -12977,27 +12947,27 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case SO_FIREWALK: case SO_ELECTRICWALK: // Can't be casted until you've walked all cells. if( sc && sc->data[SC_PROPERTYWALK] && - sc->data[SC_PROPERTYWALK]->val3 < skill_get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) { - clif_skill_fail(sd,skill_id,0x0,0); + sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) { + clif->skill_fail(sd,skill_id,0x0,0); return 0; } break; case SO_EL_CONTROL: if( !sd->status.ele_id || !sd->ed ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case RETURN_TO_ELDICASTES: if( pc_ismadogear(sd) ) { //Cannot be used if Mado is equipped. - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; case LG_REFLECTDAMAGE: case CR_REFLECTSHIELD: if( sc && sc->data[SC_KYOMU] && rand()%100 < 30){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; @@ -13006,10 +12976,10 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case KO_KAZEHU_SEIRAN: case KO_DOHU_KOUKAI: { - int ttype = skill_get_ele(skill_id, skill_lv); + int ttype = skill->get_ele(skill_id, skill_lv); ARR_FIND(1, 5, i, sd->talisman[i] > 0 && i != ttype); if( (i < 5 && i != ttype) || sd->talisman[ttype] >= 10 ){ - clif_skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); return 0; } } @@ -13018,190 +12988,203 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id case KO_ZENKAI: ARR_FIND(1, 6, i, sd->talisman[i] > 0); if( i > 4 ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } break; } switch(require.state) { - case ST_HIDING: - if(!(sc && sc->option&OPTION_HIDE)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_CLOAKING: - if(!pc_iscloaking(sd)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_HIDDEN: - if(!pc_ishiding(sd)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_RIDING: - if(!pc_isriding(sd)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_FALCON: - if(!pc_isfalcon(sd)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_CARTBOOST: - if(!(sc && sc->data[SC_CARTBOOST])) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - case ST_CART: - if(!pc_iscarton(sd)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_SHIELD: - if(sd->status.shield <= 0) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_SIGHT: - if(!(sc && sc->data[SC_SIGHT])) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_EXPLOSIONSPIRITS: - if(!(sc && sc->data[SC_EXPLOSIONSPIRITS])) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_RECOV_WEIGHT_RATE: - if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= (unsigned int)battle_config.natural_heal_weight_rate) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case ST_MOVE_ENABLE: - if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_id) - sd->ud.canmove_tick = gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex] + case ST_HIDING: + if(!(sc && sc->option&OPTION_HIDE)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_CLOAKING: + if(!pc_iscloaking(sd)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_HIDDEN: + if(!pc_ishiding(sd)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_RIDING: + if(!pc_isriding(sd) && !pc_isridingdragon(sd)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_FALCON: + if(!pc_isfalcon(sd)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_CARTBOOST: + if(!(sc && sc->data[SC_CARTBOOST])) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + case ST_CART: + if(!pc_iscarton(sd)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_SHIELD: + if(sd->status.shield <= 0) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_SIGHT: + if(!(sc && sc->data[SC_SIGHT])) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_EXPLOSIONSPIRITS: + if(!(sc && sc->data[SC_EXPLOSIONSPIRITS])) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_RECOV_WEIGHT_RATE: + if(battle_config.natural_heal_weight_rate <= 100 && sd->weight*100/sd->max_weight >= (unsigned int)battle_config.natural_heal_weight_rate) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_MOVE_ENABLE: + if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_id) + sd->ud.canmove_tick = gettick(); //When using a combo, cancel the can't move delay to enable the skill. [Skotlex] - if (!unit_can_move(&sd->bl)) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if (!unit_can_move(&sd->bl)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_WATER: + if (sc && (sc->data[SC_DELUGE] || sc->data[SC_SUITON])) + break; + if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER)) + break; + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; - } - break; - case ST_WATER: - if (sc && (sc->data[SC_DELUGE] || sc->data[SC_SUITON])) + case ST_RIDINGDRAGON: + if( !pc_isridingdragon(sd) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } break; - if (map_getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKWATER)) + case ST_WUG: + if( !pc_iswug(sd) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_RIDINGWUG: + if( !pc_isridingwug(sd) ){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_MADO: + if( !pc_ismadogear(sd) ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; + case ST_ELEMENTALSPIRIT: + if(!sd->ed) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_EL_SUMMON,0); + return 0; + } + break; + case ST_POISONINGWEAPON: + if (!(sc && sc->data[SC_POISONINGWEAPON])) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_GC_POISONINGWEAPON, 0); + return 0; + } + break; + case ST_ROLLINGCUTTER: + if (!(sc && sc->data[SC_ROLLINGCUTTER])) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0); + return 0; + } + break; + case ST_MH_FIGHTING: + if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_FIGHTING)){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + case ST_MH_GRAPPLING: + if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_GRAPPLING)){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + case ST_PECO: + if(!pc_isriding(sd)) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } break; - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - /** - * Rune Knight - **/ - case ST_RIDINGDRAGON: - if( !pc_isridingdragon(sd) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Wug - **/ - case ST_WUG: - if( !pc_iswug(sd) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Riding Wug - **/ - case ST_RIDINGWUG: - if( !pc_isridingwug(sd) ){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Mechanic - **/ - case ST_MADO: - if( !pc_ismadogear(sd) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - /** - * Sorcerer - **/ - case ST_ELEMENTALSPIRIT: - if(!sd->ed) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_EL_SUMMON,0); - return 0; - } - break; - case ST_POISONINGWEAPON: - if (!(sc && sc->data[SC_POISONINGWEAPON])) { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_GC_POISONINGWEAPON, 0); - return 0; - } - break; - case ST_ROLLINGCUTTER: - if (!(sc && sc->data[SC_ROLLINGCUTTER])) { - clif_skill_fail(sd, skill_id, USESKILL_FAIL_CONDITION, 0); - return 0; - } - break; - case ST_MH_FIGHTING: - if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_FIGHTING)){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - case ST_MH_GRAPPLING: - if (!(sc && sc->data[SC_STYLE_CHANGE] && sc->data[SC_STYLE_CHANGE]->val2 == MH_MD_GRAPPLING)){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } } if(require.mhp > 0 && get_percentage(status->hp, status->max_hp) > require.mhp) { //mhp is the max-hp-requirement, that is, //you must have this % or less of HP to cast it. - clif_skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); return 0; } if( require.weapon && !pc_check_weapontype(sd,require.weapon) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0); return 0; } if( require.sp > 0 && status->sp < (unsigned int)require.sp) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SP_INSUFFICIENT,0); return 0; } if( require.zeny > 0 && sd->status.zeny < require.zeny ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_MONEY,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_MONEY,0); return 0; } if( require.spiritball > 0 && sd->spiritball < require.spiritball) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_SPIRITS,require.spiritball); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_SPIRITS,require.spiritball); return 0; } + if( sd->sc.data[SC_COMBO] ) { + switch( skill_id ) { + case MO_CHAINCOMBO: + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + case MO_EXTREMITYFIST: + case TK_TURNKICK: + case TK_STORMKICK: + case TK_DOWNKICK: + case TK_COUNTER: + case HT_POWER: + case GC_COUNTERSLASH: + case GC_WEAPONCRUSH: + case SR_FALLENEMPIRE: + case SR_DRAGONCOMBO: + case SR_TIGERCANNON: + break; + default: return 0; + } + } + return 1; } @@ -13219,7 +13202,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id ) { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex] - sd->state.arrow_atk = skill_get_ammotype(skill_id)?1:0; //Need to do arrow state check. + sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check. sd->spiritball_old = sd->spiritball; //Need to do Spiritball check. return 1; } @@ -13244,33 +13227,36 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, return 0; break; } - - if( sd->skillitem == skill_id ) // Casting finished (Item skill or Hocus-Pocus) + /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ +#if 0 + if( sd->state.abra_flag ) // Casting finished (Hocus-Pocus) + return 1; +#endif + if( sd->skillitem == skill_id ) return 1; - if( pc_is90overweight(sd) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_WEIGHTOVER,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_WEIGHTOVER,0); return 0; } // perform skill-specific checks (and actions) switch( skill_id ) { case PR_BENEDICTIO: - skill_check_pc_partner(sd, skill_id, &skill_lv, 1, 1); + skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 1); break; case AM_CANNIBALIZE: case AM_SPHEREMINE: { int c=0; int summons[5] = { 1589, 1579, 1575, 1555, 1590 }; //int summons[5] = { 1020, 1068, 1118, 1500, 1368 }; - int maxcount = (skill_id==AM_CANNIBALIZE)? 6-skill_lv : skill_get_maxcount(skill_id,skill_lv); + int maxcount = (skill_id==AM_CANNIBALIZE)? 6-skill_lv : skill->get_maxcount(skill_id,skill_lv); int mob_class = (skill_id==AM_CANNIBALIZE)? summons[skill_lv-1] :1142; if(battle_config.land_skill_limit && maxcount>0 && (battle_config.land_skill_limit&BL_PC)) { - i = map_foreachinmap(skill_check_condition_mob_master_sub ,sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c); + i = map_foreachinmap(skill->check_condition_mob_master_sub ,sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c); if(c >= maxcount || (skill_id==AM_CANNIBALIZE && c != i && battle_config.summon_flora&2)) { //Fails when: exceed max limit. There are other plant types already out. - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } } @@ -13279,7 +13265,7 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, case NC_SILVERSNIPER: case NC_MAGICDECOY: { int c = 0, j; - int maxcount = skill_get_maxcount(skill_id,skill_lv); + int maxcount = skill->get_maxcount(skill_id,skill_lv); int mob_class = 2042; if( skill_id == NC_MAGICDECOY ) mob_class = 2043; @@ -13287,11 +13273,11 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, if( battle_config.land_skill_limit && maxcount > 0 && ( battle_config.land_skill_limit&BL_PC ) ) { if( skill_id == NC_MAGICDECOY ) { for( j = mob_class; j <= 2046; j++ ) - map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, j, skill_id, &c); + map_foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, j, skill_id, &c); } else - map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c); + map_foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, mob_class, skill_id, &c); if( c >= maxcount ) { - clif_skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0); + clif->skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0); return 0; } } @@ -13299,10 +13285,9 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, break; case KO_ZANZOU: { int c = 0; - i = map_foreachinmap(skill_check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill_id, &c); - if( c >= skill_get_maxcount(skill_id,skill_lv) || c != i) - { - clif_skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0); + i = map_foreachinmap(skill->check_condition_mob_master_sub, sd->bl.m, BL_MOB, sd->bl.id, 2308, skill_id, &c); + if( c >= skill->get_maxcount(skill_id,skill_lv) || c != i) { + clif->skill_fail(sd , skill_id, USESKILL_FAIL_LEVEL, 0); return 0; } } @@ -13311,35 +13296,35 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, status = &sd->battle_status; - require = skill_get_requirement(sd,skill_id,skill_lv); + require = skill->get_requirement(sd,skill_id,skill_lv); if( require.hp > 0 && status->hp <= (unsigned int)require.hp) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_HP_INSUFFICIENT,0); return 0; } if( require.weapon && !pc_check_weapontype(sd,require.weapon) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0); return 0; } if( require.ammo ) { //Skill requires stuff equipped in the arrow slot. if((i=sd->equip_index[EQI_AMMO]) < 0 || !sd->inventory_data[i] ) { - clif_arrow_fail(sd,0); + clif->arrow_fail(sd,0); return 0; } else if( sd->status.inventory[i].amount < require.ammo_qty ) { char e_msg[100]; sprintf(e_msg,"Skill Failed. [%s] requires %dx %s.", - skill_get_desc(skill_id), + skill->get_desc(skill_id), require.ammo_qty, itemdb_jname(sd->status.inventory[i].nameid)); - clif_colormes(sd,COLOR_RED,e_msg); + clif->colormes(sd->fd,COLOR_RED,e_msg); return 0; } if (!(require.ammo&1<<sd->inventory_data[i]->look)) { //Ammo type check. Send the "wrong weapon type" message //which is the closest we have to wrong ammo type. [Skotlex] - clif_arrow_fail(sd,0); //Haplo suggested we just send the equip-arrows message instead. [Skotlex] - //clif_skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0); + clif->arrow_fail(sd,0); //Haplo suggested we just send the equip-arrows message instead. [Skotlex] + //clif->skill_fail(sd,skill_id,USESKILL_FAIL_THIS_WEAPON,0); return 0; } } @@ -13350,11 +13335,11 @@ int skill_check_condition_castend(struct map_session_data* sd, uint16 skill_id, index[i] = pc_search_inventory(sd,require.itemid[i]); if( index[i] < 0 || sd->status.inventory[index[i]].amount < require.amount[i] ) { if( require.itemid[i] == ITEMID_RED_GEMSTONE ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_REDJAMSTONE,0);// red gemstone required + clif->skill_fail(sd,skill_id,USESKILL_FAIL_REDJAMSTONE,0);// red gemstone required else if( require.itemid[i] == ITEMID_BLUE_GEMSTONE ) - clif_skill_fail(sd,skill_id,USESKILL_FAIL_BLUEJAMSTONE,0);// blue gemstone required + clif->skill_fail(sd,skill_id,USESKILL_FAIL_BLUEJAMSTONE,0);// blue gemstone required else - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } } @@ -13370,7 +13355,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin nullpo_ret(sd); - req = skill_get_requirement(sd,skill_id,skill_lv); + req = skill->get_requirement(sd,skill_id,skill_lv); if( type&1 ) { @@ -13385,7 +13370,7 @@ int skill_consume_requirement( struct map_session_data *sd, uint16 skill_id, uin if(req.zeny > 0) { if( skill_id == NJ_ZENYNAGE ) - req.zeny = 0; //Zeny is reduced on skill_attack. + req.zeny = 0; //Zeny is reduced on skill->attack. if( sd->status.zeny < req.zeny ) req.zeny = sd->status.zeny; pc_payzeny(sd,req.zeny,LOG_TYPE_CONSUME,NULL); @@ -13450,25 +13435,28 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if( !sd ) return req; - + /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ +#if 0 + if( sd->state.abra_flag ) +#else if( sd->skillitem == skill_id ) - return req; // Item skills and Hocus-Pocus don't have requirements.[Inkfish] +#endif + return req; // Hocus-Pocus don't have requirements. sc = &sd->sc; if( !sc->count ) sc = NULL; - switch( skill_id ) - { // Turn off check. - case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD: - case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL: - case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN: - case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: case KO_YAMIKUMO: - if( sc && sc->data[status_skill2sc(skill_id)] ) - return req; + switch( skill_id ) { // Turn off check. + case BS_MAXIMIZE: case NV_TRICKDEAD: case TF_HIDING: case AS_CLOAKING: case CR_AUTOGUARD: + case ML_AUTOGUARD: case CR_DEFENDER: case ML_DEFENDER: case ST_CHASEWALK: case PA_GOSPEL: + case CR_SHRINK: case TK_RUN: case GS_GATLINGFEVER: case TK_READYCOUNTER: case TK_READYDOWN: + case TK_READYSTORM: case TK_READYTURN: case SG_FUSION: case KO_YAMIKUMO: + if( sc && sc->data[status_skill2sc(skill_id)] ) + return req; } - idx = skill_get_index(skill_id); + idx = skill->get_index(skill_id); if( idx == 0 ) // invalid skill id return req; if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL ) @@ -13529,8 +13517,8 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 if (req.ammo_qty) req.ammo = skill_db[idx].ammo; - if (!req.ammo && skill_id && skill_isammotype(sd, skill_id)) - { //Assume this skill is using the weapon, therefore it requires arrows. + if (!req.ammo && skill_id && skill->isammotype(sd, skill_id)) { + //Assume this skill is using the weapon, therefore it requires arrows. req.ammo = 0xFFFFFFFF; //Enable use on all ammo types. req.ammo_qty = 1; } @@ -13553,11 +13541,11 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 continue; break; case AB_ADORAMUS: - if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) + if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 2) ) continue; break; case WL_COMET: - if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill_check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) + if( itemid_isgemstone(skill_db[idx].itemid[i]) && skill->check_pc_partner(sd,skill_id,&skill_lv, 1, 0) ) continue; break; case GN_FIRE_EXPANSION: @@ -13709,7 +13697,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16 * Does cast-time reductions based on dex, item bonuses and config setting *------------------------------------------*/ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { - int time = skill_get_cast(skill_id, skill_lv); + int time = skill->get_cast(skill_id, skill_lv); nullpo_ret(bl); #ifndef RENEWAL_CAST @@ -13719,7 +13707,7 @@ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { sd = BL_CAST(BL_PC, bl); // calculate base cast time (reduced by dex) - if( !(skill_get_castnodex(skill_id, skill_lv)&1) ) { + if( !(skill->get_castnodex(skill_id, skill_lv)&1) ) { int scale = battle_config.castrate_dex_scale - status_get_dex(bl); if( scale > 0 ) // not instant cast time = time * scale / battle_config.castrate_dex_scale; @@ -13728,7 +13716,7 @@ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { } // calculate cast time reduced by item/card bonuses - if( !(skill_get_castnodex(skill_id, skill_lv)&4) && sd ) + if( !(skill->get_castnodex(skill_id, skill_lv)&4) && sd ) { int i; if( sd->castrate != 100 ) @@ -13765,6 +13753,9 @@ int skill_castfix_sc (struct block_list *bl, int time) if( time < 0 ) return 0; + if( bl->type == BL_MOB ) // mobs casttime is fixed nothing to alter. + return time; + if (sc && sc->count) { if (sc->data[SC_SLOWCAST]) time += time * sc->data[SC_SLOWCAST]->val2 / 100; @@ -13794,20 +13785,27 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 { struct status_change *sc = status_get_sc(bl); struct map_session_data *sd = BL_CAST(BL_PC,bl); - int fixed = skill_get_fixed_cast(skill_id, skill_lv), fixcast_r = 0, varcast_r = 0, i = 0; + int fixed = skill->get_fixed_cast(skill_id, skill_lv), fixcast_r = 0, varcast_r = 0, i = 0; if( time < 0 ) return 0; + if( bl->type == BL_MOB ) // mobs casttime is fixed nothing to alter. + return (int)time; + if( fixed == 0 ){ fixed = (int)time * 20 / 100; // fixed time time = time * 80 / 100; // variable time }else if( fixed < 0 ) // no fixed cast time fixed = 0; - if(sd && !(skill_get_castnodex(skill_id, skill_lv)&4) ){ // Increases/Decreases fixed/variable cast time of a skill by item/card bonuses. + if(sd && !(skill->get_castnodex(skill_id, skill_lv)&4) ){ // Increases/Decreases fixed/variable cast time of a skill by item/card bonuses. if( sd->bonus.varcastrate < 0 ) VARCAST_REDUCTION(sd->bonus.varcastrate); + if( sd->bonus.add_varcast != 0 ) // bonus bVariableCast + time += sd->bonus.add_varcast; + if( sd->bonus.add_fixcast != 0 ) // bonus bFixedCast + fixed += sd->bonus.add_fixcast; for (i = 0; i < ARRAYLENGTH(sd->skillfixcast) && sd->skillfixcast[i].id; i++) if (sd->skillfixcast[i].id == skill_id){ // bonus2 bSkillFixedCast fixed += sd->skillfixcast[i].val; @@ -13824,9 +13822,15 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 VARCAST_REDUCTION(i); break; } + for( i = 0; i < ARRAYLENGTH(sd->skillfixcastrate) && sd->skillfixcastrate[i].id; i++ ) + + if( sd->skillfixcastrate[i].id == skill_id ){ // bonus2 bFixedCastrate + fixcast_r = sd->skillfixcastrate[i].val; // just speculation + break; + } } - if (sc && sc->count && !(skill_get_castnodex(skill_id, skill_lv)&2) ) { + if (sc && sc->count && !(skill->get_castnodex(skill_id, skill_lv)&2) ) { // All variable cast additive bonuses must come first if (sc->data[SC_SLOWCAST]) VARCAST_REDUCTION(-sc->data[SC_SLOWCAST]->val2); @@ -13845,7 +13849,7 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 VARCAST_REDUCTION(sc->data[SC_POEMBRAGI]->val2); if (sc->data[SC_IZAYOI]) VARCAST_REDUCTION(50); - if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 && (skill_get_ele(skill_id, skill_lv) == ELE_WATER)) + if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 && (skill->get_ele(skill_id, skill_lv) == ELE_WATER)) VARCAST_REDUCTION(30); //Reduces 30% Variable Cast Time of Water spells. // Fixed cast reduction bonuses if( sc->data[SC__LAZINESS] ) @@ -13863,14 +13867,14 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 fixed -= 1000; } - if( sd && !(skill_get_castnodex(skill_id, skill_lv)&4) ){ + if( sd && !(skill->get_castnodex(skill_id, skill_lv)&4) ){ VARCAST_REDUCTION( max(sd->bonus.varcastrate, 0) + max(i, 0) ); fixcast_r = max(fixcast_r, sd->bonus.fixcastrate) + min(sd->bonus.fixcastrate,0); } if( varcast_r < 0 ) // now compute overall factors time = time * (1 - (float)varcast_r / 100); - if( !(skill_get_castnodex(skill_id, skill_lv)&1) )// reduction from status point + if( !(skill->get_castnodex(skill_id, skill_lv)&1) )// reduction from status point time = (1 - sqrt( ((float)(status_get_dex(bl)*2 + status_get_int(bl)) / battle_config.vcast_stat_scale) )) * time; // underflow checking/capping time = max(time, 0) + (1 - (float)min(fixcast_r, 100) / 100) * max(fixed,0); @@ -13882,10 +13886,10 @@ int skill_vfcastfix (struct block_list *bl, double time, uint16 skill_id, uint16 /*========================================== * Does delay reductions based on dex/agi, sc data, item bonuses, ... *------------------------------------------*/ -int skill_delayfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) +int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) { - int delaynodex = skill_get_delaynodex(skill_id, skill_lv); - int time = skill_get_delay(skill_id, skill_lv); + int delaynodex = skill->get_delaynodex(skill_id, skill_lv); + int time = skill->get_delay(skill_id, skill_lv); struct map_session_data *sd; struct status_change *sc = status_get_sc(bl); @@ -13903,40 +13907,39 @@ int skill_delayfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) // Delay reductions switch (skill_id) { //Monk combo skills have their delay reduced by agi/dex. - case MO_TRIPLEATTACK: - case MO_CHAINCOMBO: - case MO_COMBOFINISH: - case CH_TIGERFIST: - case CH_CHAINCRUSH: - case SR_DRAGONCOMBO: - case SR_FALLENEMPIRE: - time -= 4*status_get_agi(bl) - 2*status_get_dex(bl); - break; - case HP_BASILICA: - if( sc && !sc->data[SC_BASILICA] ) - time = 0; // There is no Delay on Basilica creation, only on cancel - break; - default: - if (battle_config.delay_dependon_dex && !(delaynodex&1)) - { // if skill delay is allowed to be reduced by dex - int scale = battle_config.castrate_dex_scale - status_get_dex(bl); - if (scale > 0) - time = time * scale / battle_config.castrate_dex_scale; - else //To be capped later to minimum. - time = 0; - } - if (battle_config.delay_dependon_agi && !(delaynodex&1)) - { // if skill delay is allowed to be reduced by agi - int scale = battle_config.castrate_dex_scale - status_get_agi(bl); - if (scale > 0) - time = time * scale / battle_config.castrate_dex_scale; - else //To be capped later to minimum. - time = 0; - } + case MO_TRIPLEATTACK: + case MO_CHAINCOMBO: + case MO_COMBOFINISH: + case CH_TIGERFIST: + case CH_CHAINCRUSH: + case SR_DRAGONCOMBO: + case SR_FALLENEMPIRE: + time -= 4*status_get_agi(bl) - 2*status_get_dex(bl); + break; + case HP_BASILICA: + if( sc && !sc->data[SC_BASILICA] ) + time = 0; // There is no Delay on Basilica creation, only on cancel + break; + default: + if (battle_config.delay_dependon_dex && !(delaynodex&1)) + { // if skill delay is allowed to be reduced by dex + int scale = battle_config.castrate_dex_scale - status_get_dex(bl); + if (scale > 0) + time = time * scale / battle_config.castrate_dex_scale; + else //To be capped later to minimum. + time = 0; + } + if (battle_config.delay_dependon_agi && !(delaynodex&1)) + { // if skill delay is allowed to be reduced by agi + int scale = battle_config.castrate_dex_scale - status_get_agi(bl); + if (scale > 0) + time = time * scale / battle_config.castrate_dex_scale; + else //To be capped later to minimum. + time = 0; + } } - if ( sc && sc->data[SC_SPIRIT] ) - { + if ( sc && sc->data[SC_SPIRIT] ) { switch (skill_id) { case CR_SHIELDBOOMERANG: if (sc->data[SC_SPIRIT]->val2 == SL_CRUSADER) @@ -13954,7 +13957,7 @@ int skill_delayfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) if (sc && sc->count) { if (sc->data[SC_POEMBRAGI]) time -= time * sc->data[SC_POEMBRAGI]->val3 / 100; - if (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3 && (skill_get_ele(skill_id, skill_lv) == ELE_WIND)) + if (sc->data[SC_WIND_INSIGNIA] && sc->data[SC_WIND_INSIGNIA]->val1 == 3 && (skill->get_ele(skill_id, skill_lv) == ELE_WIND)) time /= 2; // After Delay of Wind element spells reduced by 50%. } @@ -13982,8 +13985,7 @@ struct square { int val2[5]; }; -static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y) -{ +void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, int16 y) { nullpo_retv(tc); if(dir == 0){ @@ -13997,8 +13999,7 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in tc->val2[2]= tc->val2[3]= tc->val2[4]=y-1; - } - else if(dir==2){ + } else if(dir==2){ tc->val1[0]= tc->val1[1]= tc->val1[2]= @@ -14009,8 +14010,7 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in tc->val2[2]=y; tc->val2[3]=y-1; tc->val2[4]=y-2; - } - else if(dir==4){ + } else if(dir==4){ tc->val1[0]=x-2; tc->val1[1]=x-1; tc->val1[2]=x; @@ -14021,8 +14021,7 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in tc->val2[2]= tc->val2[3]= tc->val2[4]=y+1; - } - else if(dir==6){ + } else if(dir==6){ tc->val1[0]= tc->val1[1]= tc->val1[2]= @@ -14033,8 +14032,7 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in tc->val2[2]=y; tc->val2[3]=y-1; tc->val2[4]=y-2; - } - else if(dir==1){ + } else if(dir==1){ tc->val1[0]=x-1; tc->val1[1]=x; tc->val1[2]=x+1; @@ -14045,8 +14043,7 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in tc->val2[2]=y-1; tc->val2[3]=y; tc->val2[4]=y+1; - } - else if(dir==3){ + } else if(dir==3){ tc->val1[0]=x+3; tc->val1[1]=x+2; tc->val1[2]=x+1; @@ -14057,8 +14054,7 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in tc->val2[2]=y+1; tc->val2[3]=y+2; tc->val2[4]=y+3; - } - else if(dir==5){ + } else if(dir==5){ tc->val1[0]=x+1; tc->val1[1]=x; tc->val1[2]=x-1; @@ -14069,8 +14065,7 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in tc->val2[2]=y+1; tc->val2[3]=y; tc->val2[4]=y-1; - } - else if(dir==7){ + } else if(dir==7){ tc->val1[0]=x-3; tc->val1[1]=x-2; tc->val1[2]=x-1; @@ -14085,15 +14080,12 @@ static void skill_brandishspear_first (struct square *tc, uint8 dir, int16 x, in } -static void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) -{ +void skill_brandishspear_dir (struct square* tc, uint8 dir, int are) { int c; nullpo_retv(tc); - for( c = 0; c < 5; c++ ) - { - switch( dir ) - { + for( c = 0; c < 5; c++ ) { + switch( dir ) { case 0: tc->val2[c]+=are; break; case 1: tc->val1[c]-=are; tc->val2[c]+=are; break; case 2: tc->val1[c]-=are; break; @@ -14112,32 +14104,32 @@ void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 s uint8 dir = map_calc_dir(src,bl->x,bl->y); struct square tc; int x=bl->x,y=bl->y; - skill_brandishspear_first(&tc,dir,x,y); - skill_brandishspear_dir(&tc,dir,4); + skill->brandishspear_first(&tc,dir,x,y); + skill->brandishspear_dir(&tc,dir,4); skill_area_temp[1] = bl->id; if(skill_lv > 9){ for(c=1;c<4;c++){ - map_foreachincell(skill_area_sub, + map_foreachincell(skill->area_sub, bl->m,tc.val1[c],tc.val2[c],BL_CHAR, src,skill_id,skill_lv,tick, flag|BCT_ENEMY|n, - skill_castend_damage_id); + skill->castend_damage_id); } } if(skill_lv > 6){ - skill_brandishspear_dir(&tc,dir,-1); + skill->brandishspear_dir(&tc,dir,-1); n--; - }else{ - skill_brandishspear_dir(&tc,dir,-2); + } else { + skill->brandishspear_dir(&tc,dir,-2); n-=2; } if(skill_lv > 3){ for(c=0;c<5;c++){ - map_foreachincell(skill_area_sub, + map_foreachincell(skill->area_sub, bl->m,tc.val1[c],tc.val2[c],BL_CHAR, src,skill_id,skill_lv,tick, flag|BCT_ENEMY|n, - skill_castend_damage_id); + skill->castend_damage_id); if(skill_lv > 6 && n==3 && c==4){ skill_brandishspear_dir(&tc,dir,-1); n--;c=-1; @@ -14145,11 +14137,11 @@ void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 s } } for(c=0;c<10;c++){ - if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1); - map_foreachincell(skill_area_sub, + if(c==0||c==5) skill->brandishspear_dir(&tc,dir,-1); + map_foreachincell(skill->area_sub, bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR, src,skill_id,skill_lv,tick, flag|BCT_ENEMY|1, - skill_castend_damage_id); + skill->castend_damage_id); } } @@ -14176,8 +14168,8 @@ void skill_repairweapon (struct map_session_data *sd, int idx) { if( item->nameid <= 0 || item->attribute == 0 ) return; //Again invalid item.... - if( sd != target_sd && !battle_check_range(&sd->bl,&target_sd->bl, skill_get_range2(&sd->bl, sd->menuskill_id,sd->menuskill_val2) ) ){ - clif_item_repaireffect(sd,idx,1); + if( sd != target_sd && !battle->check_range(&sd->bl,&target_sd->bl, skill->get_range2(&sd->bl, sd->menuskill_id,sd->menuskill_val2) ) ){ + clif->item_repaireffect(sd,idx,1); return; } @@ -14186,22 +14178,22 @@ void skill_repairweapon (struct map_session_data *sd, int idx) { else material = materials [2]; // Armors consume 1 Steel if ( pc_search_inventory(sd,material) < 0 ) { - clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); return; } - clif_skill_nodamage(&sd->bl,&target_sd->bl,sd->menuskill_id,1,1); + clif->skill_nodamage(&sd->bl,&target_sd->bl,sd->menuskill_id,1,1); item->attribute = 0;/* clear broken state */ - clif_equiplist(target_sd); + clif->equiplist(target_sd); pc_delitem(sd,pc_search_inventory(sd,material),1,0,0,LOG_TYPE_CONSUME); - clif_item_repaireffect(sd,idx,0); + clif->item_repaireffect(sd,idx,0); if( sd != target_sd ) - clif_item_repaireffect(target_sd,idx,0); + clif->item_repaireffect(target_sd,idx,0); } /*========================================== @@ -14219,7 +14211,7 @@ void skill_identify (struct map_session_data *sd, int idx) sd->status.inventory[idx].identify=1; } } - clif_item_identified(sd,idx,flag); + clif->item_identified(sd,idx,flag); } /*========================================== @@ -14244,7 +14236,7 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) || ditem->flag.no_refine // if the item isn't refinable || (i = pc_search_inventory(sd, material [ditem->wlv])) < 0 ) { - clif_skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0); return; } @@ -14253,19 +14245,19 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) pc_delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER); if (per > rnd() % 100) { - log_pick_pc(sd, LOG_TYPE_OTHER, -1, item); + logs->pick_pc(sd, LOG_TYPE_OTHER, -1, item, ditem); item->refine++; - log_pick_pc(sd, LOG_TYPE_OTHER, 1, item); + logs->pick_pc(sd, LOG_TYPE_OTHER, 1, item, ditem); if(item->equip) { ep = item->equip; pc_unequipitem(sd,idx,3); } - clif_refine(sd->fd,0,idx,item->refine); - clif_delitem(sd,idx,1,3); - clif_additem(sd,idx,1,0); + clif->refine(sd->fd,0,idx,item->refine); + clif->delitem(sd,idx,1,3); + clif->additem(sd,idx,1,0); if (ep) pc_equipitem(sd,idx,ep); - clif_misceffect(&sd->bl,3); + clif->misceffect(&sd->bl,3); if(item->refine == 10 && item->card[0] == CARD0_FORGE && (int)MakeDWord(item->card[2],item->card[3]) == sd->status.char_id) @@ -14286,10 +14278,10 @@ void skill_weaponrefine (struct map_session_data *sd, int idx) item->refine = 0; if(item->equip) pc_unequipitem(sd,idx,3); - clif_refine(sd->fd,1,idx,item->refine); + clif->refine(sd->fd,1,idx,item->refine); pc_delitem(sd,idx,1,0,2, LOG_TYPE_OTHER); - clif_misceffect(&sd->bl,2); - clif_emotion(&sd->bl, E_OMG); + clif->misceffect(&sd->bl,2); + clif->emotion(&sd->bl, E_OMG); } } } @@ -14334,15 +14326,14 @@ int skill_autospell (struct map_session_data *sd, uint16 skill_id) maxlv = lv; sc_start4(&sd->bl,SC_AUTOSPELL,100,skill_lv,skill_id,maxlv,0, - skill_get_time(SA_AUTOSPELL,skill_lv)); + skill->get_time(SA_AUTOSPELL,skill_lv)); return 0; } /*========================================== * Sitting skills functions. *------------------------------------------*/ -static int skill_sit_count (struct block_list *bl, va_list ap) -{ +int skill_sit_count (struct block_list *bl, va_list ap) { struct map_session_data *sd; int type =va_arg(ap,int); sd=(struct map_session_data*)bl; @@ -14359,8 +14350,7 @@ static int skill_sit_count (struct block_list *bl, va_list ap) return 0; } -static int skill_sit_in (struct block_list *bl, va_list ap) -{ +int skill_sit_in (struct block_list *bl, va_list ap) { struct map_session_data *sd; int type =va_arg(ap,int); @@ -14372,8 +14362,7 @@ static int skill_sit_in (struct block_list *bl, va_list ap) if(type&1 && pc_checkskill(sd,RG_GANGSTER) > 0) sd->state.gangsterparadise=1; - if(type&2 && (pc_checkskill(sd,TK_HPTIME) > 0 || pc_checkskill(sd,TK_SPTIME) > 0 )) - { + if(type&2 && (pc_checkskill(sd,TK_HPTIME) > 0 || pc_checkskill(sd,TK_SPTIME) > 0 )) { sd->state.rest=1; status_calc_regen(bl, &sd->battle_status, &sd->regen); status_calc_regen_rate(bl, &sd->regen, &sd->sc); @@ -14382,8 +14371,7 @@ static int skill_sit_in (struct block_list *bl, va_list ap) return 0; } -static int skill_sit_out (struct block_list *bl, va_list ap) -{ +int skill_sit_out (struct block_list *bl, va_list ap) { struct map_session_data *sd; int type =va_arg(ap,int); sd=(struct map_session_data*)bl; @@ -14406,31 +14394,31 @@ int skill_sit (struct map_session_data *sd, int type) if((lv = pc_checkskill(sd,RG_GANGSTER)) > 0) { flag|=1; - range = skill_get_splash(RG_GANGSTER, lv); + range = skill->get_splash(RG_GANGSTER, lv); } if((lv = pc_checkskill(sd,TK_HPTIME)) > 0) { flag|=2; - range = skill_get_splash(TK_HPTIME, lv); + range = skill->get_splash(TK_HPTIME, lv); } else if ((lv = pc_checkskill(sd,TK_SPTIME)) > 0) { flag|=2; - range = skill_get_splash(TK_SPTIME, lv); + range = skill->get_splash(TK_SPTIME, lv); } if( type ) { - clif_status_load(&sd->bl,SI_SIT,1); + clif->sc_load(&sd->bl,sd->bl.id,SELF,SI_SIT,0,0,0); } else { - clif_status_load(&sd->bl,SI_SIT,0); + clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT); } if (!flag) return 0; if(type) { - if (map_foreachinrange(skill_sit_count,&sd->bl, range, BL_PC, flag) > 1) - map_foreachinrange(skill_sit_in,&sd->bl, range, BL_PC, flag); + if (map_foreachinrange(skill->sit_count,&sd->bl, range, BL_PC, flag) > 1) + map_foreachinrange(skill->sit_in,&sd->bl, range, BL_PC, flag); } else { - if (map_foreachinrange(skill_sit_count,&sd->bl, range, BL_PC, flag) < 2) - map_foreachinrange(skill_sit_out,&sd->bl, range, BL_PC, flag); + if (map_foreachinrange(skill->sit_count,&sd->bl, range, BL_PC, flag) < 2) + map_foreachinrange(skill->sit_out,&sd->bl, range, BL_PC, flag); } return 0; } @@ -14438,8 +14426,7 @@ int skill_sit (struct map_session_data *sd, int type) /*========================================== * *------------------------------------------*/ -int skill_frostjoke_scream (struct block_list *bl, va_list ap) -{ +int skill_frostjoke_scream (struct block_list *bl, va_list ap) { struct block_list *src; uint16 skill_id,skill_lv; unsigned int tick; @@ -14460,10 +14447,10 @@ int skill_frostjoke_scream (struct block_list *bl, va_list ap) return 0;//Frost Joke / Scream cannot target invisible or MADO Gear characters [Ind] } //It has been reported that Scream/Joke works the same regardless of woe-setting. [Skotlex] - if(battle_check_target(src,bl,BCT_ENEMY) > 0) - skill_additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); - else if(battle_check_target(src,bl,BCT_PARTY) > 0 && rnd()%100 < 10) - skill_additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); + if(battle->check_target(src,bl,BCT_ENEMY) > 0) + skill->additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); + else if(battle->check_target(src,bl,BCT_PARTY) > 0 && rnd()%100 < 10) + skill->additional_effect(src,bl,skill_id,skill_lv,BF_MISC,ATK_DEF,tick); return 0; } @@ -14471,9 +14458,8 @@ int skill_frostjoke_scream (struct block_list *bl, va_list ap) /*========================================== * *------------------------------------------*/ -static void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag) -{ - int range = skill_get_unit_range(skill_id,skill_lv); +void skill_unitsetmapcell (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag) { + int range = skill->get_unit_range(skill_id,skill_lv); int x,y; for( y = src->bl.y - range; y <= src->bl.y + range; ++y ) @@ -14504,24 +14490,24 @@ int skill_attack_area (struct block_list *bl, va_list ap) if (skill_area_temp[1] == bl->id) //This is the target of the skill, do a full attack and skip target checks. - return skill_attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag); + return skill->attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag); - if(battle_check_target(dsrc,bl,type) <= 0 || + if(battle->check_target(dsrc,bl,type) <= 0 || !status_check_skilluse(NULL, bl, skill_id, 2)) return 0; switch (skill_id) { - case WZ_FROSTNOVA: //Skills that don't require the animation to be removed - case NPC_ACIDBREATH: - case NPC_DARKNESSBREATH: - case NPC_FIREBREATH: - case NPC_ICEBREATH: - case NPC_THUNDERBREATH: - return skill_attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag); - default: - //Area-splash, disable skill animation. - return skill_attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); + case WZ_FROSTNOVA: //Skills that don't require the animation to be removed + case NPC_ACIDBREATH: + case NPC_DARKNESSBREATH: + case NPC_FIREBREATH: + case NPC_ICEBREATH: + case NPC_THUNDERBREATH: + return skill->attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag); + default: + //Area-splash, disable skill animation. + return skill->attack(atk_type,src,dsrc,bl,skill_id,skill_lv,tick,flag|SD_ANIMATION); } } /*========================================== @@ -14537,8 +14523,7 @@ int skill_clear_group (struct block_list *bl, int flag) if (!ud) return 0; //All groups to be deleted are first stored on an array since the array elements shift around when you delete them. [Skotlex] - for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) - { + for (i=0;i<MAX_SKILLUNITGROUP && ud->skillunit[i];i++) { switch (ud->skillunit[i]->skill_id) { case SA_DELUGE: case SA_VOLCANO: @@ -14558,22 +14543,21 @@ int skill_clear_group (struct block_list *bl, int flag) group[count++] = ud->skillunit[i]; break; default: - if (flag&2 && skill_get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP) + if (flag&2 && skill->get_inf2(ud->skillunit[i]->skill_id)&INF2_TRAP) group[count++]= ud->skillunit[i]; break; } } for (i=0;i<count;i++) - skill_delunitgroup(group[i]); + skill->del_unitgroup(group[i],ALC_MARK); return count; } /*========================================== * Returns the first element field found [Skotlex] *------------------------------------------*/ -struct skill_unit_group *skill_locate_element_field(struct block_list *bl) -{ +struct skill_unit_group *skill_locate_element_field(struct block_list *bl) { struct unit_data *ud = unit_bl2ud(bl); int i; nullpo_ret(bl); @@ -14595,8 +14579,7 @@ struct skill_unit_group *skill_locate_element_field(struct block_list *bl) } // for graffiti cleaner [Valaris] -int skill_graffitiremover (struct block_list *bl, va_list ap) -{ +int skill_graffitiremover (struct block_list *bl, va_list ap) { struct skill_unit *unit=NULL; nullpo_ret(bl); @@ -14606,13 +14589,12 @@ int skill_graffitiremover (struct block_list *bl, va_list ap) return 0; if((unit->group) && (unit->group->unit_id == UNT_GRAFFITI)) - skill_delunit(unit); + skill->delunit(unit); return 0; } -int skill_greed (struct block_list *bl, va_list ap) -{ +int skill_greed (struct block_list *bl, va_list ap) { struct block_list *src; struct map_session_data *sd=NULL; struct flooritem_data *fitem=NULL; @@ -14651,15 +14633,13 @@ int skill_detonator(struct block_list *bl, va_list ap) case UNT_CLUSTERBOMB: case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: - if( unit_id == UNT_TALKIEBOX ) - { - clif_talkiebox(bl,unit->group->valstr); + if( unit_id == UNT_TALKIEBOX ) { + clif->talkiebox(bl,unit->group->valstr); unit->group->val2 = -1; - } - else - map_foreachinrange(skill_trap_splash,bl,skill_get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick); + } else + map_foreachinrange(skill->trap_splash,bl,skill->get_splash(unit->group->skill_id,unit->group->skill_lv),unit->group->bl_flag,bl,unit->group->tick); - clif_changetraplook(bl,unit_id == UNT_FIRINGTRAP ? UNT_DUMMYSKILL : UNT_USED_TRAPS); + clif->changetraplook(bl,unit_id == UNT_FIRINGTRAP ? UNT_DUMMYSKILL : UNT_USED_TRAPS); unit->group->unit_id = UNT_USED_TRAPS; unit->group->limit = DIFF_TICK(gettick(),unit->group->tick) + (unit_id == UNT_TALKIEBOX ? 5000 : (unit_id == UNT_CLUSTERBOMB || unit_id == UNT_ICEBOUNDTRAP? 2500 : 1500) ); @@ -14671,8 +14651,7 @@ int skill_detonator(struct block_list *bl, va_list ap) /*========================================== * *------------------------------------------*/ -static int skill_cell_overlap(struct block_list *bl, va_list ap) -{ +int skill_cell_overlap(struct block_list *bl, va_list ap) { uint16 skill_id; int *alive; struct skill_unit *unit; @@ -14688,18 +14667,18 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap) case SA_LANDPROTECTOR: if( unit->group->skill_id == SA_LANDPROTECTOR ) {//Check for offensive Land Protector to delete both. [Skotlex] (*alive) = 0; - skill_delunit(unit); + skill->delunit(unit); return 1; } - if( !(skill_get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) ) { //It deletes everything except songs/dances and traps - skill_delunit(unit); + if( !(skill->get_inf2(unit->group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP)) || unit->group->skill_id == WZ_FIREPILLAR ) { //It deletes everything except songs/dances and traps + skill->delunit(unit); return 1; } break; case HW_GANBANTEIN: case LG_EARTHDRIVE: if( !(unit->group->state.song_dance&0x1) ) {// Don't touch song/dance. - skill_delunit(unit); + skill->delunit(unit); return 1; } break; @@ -14759,13 +14738,13 @@ static int skill_cell_overlap(struct block_list *bl, va_list ap) case UNT_VIOLENTGALE: case UNT_SAFETYWALL: case UNT_PNEUMA: - skill_delunit(unit); + skill->delunit(unit); return 1; } break; } - if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill_get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_TRAP))) { //It deletes everything except songs/dances/traps + if (unit->group->skill_id == SA_LANDPROTECTOR && !(skill->get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_TRAP))) { //It deletes everything except songs/dances/traps (*alive) = 0; return 1; } @@ -14797,8 +14776,7 @@ int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap) /*========================================== * *------------------------------------------*/ -static int skill_trap_splash (struct block_list *bl, va_list ap) -{ +int skill_trap_splash (struct block_list *bl, va_list ap) { struct block_list *src; int tick; struct skill_unit *unit; @@ -14814,57 +14792,57 @@ static int skill_trap_splash (struct block_list *bl, va_list ap) nullpo_ret(sg = unit->group); nullpo_ret(ss = map_id2bl(sg->src_id)); - if(battle_check_target(src,bl,sg->target_flag) <= 0) + if(battle->check_target(src,bl,sg->target_flag) <= 0) return 0; switch(sg->unit_id){ case UNT_SHOCKWAVE: case UNT_SANDMAN: case UNT_FLASHER: - skill_additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,ATK_DEF,tick); + skill->additional_effect(ss,bl,sg->skill_id,sg->skill_lv,BF_MISC,ATK_DEF,tick); break; case UNT_GROUNDDRIFT_WIND: - if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_STUN,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_STUN,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_DARK: - if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_BLIND,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_BLIND,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_POISON: - if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_POISON,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_POISON,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_WATER: - if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - sc_start(bl,SC_FREEZE,5,sg->skill_lv,skill_get_time2(sg->skill_id, sg->skill_lv)); + if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + sc_start(bl,SC_FREEZE,5,sg->skill_lv,skill->get_time2(sg->skill_id, sg->skill_lv)); break; case UNT_GROUNDDRIFT_FIRE: - if(skill_attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) - skill_blown(src,bl,skill_get_blewcount(sg->skill_id,sg->skill_lv),-1,0); + if(skill->attack(BF_WEAPON,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1)) + skill->blown(src,bl,skill->get_blewcount(sg->skill_id,sg->skill_lv),-1,0); break; case UNT_ELECTRICSHOCKER: - clif_skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5); + clif->skill_damage(src,bl,tick,0,0,-30000,1,sg->skill_id,sg->skill_lv,5); break; case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: case UNT_CLUSTERBOMB: if( ss != bl ) - skill_attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1|SD_LEVEL); + skill->attack(BF_MISC,ss,src,bl,sg->skill_id,sg->skill_lv,tick,sg->val1|SD_LEVEL); break; case UNT_MAGENTATRAP: case UNT_COBALTTRAP: case UNT_MAIZETRAP: case UNT_VERDURETRAP: if( bl->type != BL_PC && !is_boss(bl) ) - sc_start2(bl,SC_ELEMENTALCHANGE,100,sg->skill_lv,skill_get_ele(sg->skill_id,sg->skill_lv),skill_get_time2(sg->skill_id,sg->skill_lv)); + sc_start2(bl,SC_ELEMENTALCHANGE,100,sg->skill_lv,skill->get_ele(sg->skill_id,sg->skill_lv),skill->get_time2(sg->skill_id,sg->skill_lv)); break; case UNT_REVERBERATION: - skill_addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse - skill_addtimerskill(ss,tick+250,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,0); + skill->addtimerskill(ss,tick+50,bl->id,0,0,WM_REVERBERATION_MELEE,sg->skill_lv,BF_WEAPON,0); // for proper skill delay animation when use with Dominion Impulse + skill->addtimerskill(ss,tick+250,bl->id,0,0,WM_REVERBERATION_MAGIC,sg->skill_lv,BF_MAGIC,0); break; default: - skill_attack(skill_get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0); + skill->attack(skill->get_type(sg->skill_id),ss,src,bl,sg->skill_id,sg->skill_lv,tick,0); break; } return 1; @@ -14905,23 +14883,16 @@ bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce wall = false; } - if( sce ) - { - if( !wall ) - { + if( sce ) { + if( !wall ) { if( sce->val1 < 3 ) //End cloaking. status_change_end(bl, SC_CLOAKING, INVALID_TIMER); - else - if( sce->val4&1 ) - { //Remove wall bonus + else if( sce->val4&1 ) { //Remove wall bonus sce->val4&=~1; status_calc_bl(bl,SCB_SPEED); } - } - else - { - if( !(sce->val4&1) ) - { //Add wall speed bonus + } else { + if( !(sce->val4&1) ) { //Add wall speed bonus sce->val4|=1; status_calc_bl(bl,SCB_SPEED); } @@ -14936,23 +14907,18 @@ bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *s static int dy[] = {-1, 0, 1, 0, -1, -1, 1, 1}; bool wall = true; - if( bl->type == BL_PC ) - { //Check for walls. + if( bl->type == BL_PC ) { //Check for walls. int i; ARR_FIND( 0, 8, i, map_getcell(bl->m, bl->x+dx[i], bl->y+dy[i], CELL_CHKNOPASS) != 0 ); if( i == 8 ) wall = false; } - if( sce ) - { - if( !wall ) - { + if( sce ) { + if( !wall ) { if( sce->val1 < 3 ) //End camouflage. status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); - else - if( sce->val3&1 ) - { //Remove wall bonus + else if( sce->val3&1 ) { //Remove wall bonus sce->val3&=~1; status_calc_bl(bl,SCB_SPEED); } @@ -14994,26 +14960,26 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int switch (group->skill_id) { case WZ_ICEWALL: map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,5); - clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,5,AREA); - skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true); + clif->changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,5,AREA); + skill->unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true); map[unit->bl.m].icewall_num++; break; case SA_LANDPROTECTOR: - skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true); + skill->unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true); break; case HP_BASILICA: - skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,true); + skill->unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,true); break; case SC_MAELSTROM: - skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,true); + skill->unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,true); break; default: if (group->state.song_dance&0x1) //Check for dissonance. - skill_dance_overlap(unit, 1); + skill->dance_overlap(unit, 1); break; } - clif_skill_setunit(unit); + clif->skill_setunit(unit); return unit; } @@ -15021,8 +14987,7 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int /*========================================== * *------------------------------------------*/ -int skill_delunit (struct skill_unit* unit) -{ +int skill_delunit (struct skill_unit* unit) { struct skill_unit_group *group; nullpo_ret(unit); @@ -15033,11 +14998,11 @@ int skill_delunit (struct skill_unit* unit) nullpo_ret(group=unit->group); if( group->state.song_dance&0x1 ) //Cancel dissonance effect. - skill_dance_overlap(unit, 0); + skill->dance_overlap(unit, 0); // invoke onout event if( !unit->range ) - map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),4); + map_foreachincell(skill->unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),4); // perform ondelete actions switch (group->skill_id) { @@ -15049,15 +15014,15 @@ int skill_delunit (struct skill_unit* unit) break; case WZ_ICEWALL: map_setgatcell(unit->bl.m,unit->bl.x,unit->bl.y,unit->val2); - clif_changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug - skill_unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); + clif->changemapcell(0,unit->bl.m,unit->bl.x,unit->bl.y,unit->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug + skill->unitsetmapcell(unit,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false); map[unit->bl.m].icewall_num--; break; case SA_LANDPROTECTOR: - skill_unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false); + skill->unitsetmapcell(unit,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,false); break; case HP_BASILICA: - skill_unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false); + skill->unitsetmapcell(unit,HP_BASILICA,group->skill_lv,CELL_BASILICA,false); break; case RA_ELECTRICSHOCKER: { struct block_list* target = map_id2bl(group->val2); @@ -15066,7 +15031,7 @@ int skill_delunit (struct skill_unit* unit) } break; case SC_MAELSTROM: - skill_unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false); + skill->unitsetmapcell(unit,SC_MAELSTROM,group->skill_lv,CELL_MAELSTROM,false); break; case SC_MANHOLE: // Note : Removing the unit don't remove the status (official info) if( group->val2 ) { // Someone Traped @@ -15077,14 +15042,14 @@ int skill_delunit (struct skill_unit* unit) break; } - clif_skill_delunit(unit); + clif->skill_delunit(unit); unit->group=NULL; map_delblock(&unit->bl); // don't free yet map_deliddb(&unit->bl); idb_remove(skillunit_db, unit->bl.id); if(--group->alive_count==0) - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); return 0; } @@ -15106,7 +15071,7 @@ static int skill_unit_group_newid = MAX_SKILL_DB; /// Fatal error if nothing is available. static int skill_get_new_group_id(void) { - if( skill_unit_group_newid >= MAX_SKILL_DB && skill_id2group(skill_unit_group_newid) == NULL ) + if( skill_unit_group_newid >= MAX_SKILL_DB && skill->id2group(skill_unit_group_newid) == NULL ) return skill_unit_group_newid++;// available {// find next id int base_id = skill_unit_group_newid; @@ -15114,7 +15079,7 @@ static int skill_get_new_group_id(void) { if( skill_unit_group_newid < MAX_SKILL_DB ) skill_unit_group_newid = MAX_SKILL_DB; - if( skill_id2group(skill_unit_group_newid) == NULL ) + if( skill->id2group(skill_unit_group_newid) == NULL ) return skill_unit_group_newid++;// available } // full loop, nothing available @@ -15136,8 +15101,7 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, // find a free spot to store the new unit group ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == NULL ); - if(i == MAX_SKILLUNITGROUP) - { + if(i == MAX_SKILLUNITGROUP) { // array is full, make room by discarding oldest group int j=0; unsigned maxdiff=0,x,tick=gettick(); @@ -15146,7 +15110,7 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, maxdiff=x; j=i; } - skill_delunitgroup(ud->skillunit[j]); + skill->del_unitgroup(ud->skillunit[j],ALC_MARK); //Since elements must have shifted, we use the last slot. i = MAX_SKILLUNITGROUP-1; } @@ -15184,7 +15148,7 @@ struct skill_unit_group* skill_initunitgroup (struct block_list* src, int count, /*========================================== * *------------------------------------------*/ -int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func) +int skill_delunitgroup(struct skill_unit_group *group, const char* file, int line, const char* func) { struct block_list* src; struct unit_data *ud; @@ -15215,12 +15179,12 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li case DC_DONTFORGETME: case DC_FORTUNEKISS: case DC_SERVICEFORYOU: - skill_usave_add(((TBL_PC*)src), group->skill_id, group->skill_lv); + skill->usave_add(((TBL_PC*)src), group->skill_id, group->skill_lv); break; } } - if (skill_get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) + if (skill->get_unit_flag(group->skill_id)&(UF_DANCE|UF_SONG|UF_ENSEMBLE)) { struct status_change* sc = status_get_sc(src); if (sc && sc->data[SC_DANCING]) @@ -15282,18 +15246,17 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li } if (src->type==BL_PC && group->state.ammo_consume) - battle_consume_ammo((TBL_PC*)src, group->skill_id, group->skill_lv); + battle->consume_ammo((TBL_PC*)src, group->skill_id, group->skill_lv); group->alive_count=0; // remove all unit cells if(group->unit != NULL) for( i = 0; i < group->unit_count; i++ ) - skill_delunit(&group->unit[i]); + skill->delunit(&group->unit[i]); // clear Talkie-box string - if( group->valstr != NULL ) - { + if( group->valstr != NULL ) { aFree(group->valstr); group->valstr = NULL; } @@ -15307,13 +15270,11 @@ int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int li // locate this group, swap with the last entry and delete it ARR_FIND( 0, MAX_SKILLUNITGROUP, i, ud->skillunit[i] == group ); ARR_FIND( i, MAX_SKILLUNITGROUP, j, ud->skillunit[j] == NULL ); j--; - if( i < MAX_SKILLUNITGROUP ) - { + if( i < MAX_SKILLUNITGROUP ) { ud->skillunit[i] = ud->skillunit[j]; ud->skillunit[j] = NULL; ers_free(skill_unit_ers, group); - } - else + } else ShowError("skill_delunitgroup: Group not found! (src_id: %d skill_id: %d)\n", group->src_id, group->skill_id); return 1; @@ -15329,7 +15290,7 @@ int skill_clear_unitgroup (struct block_list *src) nullpo_ret(ud); while (ud->skillunit[0]) - skill_delunitgroup(ud->skillunit[0]); + skill->del_unitgroup(ud->skillunit[0],ALC_MARK); return 1; } @@ -15337,8 +15298,7 @@ int skill_clear_unitgroup (struct block_list *src) /*========================================== * *------------------------------------------*/ -struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_list *bl, struct skill_unit_group *group, int tick) -{ +struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_list *bl, struct skill_unit_group *group, int tick) { int i,j=-1,k,s,id; struct unit_data *ud; struct skill_unit_group_tickset *set; @@ -15352,7 +15312,7 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_lis set = ud->skillunittick; - if (skill_get_unit_flag(group->skill_id)&UF_NOOVERLAP) + if (skill->get_unit_flag(group->skill_id)&UF_NOOVERLAP) id = s = group->skill_id; else id = s = group->group_id; @@ -15378,8 +15338,7 @@ struct skill_unit_group_tickset *skill_unitgrouptickset_search (struct block_lis /*========================================== * *------------------------------------------*/ -int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) -{ +int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) { struct skill_unit* unit = va_arg(ap,struct skill_unit *); struct skill_unit_group* group = unit->group; unsigned int tick = va_arg(ap,unsigned int); @@ -15389,13 +15348,13 @@ int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) nullpo_ret(group); - if( !(skill_get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) ) + if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map_getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) ) return 0; //AoE skills are ineffective. [Skotlex] - if( battle_check_target(&unit->bl,bl,group->target_flag) <= 0 ) + if( battle->check_target(&unit->bl,bl,group->target_flag) <= 0 ) return 0; - skill_unit_onplace_timer(unit,bl,tick); + skill->unit_onplace_timer(unit,bl,tick); return 1; } @@ -15403,9 +15362,8 @@ int skill_unit_timer_sub_onplace (struct block_list* bl, va_list ap) /** * @see DBApply */ -static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) -{ - struct skill_unit* unit = db_data2ptr(data); +int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) { + struct skill_unit* unit = DB->data2ptr(data); struct skill_unit_group* group = unit->group; unsigned int tick = va_arg(ap,unsigned int); bool dissonance; @@ -15431,7 +15389,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) case UNT_GROUNDDRIFT_WATER: case UNT_GROUNDDRIFT_FIRE: group->unit_id = UNT_USED_TRAPS; - //clif_changetraplook(bl, UNT_FIREPILLAR_ACTIVE); + //clif->changetraplook(bl, UNT_FIREPILLAR_ACTIVE); group->limit=DIFF_TICK(tick+1500,group->tick); unit->limit=DIFF_TICK(tick+1500,group->tick); break; @@ -15440,7 +15398,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) case UNT_ELECTRICSHOCKER: if( group->val2 > 0 ) { // Used Trap don't returns back to item - skill_delunit(unit); + skill->delunit(unit); break; } case UNT_SKIDTRAP: @@ -15471,19 +15429,19 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) item_tmp.identify = 1; map_addflooritem(&item_tmp,1,bl->m,bl->x,bl->y,0,0,0,0); } - skill_delunit(unit); + skill->delunit(unit); } break; case UNT_WARP_ACTIVE: // warp portal opens (morph to a UNT_WARP_WAITING cell) - group->unit_id = skill_get_unit_id(group->skill_id, 1); // UNT_WARP_WAITING - clif_changelook(&unit->bl, LOOK_BASE, group->unit_id); + group->unit_id = skill->get_unit_id(group->skill_id, 1); // UNT_WARP_WAITING + clif->changelook(&unit->bl, LOOK_BASE, group->unit_id); // restart timers - group->limit = skill_get_time(group->skill_id,group->skill_lv); - unit->limit = skill_get_time(group->skill_id,group->skill_lv); + group->limit = skill->get_time(group->skill_id,group->skill_lv); + unit->limit = skill->get_time(group->skill_id,group->skill_lv); // apply effect to all units standing on it - map_foreachincell(skill_unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); + map_foreachincell(skill->unit_effect,unit->bl.m,unit->bl.x,unit->bl.y,group->bl_flag,&unit->bl,gettick(),1); break; case UNT_CALLFAMILY: @@ -15501,17 +15459,17 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) if (sd && !map[sd->bl.m].flag.nowarp) pc_setpos(sd,map_id2index(unit->bl.m),unit->bl.x,unit->bl.y,CLR_TELEPORT); } - skill_delunit(unit); + skill->delunit(unit); } break; case UNT_REVERBERATION: if( unit->val1 <= 0 ) { // If it was deactivated. - skill_delunit(unit); + skill->delunit(unit); break; } - clif_changetraplook(bl,UNT_USED_TRAPS); - map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); + clif->changetraplook(bl,UNT_USED_TRAPS); + map_foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); group->limit = DIFF_TICK(tick,group->tick)+1000; unit->limit = DIFF_TICK(tick,group->tick)+1000; group->unit_id = UNT_USED_TRAPS; @@ -15520,8 +15478,8 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) case UNT_FEINTBOMB: { struct block_list *src = map_id2bl(group->src_id); if( src ) - map_foreachinrange(skill_area_sub, &group->unit->bl, unit->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill_castend_damage_id); - skill_delunit(unit); + map_foreachinrange(skill->area_sub, &group->unit->bl, unit->range, splash_target(src), src, SC_FEINTBOMB, group->skill_lv, tick, BCT_ENEMY|SD_ANIMATION|1, skill->castend_damage_id); + skill->delunit(unit); break; } @@ -15531,7 +15489,7 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) struct status_change *sc; if( !src || (sc = status_get_sc(src)) == NULL || !sc->data[SC_BANDING] ) { - skill_delunit(unit); + skill->delunit(unit); break; } // This unit isn't removed while SC_BANDING is active. @@ -15541,13 +15499,10 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) break; default: - skill_delunit(unit); + skill->delunit(unit); } - } - else - {// skill unit is still active - switch( group->unit_id ) - { + } else {// skill unit is still active + switch( group->unit_id ) { case UNT_ICEWALL: // icewall loses 50 hp every second unit->val1 -= SKILLUNITTIMER_INTERVAL/20; // trap's hp @@ -15566,9 +15521,9 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) case UNT_ANKLESNARE: if( unit->val1 <= 0 ) { if( group->unit_id == UNT_ANKLESNARE && group->val2 > 0 ) - skill_delunit(unit); + skill->delunit(unit); else { - clif_changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); + clif->changetraplook(bl, group->unit_id==UNT_LANDMINE?UNT_FIREPILLAR_ACTIVE:UNT_USED_TRAPS); group->limit = DIFF_TICK(tick, group->tick) + 1500; group->unit_id = UNT_USED_TRAPS; } @@ -15576,8 +15531,8 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) break; case UNT_REVERBERATION: if( unit->val1 <= 0 ){ - clif_changetraplook(bl,UNT_USED_TRAPS); - map_foreachinrange(skill_trap_splash, bl, skill_get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); + clif->changetraplook(bl,UNT_USED_TRAPS); + map_foreachinrange(skill->trap_splash, bl, skill->get_splash(group->skill_id, group->skill_lv), group->bl_flag, bl, tick); group->limit = DIFF_TICK(tick,group->tick)+1000; unit->limit = DIFF_TICK(tick,group->tick)+1000; group->unit_id = UNT_USED_TRAPS; @@ -15596,41 +15551,38 @@ static int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) if( !group || !unit->alive ) return 0; - dissonance = skill_dance_switch(unit, 0); + dissonance = skill->dance_switch(unit, 0); if( unit->range >= 0 && group->interval != -1 ) { if( battle_config.skill_wall_check ) - map_foreachinshootrange(skill_unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); + map_foreachinshootrange(skill->unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); else - map_foreachinrange(skill_unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); + map_foreachinrange(skill->unit_timer_sub_onplace, bl, unit->range, group->bl_flag, bl,tick); if(unit->range == -1) //Unit disabled, but it should not be deleted yet. group->unit_id = UNT_USED_TRAPS; - - if( group->unit_id == UNT_TATAMIGAESHI ) - { + else if( group->unit_id == UNT_TATAMIGAESHI ) { unit->range = -1; //Disable processed cell. - if (--group->val1 <= 0) // number of live cells - { //All tiles were processed, disable skill. + if (--group->val1 <= 0) { // number of live cells + //All tiles were processed, disable skill. group->target_flag=BCT_NOONE; group->bl_flag= BL_NUL; } } } - if( dissonance ) skill_dance_switch(unit, 1); + if( dissonance ) skill->dance_switch(unit, 1); return 0; } /*========================================== * Executes on all skill units every SKILLUNITTIMER_INTERVAL miliseconds. *------------------------------------------*/ -int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) -{ +int skill_unit_timer(int tid, unsigned int tick, int id, intptr_t data) { map_freeblock_lock(); - skillunit_db->foreach(skillunit_db, skill_unit_timer_sub, tick); + skillunit_db->foreach(skillunit_db, skill->unit_timer_sub, tick); map_freeblock_unlock(); @@ -15641,8 +15593,7 @@ static int skill_unit_temp[20]; // temporary storage for tracking skill unit sk /*========================================== * *------------------------------------------*/ -int skill_unit_move_sub (struct block_list* bl, va_list ap) -{ +int skill_unit_move_sub (struct block_list* bl, va_list ap) { struct skill_unit* unit = (struct skill_unit *)bl; struct skill_unit_group* group = unit->group; @@ -15660,37 +15611,30 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) return 0; if( flag&1 && ( unit->group->skill_id == PF_SPIDERWEB || unit->group->skill_id == GN_THORNS_TRAP ) ) - return 0; // Fiberlock is never supposed to trigger on skill_unit_move. [Inkfish] + return 0; // Fiberlock is never supposed to trigger on skill->unit_move. [Inkfish] - dissonance = skill_dance_switch(unit, 0); + dissonance = skill->dance_switch(unit, 0); //Necessary in case the group is deleted after calling on_place/on_out [Skotlex] skill_id = unit->group->skill_id; - if( unit->group->interval != -1 && !(skill_get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY ) //Lullaby is the exception, bugreport:411 + if( unit->group->interval != -1 && !(skill->get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY ) //Lullaby is the exception, bugreport:411 { //Non-dualmode unit skills with a timer don't trigger when walking, so just return - if( dissonance ) skill_dance_switch(unit, 1); + if( dissonance ) skill->dance_switch(unit, 1); return 0; } //Target-type check. - if( !(group->bl_flag&target->type && battle_check_target(&unit->bl,target,group->target_flag) > 0) ) - { - if( group->src_id == target->id && group->state.song_dance&0x2 ) - { //Ensemble check to see if they went out/in of the area [Skotlex] - if( flag&1 ) - { - if( flag&2 ) - { //Clear this skill id. + if( !(group->bl_flag&target->type && battle->check_target(&unit->bl,target,group->target_flag) > 0) ) { + if( group->src_id == target->id && group->state.song_dance&0x2 ) { //Ensemble check to see if they went out/in of the area [Skotlex] + if( flag&1 ) { + if( flag&2 ) { //Clear this skill id. ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == skill_id ); if( i < ARRAYLENGTH(skill_unit_temp) ) skill_unit_temp[i] = 0; } - } - else - { - if( flag&2 ) - { //Store this skill id. + } else { + if( flag&2 ) { //Store this skill id. ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0 ); if( i < ARRAYLENGTH(skill_unit_temp) ) skill_unit_temp[i] = skill_id; @@ -15701,30 +15645,23 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) } if( flag&4 ) - skill_unit_onleft(skill_id,target,tick); + skill->unit_onleft(skill_id,target,tick); } - if( dissonance ) skill_dance_switch(unit, 1); + if( dissonance ) skill->dance_switch(unit, 1); return 0; - } - else - { - if( flag&1 ) - { - int result = skill_unit_onplace(unit,target,tick); - if( flag&2 && result ) - { //Clear skill ids we have stored in onout. + } else { + if( flag&1 ) { + int result = skill->unit_onplace(unit,target,tick); + if( flag&2 && result ) { //Clear skill ids we have stored in onout. ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == result ); if( i < ARRAYLENGTH(skill_unit_temp) ) skill_unit_temp[i] = 0; } - } - else - { - int result = skill_unit_onout(unit,target,tick); - if( flag&2 && result ) - { //Store this unit id. + } else { + int result = skill->unit_onout(unit,target,tick); + if( flag&2 && result ) { //Store this unit id. ARR_FIND( 0, ARRAYLENGTH(skill_unit_temp), i, skill_unit_temp[i] == 0 ); if( i < ARRAYLENGTH(skill_unit_temp) ) skill_unit_temp[i] = skill_id; @@ -15736,10 +15673,10 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) //TODO: Normally, this is dangerous since the unit and group could be freed //inside the onout/onplace functions. Currently it is safe because we know song/dance //cells do not get deleted within them. [Skotlex] - if( dissonance ) skill_dance_switch(unit, 1); + if( dissonance ) skill->dance_switch(unit, 1); if( flag&4 ) - skill_unit_onleft(skill_id,target,tick); + skill->unit_onleft(skill_id,target,tick); return 1; } @@ -15753,26 +15690,23 @@ int skill_unit_move_sub (struct block_list* bl, va_list ap) * units to figure out when they have left a group. * flag&4: Force a onleft event (triggered when the bl is killed, for example) *------------------------------------------*/ -int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) -{ +int skill_unit_move (struct block_list *bl, unsigned int tick, int flag) { nullpo_ret(bl); if( bl->prev == NULL ) return 0; - if( flag&2 && !(flag&1) ) - { //Onout, clear data + if( flag&2 && !(flag&1) ) { //Onout, clear data memset(skill_unit_temp, 0, sizeof(skill_unit_temp)); } - map_foreachincell(skill_unit_move_sub,bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag); + map_foreachincell(skill->unit_move_sub,bl->m,bl->x,bl->y,BL_SKILL,bl,tick,flag); - if( flag&2 && flag&1 ) - { //Onplace, check any skill units you have left. + if( flag&2 && flag&1 ) { //Onplace, check any skill units you have left. int i; for( i = 0; i < ARRAYLENGTH(skill_unit_temp); i++ ) if( skill_unit_temp[i] ) - skill_unit_onleft(skill_unit_temp[i], bl, tick); + skill->unit_onleft(skill_unit_temp[i], bl, tick); } return 0; @@ -15796,7 +15730,7 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d if (group->unit==NULL) return 0; - if (skill_get_unit_flag(group->skill_id)&UF_ENSEMBLE) + if (skill->get_unit_flag(group->skill_id)&UF_ENSEMBLE) return 0; //Ensembles may not be moved around. if( group->unit_id == UNT_ICEWALL || group->unit_id == UNT_WALLOFTHORN ) @@ -15831,8 +15765,8 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d continue; if (!(m_flag[i]&0x2)) { if (group->state.song_dance&0x1) //Cancel dissonance effect. - skill_dance_overlap(unit1, 0); - map_foreachincell(skill_unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,4); + skill->dance_overlap(unit1, 0); + map_foreachincell(skill->unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,4); } //Move Cell using "smart" criteria (avoid useless moving around) switch(m_flag[i]) @@ -15861,9 +15795,9 @@ int skill_unit_move_unit_group (struct skill_unit_group *group, int16 m, int16 d } if (!(m_flag[i]&0x2)) { //We only moved the cell in 0-1 if (group->state.song_dance&0x1) //Check for dissonance effect. - skill_dance_overlap(unit1, 1); - clif_skill_setunit(unit1); - map_foreachincell(skill_unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,1); + skill->dance_overlap(unit1, 1); + clif->skill_setunit(unit1); + map_foreachincell(skill->unit_effect,unit1->bl.m,unit1->bl.x,unit1->bl.y,group->bl_flag,&unit1->bl,tick,1); } } aFree(m_flag); @@ -15950,7 +15884,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, if( sd->skill_id_old == skill_id ) skill_lv = sd->skill_lv_old; - if( !(idx=skill_can_produce_mix(sd,nameid,-1, qty)) ) + if( !(idx=skill->can_produce_mix(sd,nameid,-1, qty)) ) return 0; idx--; @@ -15997,7 +15931,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, for( i = 0; i < MAX_INVENTORY; i++ ) { if( sd->status.inventory[i].nameid == nameid ) { if( sd->status.inventory[i].amount >= data->stack.amount ) { - clif_msgtable(sd->fd,0x61b); + clif->msgtable(sd->fd,0x61b); return 0; } else { /** @@ -16076,9 +16010,9 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, make_per = pc_checkskill(sd,AM_LEARNINGPOTION)*50 + pc_checkskill(sd,AM_PHARMACY)*300 + sd->status.job_level*20 + (status->int_/2)*10 + status->dex*10+status->luk*10; - if(merc_is_hom_active(sd->hd)) {//Player got a homun + if(homun_alive(sd->hd)) {//Player got a homun int skill; - if((skill=merc_hom_checkskill(sd->hd,HVAN_INSTRUCT)) > 0) //His homun is a vanil with instruction change + if((skill=homun->checkskill(sd->hd,HVAN_INSTRUCT)) > 0) //His homun is a vanil with instruction change make_per += skill*100; //+1% bonus per level } switch(nameid){ @@ -16346,8 +16280,8 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, //TODO update PICKLOG if(equip){ - clif_produceeffect(sd,0,nameid); - clif_misceffect(&sd->bl,3); + clif->produce_effect(sd,0,nameid); + clif->misceffect(&sd->bl,3); if(itemdb_wlv(nameid) >= 3 && ((ele? 1 : 0) + sc) >= 3) // Fame point system [DracoRPG] pc_addfame(sd,10); // Success to forge a lv3 weapon with 3 additional ingredients = +10 fame point } else { @@ -16397,24 +16331,24 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, case AM_TWILIGHT2: case AM_TWILIGHT3: case ASC_CDP: - clif_produceeffect(sd,2,nameid); - clif_misceffect(&sd->bl,5); + clif->produce_effect(sd,2,nameid); + clif->misceffect(&sd->bl,5); break; case BS_IRON: case BS_STEEL: case BS_ENCHANTEDSTONE: - clif_produceeffect(sd,0,nameid); - clif_misceffect(&sd->bl,3); + clif->produce_effect(sd,0,nameid); + clif->misceffect(&sd->bl,3); break; case RK_RUNEMASTERY: case GC_CREATENEWPOISON: - clif_produceeffect(sd,2,nameid); - clif_misceffect(&sd->bl,5); + clif->produce_effect(sd,2,nameid); + clif->misceffect(&sd->bl,5); break; default: //Those that don't require a skill? if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20) { //Cooking items. - clif_specialeffect(&sd->bl, 608, AREA); + clif->specialeffect(&sd->bl, 608, AREA); if( sd->cook_mastery < 1999 ) pc_setglobalreg(sd, "COOK_MASTERY",sd->cook_mastery + ( 1 << ( (skill_produce_db[idx].itemlv - 11) / 2 ) ) * 5); } @@ -16429,7 +16363,7 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, if( rnd()%1000 < skill_changematerial_db[i].qty_rate[j] ){ tmp_item.amount = qty * skill_changematerial_db[i].qty[j]; if((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } k++; @@ -16438,16 +16372,16 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, break; } if( k ){ - clif_msg_skill(sd,skill_id,0x627); + clif->msg_skill(sd,skill_id,0x627); return 1; } } else if (tmp_item.amount) { //Success if((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } if( skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY ) - clif_msg_skill(sd,skill_id,0x627); + clif->msg_skill(sd,skill_id,0x627); return 1; } } @@ -16457,8 +16391,8 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, //TODO update PICKLOG if(equip){ - clif_produceeffect(sd,1,nameid); - clif_misceffect(&sd->bl,2); + clif->produce_effect(sd,1,nameid); + clif->misceffect(&sd->bl,2); } else { switch (skill_id) { case ASC_CDP: //25% Damage yourself, and display same effect as failed potion. @@ -16467,20 +16401,20 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, case AM_TWILIGHT1: case AM_TWILIGHT2: case AM_TWILIGHT3: - clif_produceeffect(sd,3,nameid); - clif_misceffect(&sd->bl,6); + clif->produce_effect(sd,3,nameid); + clif->misceffect(&sd->bl,6); sd->potion_success_counter = 0; // Fame point system [DracoRPG] break; case BS_IRON: case BS_STEEL: case BS_ENCHANTEDSTONE: - clif_produceeffect(sd,1,nameid); - clif_misceffect(&sd->bl,2); + clif->produce_effect(sd,1,nameid); + clif->misceffect(&sd->bl,2); break; case RK_RUNEMASTERY: case GC_CREATENEWPOISON: - clif_produceeffect(sd,3,nameid); - clif_misceffect(&sd->bl,6); + clif->produce_effect(sd,3,nameid); + clif->misceffect(&sd->bl,6); break; case GN_MIX_COOKING: { struct item tmp_item; @@ -16495,21 +16429,21 @@ int skill_produce_mix (struct map_session_data *sd, uint16 skill_id, int nameid, tmp_item.amount = qty; tmp_item.identify = 1; if( pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE) ) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } - clif_msg_skill(sd,skill_id,0x628); + clif->msg_skill(sd,skill_id,0x628); } break; case GN_MAKEBOMB: case GN_S_PHARMACY: case GN_CHANGEMATERIAL: - clif_msg_skill(sd,skill_id,0x628); + clif->msg_skill(sd,skill_id,0x628); break; default: if( skill_produce_db[idx].itemlv > 10 && skill_produce_db[idx].itemlv <= 20 ) { //Cooking items. - clif_specialeffect(&sd->bl, 609, AREA); + clif->specialeffect(&sd->bl, 609, AREA); if( sd->cook_mastery > 0 ) pc_setglobalreg(sd, "COOK_MASTERY", sd->cook_mastery - ( 1 << ((skill_produce_db[idx].itemlv - 11) / 2) ) - ( ( ( 1 << ((skill_produce_db[idx].itemlv - 11) / 2) ) >> 1 ) * 3 )); } @@ -16552,7 +16486,7 @@ int skill_arrow_create (struct map_session_data *sd, int nameid) if(tmp_item.nameid <= 0 || tmp_item.amount <= 0) continue; if((flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_PRODUCE))) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } @@ -16564,11 +16498,11 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) { int chance, i; nullpo_ret(sd); if( nameid <= 0 || (i = pc_search_inventory(sd,nameid)) < 0 || pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) { - clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); return 0; } switch( nameid ) - { // t_lv used to take duration from skill_get_time2 + { // t_lv used to take duration from skill->get_time2 case PO_PARALYSE: type = SC_PARALYSE; break; case PO_PYREXIA: type = SC_PYREXIA; break; case PO_DEATHHURT: type = SC_DEATHHURT; break; @@ -16578,39 +16512,34 @@ int skill_poisoningweapon( struct map_session_data *sd, int nameid) { case PO_MAGICMUSHROOM: type = SC_MAGICMUSHROOM; break; case PO_OBLIVIONCURSE: type = SC_OBLIVIONCURSE; break; default: - clif_skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,GC_POISONINGWEAPON,USESKILL_FAIL_LEVEL,0); return 0; } chance = 2 + 2 * sd->menuskill_val; // 2 + 2 * skill_lv sc_start4(&sd->bl, SC_POISONINGWEAPON, 100, pc_checkskill(sd, GC_RESEARCHNEWPOISON), //in Aegis it store the level of GC_RESEARCHNEWPOISON in val1 - type, chance, 0, skill_get_time(GC_POISONINGWEAPON, sd->menuskill_val)); + type, chance, 0, skill->get_time(GC_POISONINGWEAPON, sd->menuskill_val)); return 0; } -static void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) -{ +void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) { struct status_change *sc = status_get_sc(bl); // non-offensive and non-magic skills do not affect the status - if (skill_get_nk(skill_id)&NK_NO_DAMAGE || !(skill_get_type(skill_id)&BF_MAGIC)) + if (skill->get_nk(skill_id)&NK_NO_DAMAGE || !(skill->get_type(skill_id)&BF_MAGIC)) return; - if (sc && sc->count && sc->data[SC_MAGICPOWER]) - { - if (sc->data[SC_MAGICPOWER]->val4) - { + if (sc && sc->count && sc->data[SC_MAGICPOWER]) { + if (sc->data[SC_MAGICPOWER]->val4) { status_change_end(bl, SC_MAGICPOWER, INVALID_TIMER); - } - else - { + } else { sc->data[SC_MAGICPOWER]->val4 = 1; status_calc_bl(bl, status_sc2scb_flag(SC_MAGICPOWER)); #ifndef RENEWAL if(bl->type == BL_PC){// update current display. - clif_updatestatus(((TBL_PC *)bl),SP_MATK1); - clif_updatestatus(((TBL_PC *)bl),SP_MATK2); + clif->updatestatus(((TBL_PC *)bl),SP_MATK1); + clif->updatestatus(((TBL_PC *)bl),SP_MATK2); } #endif } @@ -16619,14 +16548,14 @@ static void skill_toggle_magicpower(struct block_list *bl, uint16 skill_id) int skill_magicdecoy(struct map_session_data *sd, int nameid) { - int x, y, i, class_, skill; + int x, y, i, class_, skill_id; struct mob_data *md; nullpo_ret(sd); - skill = sd->menuskill_val; + skill_id = sd->menuskill_val; - if( nameid <= 0 || !itemdb_is_element(nameid) || (i = pc_search_inventory(sd,nameid)) < 0 || !skill || pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) + if( nameid <= 0 || !itemdb_is_element(nameid) || (i = pc_search_inventory(sd,nameid)) < 0 || !skill_id || pc_delitem(sd,i,1,0,0,LOG_TYPE_CONSUME) ) { - clif_skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,NC_MAGICDECOY,USESKILL_FAIL_LEVEL,0); return 0; } @@ -16646,9 +16575,9 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) { md->special_state.ai = AI_FLORA; if( md->deletetimer != INVALID_TIMER ) delete_timer(md->deletetimer, mob_timer_delete); - md->deletetimer = add_timer (gettick() + skill_get_time(NC_MAGICDECOY,skill), mob_timer_delete, md->bl.id, 0); + md->deletetimer = add_timer (gettick() + skill->get_time(NC_MAGICDECOY,skill_id), mob_timer_delete, md->bl.id, 0); mob_spawn(md); - md->status.matk_min = md->status.matk_max = 250 + (50 * skill); + md->status.matk_min = md->status.matk_max = 250 + (50 * skill_id); } return 0; @@ -16667,7 +16596,7 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { for(i=SC_SPELLBOOK1; i <= SC_MAXSPELLBOOK; i++) if( sc && !sc->data[i] ) break; if( i > SC_MAXSPELLBOOK ) { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); + clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_READING, 0); return 0; } @@ -16676,18 +16605,17 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { if( !pc_checkskill(sd, (skill_id = skill_spellbook_db[i].skill_id)) ) { // User don't know the skill - sc_start(&sd->bl, SC_SLEEP, 100, 1, skill_get_time(WL_READING_SB, pc_checkskill(sd,WL_READING_SB))); - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); + sc_start(&sd->bl, SC_SLEEP, 100, 1, skill->get_time(WL_READING_SB, pc_checkskill(sd,WL_READING_SB))); + clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_DIFFICULT_SLEEP, 0); return 0; } max_preserve = 4 * pc_checkskill(sd, WL_FREEZE_SP) + status_get_int(&sd->bl) / 10 + sd->status.base_level / 10; point = skill_spellbook_db[i].point; - if( sc && sc->data[SC_READING_SB] ){ - if( (sc->data[SC_READING_SB]->val2 + point) > max_preserve ) - { - clif_skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0); + if( sc && sc->data[SC_READING_SB] ) { + if( (sc->data[SC_READING_SB]->val2 + point) > max_preserve ) { + clif->skill_fail(sd, WL_READING_SB, USESKILL_FAIL_SPELLBOOK_PRESERVATION_POINT, 0); return 0; } for(i = SC_MAXSPELLBOOK; i >= SC_SPELLBOOK1; i--){ // This is how official saves spellbook. [malufett] @@ -16705,24 +16633,26 @@ int skill_spellbook (struct map_session_data *sd, int nameid) { return 1; } int skill_select_menu(struct map_session_data *sd,uint16 skill_id) { - int id, lv, prob, aslvl = 0; + int id, lv, prob, aslvl = 0, idx = 0; nullpo_ret(sd); if (sd->sc.data[SC_STOP]) { aslvl = sd->sc.data[SC_STOP]->val1; status_change_end(&sd->bl,SC_STOP,INVALID_TIMER); } + + idx = skill->get_index(skill_id); - if( skill_id >= GS_GLITTERING || skill_get_type(skill_id) != BF_MAGIC || - (id = sd->status.skill[skill_id].id) == 0 || sd->status.skill[skill_id].flag != SKILL_FLAG_PLAGIARIZED ) { - clif_skill_fail(sd,SC_AUTOSHADOWSPELL,0,0); + if( skill_id >= GS_GLITTERING || skill->get_type(skill_id) != BF_MAGIC || + (id = sd->status.skill[idx].id) == 0 || sd->status.skill[idx].flag != SKILL_FLAG_PLAGIARIZED ) { + clif->skill_fail(sd,SC_AUTOSHADOWSPELL,0,0); return 0; } lv = (aslvl + 1) / 2; // The level the skill will be autocasted - lv = min(lv,sd->status.skill[skill_id].lv); + lv = min(lv,sd->status.skill[idx].lv); prob = (aslvl == 10) ? 15 : (32 - 2 * aslvl); // Probability at level 10 was increased to 15. - sc_start4(&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill_get_time(SC_AUTOSHADOWSPELL,aslvl)); + sc_start4(&sd->bl,SC__AUTOSHADOWSPELL,100,id,lv,prob,0,skill->get_time(SC_AUTOSHADOWSPELL,aslvl)); return 0; } int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, unsigned short* item_list) { @@ -16746,7 +16676,7 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, add_amount = (skill_lv == 1) ? del_amount * (5 + rnd()%5) : del_amount / 10 ; if( (nameid = sd->status.inventory[idx].nameid) <= 0 || del_amount > sd->status.inventory[idx].amount ) { - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } @@ -16762,17 +16692,17 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, case 992: product = 996; break; // Wind of Verdure -> Rough Wind. case 993: product = 997; break; // Green Live -> Great Nature. default: - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } if( pc_delitem(sd,idx,del_amount,0,1,LOG_TYPE_CONSUME) ) { - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } if( skill_lv == 2 && rnd()%100 < 25 ) { // At level 2 have a fail chance. You loose your items if it fails. - clif_skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0); return 1; } @@ -16784,7 +16714,7 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv, if( tmp_item.amount ) { if( (flag = pc_additem(sd,&tmp_item,tmp_item.amount,LOG_TYPE_CONSUME)) ) { - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); map_addflooritem(&tmp_item,tmp_item.amount,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0); } } @@ -16814,7 +16744,7 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite nameid = sd->status.inventory[idx].nameid; amount = item_list[k*2+1]; if( nameid > 0 && sd->status.inventory[idx].identify == 0 ){ - clif_msg_skill(sd,GN_CHANGEMATERIAL,0x62D); + clif->msg_skill(sd,GN_CHANGEMATERIAL,0x62D); return 0; } if( nameid == skill_produce_db[i].mat_id[j] && (amount-p*skill_produce_db[i].mat_amount[j]) >= skill_produce_db[i].mat_amount[j] @@ -16829,21 +16759,21 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite } while(n == j && c == n); p--; if ( p > 0 ) { - skill_produce_mix(sd,GN_CHANGEMATERIAL,skill_produce_db[i].nameid,0,0,0,p); + skill->produce_mix(sd,GN_CHANGEMATERIAL,skill_produce_db[i].nameid,0,0,0,p); return 1; } } } if( p == 0) - clif_msg_skill(sd,GN_CHANGEMATERIAL,0x623); + clif->msg_skill(sd,GN_CHANGEMATERIAL,0x623); return 0; } /** * for Royal Guard's LG_TRAMPLE **/ -static int skill_destroy_trap( struct block_list *bl, va_list ap ) { +int skill_destroy_trap( struct block_list *bl, va_list ap ) { struct skill_unit *su = (struct skill_unit *)bl; struct skill_unit_group *sg; unsigned int tick; @@ -16851,7 +16781,7 @@ static int skill_destroy_trap( struct block_list *bl, va_list ap ) { nullpo_ret(su); tick = va_arg(ap, unsigned int); - if (su->alive && (sg = su->group) && skill_get_inf2(sg->skill_id)&INF2_TRAP) { + if (su->alive && (sg = su->group) && skill->get_inf2(sg->skill_id)&INF2_TRAP) { switch( sg->unit_id ) { case UNT_LANDMINE: case UNT_CLAYMORETRAP: @@ -16863,19 +16793,18 @@ static int skill_destroy_trap( struct block_list *bl, va_list ap ) { case UNT_CLUSTERBOMB: case UNT_FIRINGTRAP: case UNT_ICEBOUNDTRAP: - map_foreachinrange(skill_trap_splash,&su->bl, skill_get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); + map_foreachinrange(skill->trap_splash,&su->bl, skill->get_splash(sg->skill_id, sg->skill_lv), sg->bl_flag, &su->bl,tick); break; } // Traps aren't recovered. - skill_delunit(su); + skill->delunit(su); } return 0; } /*========================================== * *------------------------------------------*/ -int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) -{ +int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) { struct map_session_data *sd = map_id2sd(id); struct skill_cd * cd = NULL; @@ -16919,11 +16848,9 @@ int skill_blockpc_end(int tid, unsigned int tick, int id, intptr_t data) * @param load whether this assignment is being loaded upon player login * @return 0 if successful, -1 otherwise */ -int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, bool load) -{ - int oskill_id = skill_id; +int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, bool load) { struct skill_cd* cd = NULL; - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); nullpo_retr (-1, sd); @@ -16936,12 +16863,10 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, } if( battle_config.display_status_timers ) - clif_skill_cooldown(sd, idx, tick); + clif->skill_cooldown(sd, idx, tick); - if( !load ) - {// not being loaded initially so ensure the skill delay is recorded - if( !(cd = idb_get(skillcd_db,sd->status.char_id)) ) - {// create a new skill cooldown object for map storage + if( !load ) {// not being loaded initially so ensure the skill delay is recorded + if( !(cd = idb_get(skillcd_db,sd->status.char_id)) ) {// create a new skill cooldown object for map storage CREATE( cd, struct skill_cd, 1 ); idb_put( skillcd_db, sd->status.char_id, cd ); } @@ -16949,16 +16874,15 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick, // record the skill duration in the database map cd->duration[cd->cursor] = tick; cd->skidx[cd->cursor] = idx; - cd->nameid[cd->cursor] = oskill_id; + cd->nameid[cd->cursor] = skill_id; cd->cursor++; } - sd->blockskill[idx] = 0x1|(0xFE&add_timer(gettick()+tick,skill_blockpc_end,sd->bl.id,idx)); + sd->blockskill[idx] = 0x1|(0xFE&add_timer(gettick()+tick,skill->blockpc_end,sd->bl.id,idx)); return 0; } -int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] -{ +int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) { //[orn] struct homun_data *hd = (TBL_HOM*) map_id2bl(id); if (data <= 0 || data >= MAX_SKILL) return 0; @@ -16967,9 +16891,8 @@ int skill_blockhomun_end(int tid, unsigned int tick, int id, intptr_t data) //[o return 1; } -int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) //[orn] -{ - uint16 idx = skill_get_index(skill_id); +int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) { //[orn] + uint16 idx = skill->get_index(skill_id); nullpo_retr (-1, hd); @@ -16981,11 +16904,10 @@ int skill_blockhomun_start(struct homun_data *hd, uint16 skill_id, int tick) //[ return -1; } hd->blockskill[idx] = 1; - return add_timer(gettick() + tick, skill_blockhomun_end, hd->bl.id, idx); + return add_timer(gettick() + tick, skill->blockhomun_end, hd->bl.id, idx); } -int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) //[orn] -{ +int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) {//[orn] struct mercenary_data *md = (TBL_MER*)map_id2bl(id); if( data <= 0 || data >= MAX_SKILL ) return 0; @@ -16996,7 +16918,7 @@ int skill_blockmerc_end(int tid, unsigned int tick, int id, intptr_t data) //[or int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick) { - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); nullpo_retr (-1, md); if (idx == 0) @@ -17007,7 +16929,7 @@ int skill_blockmerc_start(struct mercenary_data *md, uint16 skill_id, int tick) return -1; } md->blockskill[idx] = 1; - return add_timer(gettick() + tick, skill_blockmerc_end, md->bl.id, idx); + return add_timer(gettick() + tick, skill->blockmerc_end, md->bl.id, idx); } /** * Adds a new skill unit entry for this player to recast after map load @@ -17034,7 +16956,7 @@ void skill_usave_trigger(struct map_session_data *sd) { return; } - skill_unitsetting(&sd->bl,sus->skill_id,sus->skill_lv,sd->bl.x,sd->bl.y,0); + skill->unitsetting(&sd->bl,sus->skill_id,sus->skill_lv,sd->bl.x,sd->bl.y,0); idb_remove(skillusave_db,sd->status.char_id); @@ -17043,12 +16965,10 @@ void skill_usave_trigger(struct map_session_data *sd) { /* * */ -int skill_split_str (char *str, char **val, int num) -{ +int skill_split_str (char *str, char **val, int num) { int i; - for( i = 0; i < num && str; i++ ) - { + for( i = 0; i < num && str; i++ ) { val[i] = str; str = strchr(str,','); if( str ) @@ -17060,8 +16980,7 @@ int skill_split_str (char *str, char **val, int num) /* * */ -int skill_split_atoi (char *str, int *val) -{ +int skill_split_atoi (char *str, int *val) { int i, j, diff, step = 1; for (i=0; i<MAX_SKILL_LEVEL; i++) { @@ -17073,15 +16992,13 @@ int skill_split_atoi (char *str, int *val) } if(i==0) //No data found. return 0; - if(i==1) - { //Single value, have the whole range have the same value. + if(i==1) { //Single value, have the whole range have the same value. for (; i < MAX_SKILL_LEVEL; i++) val[i] = val[i-1]; return i; } //Check for linear change with increasing steps until we reach half of the data acquired. - for (step = 1; step <= i/2; step++) - { + for (step = 1; step <= i/2; step++) { diff = val[i-1] - val[i-step-1]; for(j = i-1; j >= step; j--) if ((val[j]-val[j-step]) != diff) @@ -17090,8 +17007,7 @@ int skill_split_atoi (char *str, int *val) if (j>=step) //No match, try next step. continue; - for(; i < MAX_SKILL_LEVEL; i++) - { //Apply linear increase + for(; i < MAX_SKILL_LEVEL; i++) { //Apply linear increase val[i] = val[i-step]+diff; if (val[i] < 1 && val[i-1] >=0) //Check if we have switched from + to -, cap the decrease to 0 in said cases. { val[i] = 1; diff = 0; step = 1; } @@ -17107,8 +17023,7 @@ int skill_split_atoi (char *str, int *val) /* * */ -void skill_init_unit_layout (void) -{ +void skill_init_unit_layout (void) { int i,j,size,pos = 0; memset(skill_unit_layout,0,sizeof(skill_unit_layout)); @@ -17128,163 +17043,156 @@ void skill_init_unit_layout (void) for (i=0;i<MAX_SKILL_DB;i++) { if (!skill_db[i].unit_id[0] || skill_db[i].unit_layout_type[0] != -1) continue; - if( i >= HM_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) { - int skill = i; - - if( i >= EL_SKILLRANGEMIN && i <= EL_SKILLRANGEMAX ) { - skill -= EL_SKILLRANGEMIN; - skill += EL_SKILLBASE; - } - if( skill == EL_FIRE_MANTLE ) { + + switch (skill_db[i].nameid) { + case MG_FIREWALL: + case WZ_ICEWALL: + case WL_EARTHSTRAIN://Warlock + // these will be handled later + break; + case PR_SANCTUARY: + case NPC_EVILLAND: { + static const int dx[] = { + -1, 0, 1,-2,-1, 0, 1, 2,-2,-1, + 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1}; + static const int dy[]={ + -2,-2,-2,-1,-1,-1,-1,-1, 0, 0, + 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2}; + skill_unit_layout[pos].count = 21; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case PR_MAGNUS: { + static const int dx[] = { + -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, + 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, + -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1}; + static const int dy[] = { + -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, + -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3}; + skill_unit_layout[pos].count = 33; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case MH_POISON_MIST: + case AS_VENOMDUST: { + static const int dx[] = {-1, 0, 0, 0, 1}; + static const int dy[] = { 0,-1, 0, 1, 0}; + skill_unit_layout[pos].count = 5; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case CR_GRANDCROSS: + case NPC_GRANDDARKNESS: { + static const int dx[] = { + 0, 0,-1, 0, 1,-2,-1, 0, 1, 2, + -4,-3,-2,-1, 0, 1, 2, 3, 4,-2, + -1, 0, 1, 2,-1, 0, 1, 0, 0}; + static const int dy[] = { + -4,-3,-2,-2,-2,-1,-1,-1,-1,-1, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 2, 2, 2, 3, 4}; + skill_unit_layout[pos].count = 29; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case PF_FOGWALL: { + static const int dx[] = { + -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; + static const int dy[] = { + -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; + skill_unit_layout[pos].count = 15; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case PA_GOSPEL: { + static const int dx[] = { + -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, + 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, + -3,-2,-1, 0, 1, 2, 3,-1, 0, 1, + -1, 0, 1}; + static const int dy[] = { + -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, + -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, + 3, 3, 3}; + skill_unit_layout[pos].count = 33; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case NJ_KAENSIN: { + static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; + static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2}; + skill_unit_layout[pos].count = 24; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case NJ_TATAMIGAESHI: { + //Level 1 (count 4, cross of 3x3) + static const int dx1[] = {-1, 1, 0, 0}; + static const int dy1[] = { 0, 0,-1, 1}; + //Level 2-3 (count 8, cross of 5x5) + static const int dx2[] = {-2,-1, 1, 2, 0, 0, 0, 0}; + static const int dy2[] = { 0, 0, 0, 0,-2,-1, 1, 2}; + //Level 4-5 (count 12, cross of 7x7 + static const int dx3[] = {-3,-2,-1, 1, 2, 3, 0, 0, 0, 0, 0, 0}; + static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3}; + //lv1 + j = 0; + skill_unit_layout[pos].count = 4; + memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1)); + memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1)); + skill_db[i].unit_layout_type[j] = pos; + //lv2/3 + j++; + pos++; + skill_unit_layout[pos].count = 8; + memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2)); + memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2)); + skill_db[i].unit_layout_type[j] = pos; + skill_db[i].unit_layout_type[++j] = pos; + //lv4/5 + j++; + pos++; + skill_unit_layout[pos].count = 12; + memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3)); + memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3)); + skill_db[i].unit_layout_type[j] = pos; + skill_db[i].unit_layout_type[++j] = pos; + //Fill in the rest using lv 5. + for (;j<MAX_SKILL_LEVEL;j++) + skill_db[i].unit_layout_type[j] = pos; + //Skip, this way the check below will fail and continue to the next skill. + pos++; + } + break; + case GN_WALLOFTHORN: { + static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0}; + static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2}; + skill_unit_layout[pos].count = 16; + memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); + memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); + } + break; + case EL_FIRE_MANTLE: { static const int dx[] = {-1, 0, 1, 1, 1, 0,-1,-1}; static const int dy[] = { 1, 1, 1, 0,-1,-1,-1, 0}; skill_unit_layout[pos].count = 8; memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - } else { - switch (i) { - case MG_FIREWALL: - case WZ_ICEWALL: - case WL_EARTHSTRAIN://Warlock - // these will be handled later - break; - case PR_SANCTUARY: - case NPC_EVILLAND: { - static const int dx[] = { - -1, 0, 1,-2,-1, 0, 1, 2,-2,-1, - 0, 1, 2,-2,-1, 0, 1, 2,-1, 0, 1}; - static const int dy[]={ - -2,-2,-2,-1,-1,-1,-1,-1, 0, 0, - 0, 0, 0, 1, 1, 1, 1, 1, 2, 2, 2}; - skill_unit_layout[pos].count = 21; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case PR_MAGNUS: { - static const int dx[] = { - -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, - 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, - -3,-2,-1, 0, 1, 2, 3,-1, 0, 1,-1, 0, 1}; - static const int dy[] = { - -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, - -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3}; - skill_unit_layout[pos].count = 33; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case MH_POISON_MIST: - case AS_VENOMDUST: { - static const int dx[] = {-1, 0, 0, 0, 1}; - static const int dy[] = { 0,-1, 0, 1, 0}; - skill_unit_layout[pos].count = 5; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case CR_GRANDCROSS: - case NPC_GRANDDARKNESS: { - static const int dx[] = { - 0, 0,-1, 0, 1,-2,-1, 0, 1, 2, - -4,-3,-2,-1, 0, 1, 2, 3, 4,-2, - -1, 0, 1, 2,-1, 0, 1, 0, 0}; - static const int dy[] = { - -4,-3,-2,-2,-2,-1,-1,-1,-1,-1, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, - 1, 1, 1, 1, 2, 2, 2, 3, 4}; - skill_unit_layout[pos].count = 29; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case PF_FOGWALL: { - static const int dx[] = { - -2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; - static const int dy[] = { - -1,-1,-1,-1,-1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1}; - skill_unit_layout[pos].count = 15; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case PA_GOSPEL: { - static const int dx[] = { - -1, 0, 1,-1, 0, 1,-3,-2,-1, 0, - 1, 2, 3,-3,-2,-1, 0, 1, 2, 3, - -3,-2,-1, 0, 1, 2, 3,-1, 0, 1, - -1, 0, 1}; - static const int dy[] = { - -3,-3,-3,-2,-2,-2,-1,-1,-1,-1, - -1,-1,-1, 0, 0, 0, 0, 0, 0, 0, - 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, - 3, 3, 3}; - skill_unit_layout[pos].count = 33; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case NJ_KAENSIN: { - static const int dx[] = {-2,-1, 0, 1, 2,-2,-1, 0, 1, 2,-2,-1, 1, 2,-2,-1, 0, 1, 2,-2,-1, 0, 1, 2}; - static const int dy[] = { 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0,-1,-1,-1,-1,-1,-2,-2,-2,-2,-2}; - skill_unit_layout[pos].count = 24; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - case NJ_TATAMIGAESHI: { - //Level 1 (count 4, cross of 3x3) - static const int dx1[] = {-1, 1, 0, 0}; - static const int dy1[] = { 0, 0,-1, 1}; - //Level 2-3 (count 8, cross of 5x5) - static const int dx2[] = {-2,-1, 1, 2, 0, 0, 0, 0}; - static const int dy2[] = { 0, 0, 0, 0,-2,-1, 1, 2}; - //Level 4-5 (count 12, cross of 7x7 - static const int dx3[] = {-3,-2,-1, 1, 2, 3, 0, 0, 0, 0, 0, 0}; - static const int dy3[] = { 0, 0, 0, 0, 0, 0,-3,-2,-1, 1, 2, 3}; - //lv1 - j = 0; - skill_unit_layout[pos].count = 4; - memcpy(skill_unit_layout[pos].dx,dx1,sizeof(dx1)); - memcpy(skill_unit_layout[pos].dy,dy1,sizeof(dy1)); - skill_db[i].unit_layout_type[j] = pos; - //lv2/3 - j++; - pos++; - skill_unit_layout[pos].count = 8; - memcpy(skill_unit_layout[pos].dx,dx2,sizeof(dx2)); - memcpy(skill_unit_layout[pos].dy,dy2,sizeof(dy2)); - skill_db[i].unit_layout_type[j] = pos; - skill_db[i].unit_layout_type[++j] = pos; - //lv4/5 - j++; - pos++; - skill_unit_layout[pos].count = 12; - memcpy(skill_unit_layout[pos].dx,dx3,sizeof(dx3)); - memcpy(skill_unit_layout[pos].dy,dy3,sizeof(dy3)); - skill_db[i].unit_layout_type[j] = pos; - skill_db[i].unit_layout_type[++j] = pos; - //Fill in the rest using lv 5. - for (;j<MAX_SKILL_LEVEL;j++) - skill_db[i].unit_layout_type[j] = pos; - //Skip, this way the check below will fail and continue to the next skill. - pos++; - } - break; - case GN_WALLOFTHORN: { - static const int dx[] = {-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2, 2, 2, 1, 0}; - static const int dy[] = { 2, 2, 1, 0,-1,-2,-2,-2,-2,-2,-1, 0, 1, 2, 2, 2}; - skill_unit_layout[pos].count = 16; - memcpy(skill_unit_layout[pos].dx,dx,sizeof(dx)); - memcpy(skill_unit_layout[pos].dy,dy,sizeof(dy)); - } - break; - default: - ShowError("unknown unit layout at skill %d\n",i); - break; - } + } + break; + default: + ShowError("unknown unit layout at skill %d\n",i); + break; } if (!skill_unit_layout[pos].count) continue; @@ -17393,11 +17301,10 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) { switch(type){ case SC_STASIS: - inf = skill_get_inf2(skill_id); - if( inf == INF2_SONG_DANCE || /*skill_get_inf2(skill_id) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL ) + inf = skill->get_inf2(skill_id); + if( inf == INF2_SONG_DANCE || /*skill->get_inf2(skill_id) == INF2_CHORUS_SKILL ||*/ inf == INF2_SPIRIT_SKILL ) return 1; // Can't do it. - switch( skill_id ) - { + switch( skill_id ) { case NV_FIRSTAID: case TF_HIDING: case AS_CLOAKING: case WZ_SIGHTRASHER: case RG_STRIPWEAPON: case RG_STRIPSHIELD: case RG_STRIPARMOR: case WZ_METEOR: case RG_STRIPHELM: case SC_STRIPACCESSARY: case ST_FULLSTRIP: case WZ_SIGHTBLASTER: @@ -17432,7 +17339,7 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) { } break; case SC_KAGEHUMI: - switch(skill_id){ + switch(skill_id) { case TF_HIDING: case AS_CLOAKING: case GC_CLOAKINGEXCEED: case SC_SHADOWFORM: case MI_HARMONIZE: case CG_MARIONETTE: case AL_TELEPORT: case TF_BACKSLIDING: case RA_CAMOUFLAGE: case ST_CHASEWALK: case GD_EMERGENCYCALL: @@ -17471,16 +17378,14 @@ void skill_cooldown_load(struct map_session_data * sd) // always check to make sure the session properly exists nullpo_retv(sd); - if( !(cd = idb_get(skillcd_db, sd->status.char_id)) ) - {// no skill cooldown is associated with this character + if( !(cd = idb_get(skillcd_db, sd->status.char_id)) ) {// no skill cooldown is associated with this character return; } // process each individual cooldown associated with the character - for( i = 0; i < cd->cursor; i++ ) - { + for( i = 0; i < cd->cursor; i++ ) { // block the skill from usage but ensure it is not recorded (load = true) - skill_blockpc_start_( sd, cd->nameid[i], cd->duration[i], true ); + skill->blockpc_start( sd, cd->nameid[i], cd->duration[i], true ); } } @@ -17488,9 +17393,8 @@ void skill_cooldown_load(struct map_session_data * sd) * sub-function of DB reading. * skill_db.txt *------------------------------------------*/ - -static bool skill_parse_row_skilldb(char* split[], int columns, int current) -{// id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description +bool skill_parse_row_skilldb(char* split[], int columns, int current) { +// id,range,hit,inf,element,nk,splash,max,list_num,castcancel,cast_defence_rate,inf2,maxcount,skill_type,blow_count,name,description uint16 skill_id = atoi(split[0]); uint16 idx; if( (skill_id >= GD_SKILLRANGEMIN && skill_id <= GD_SKILLRANGEMAX) @@ -17501,18 +17405,19 @@ static bool skill_parse_row_skilldb(char* split[], int columns, int current) return false; } - idx = skill_get_index(skill_id); + idx = skill->get_index(skill_id); if( !idx ) // invalid skill id return false; - - skill_split_atoi(split[1],skill_db[idx].range); + + skill_db[idx].nameid = skill_id; + skill->split_atoi(split[1],skill_db[idx].range); skill_db[idx].hit = atoi(split[2]); skill_db[idx].inf = atoi(split[3]); - skill_split_atoi(split[4],skill_db[idx].element); + skill->split_atoi(split[4],skill_db[idx].element); skill_db[idx].nk = (int)strtol(split[5], NULL, 0); - skill_split_atoi(split[6],skill_db[idx].splash); + skill->split_atoi(split[6],skill_db[idx].splash); skill_db[idx].max = atoi(split[7]); - skill_split_atoi(split[8],skill_db[idx].num); + skill->split_atoi(split[8],skill_db[idx].num); if( strcmpi(split[9],"yes") == 0 ) skill_db[idx].castcancel = 1; @@ -17520,7 +17425,7 @@ static bool skill_parse_row_skilldb(char* split[], int columns, int current) skill_db[idx].castcancel = 0; skill_db[idx].cast_def_rate = atoi(split[10]); skill_db[idx].inf2 = (int)strtol(split[11], NULL, 0); - skill_split_atoi(split[12],skill_db[idx].maxcount); + skill->split_atoi(split[12],skill_db[idx].maxcount); if( strcmpi(split[13],"weapon") == 0 ) skill_db[idx].skill_type = BF_WEAPON; else if( strcmpi(split[13],"magic") == 0 ) @@ -17529,42 +17434,39 @@ static bool skill_parse_row_skilldb(char* split[], int columns, int current) skill_db[idx].skill_type = BF_MISC; else skill_db[idx].skill_type = 0; - skill_split_atoi(split[14],skill_db[idx].blewcount); + skill->split_atoi(split[14],skill_db[idx].blewcount); safestrncpy(skill_db[idx].name, trim(split[15]), sizeof(skill_db[idx].name)); safestrncpy(skill_db[idx].desc, trim(split[16]), sizeof(skill_db[idx].desc)); strdb_iput(skilldb_name2id, skill_db[idx].name, skill_id); - + return true; } -static bool skill_parse_row_requiredb(char* split[], int columns, int current) -{// skill_id,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10 +bool skill_parse_row_requiredb(char* split[], int columns, int current) { +// skill_id,HPCost,MaxHPTrigger,SPCost,HPRateCost,SPRateCost,ZenyCost,RequiredWeapons,RequiredAmmoTypes,RequiredAmmoAmount,RequiredState,SpiritSphereCost,RequiredItemID1,RequiredItemAmount1,RequiredItemID2,RequiredItemAmount2,RequiredItemID3,RequiredItemAmount3,RequiredItemID4,RequiredItemAmount4,RequiredItemID5,RequiredItemAmount5,RequiredItemID6,RequiredItemAmount6,RequiredItemID7,RequiredItemAmount7,RequiredItemID8,RequiredItemAmount8,RequiredItemID9,RequiredItemAmount9,RequiredItemID10,RequiredItemAmount10 char* p; int j; uint16 skill_id = atoi(split[0]); - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); if( !idx ) // invalid skill id return false; - skill_split_atoi(split[1],skill_db[idx].hp); - skill_split_atoi(split[2],skill_db[idx].mhp); - skill_split_atoi(split[3],skill_db[idx].sp); - skill_split_atoi(split[4],skill_db[idx].hp_rate); - skill_split_atoi(split[5],skill_db[idx].sp_rate); - skill_split_atoi(split[6],skill_db[idx].zeny); + skill->split_atoi(split[1],skill_db[idx].hp); + skill->split_atoi(split[2],skill_db[idx].mhp); + skill->split_atoi(split[3],skill_db[idx].sp); + skill->split_atoi(split[4],skill_db[idx].hp_rate); + skill->split_atoi(split[5],skill_db[idx].sp_rate); + skill->split_atoi(split[6],skill_db[idx].zeny); //Wich weapon type are required, see doc/item_db for types p = split[7]; - for( j = 0; j < 32; j++ ) - { + for( j = 0; j < 32; j++ ) { int l = atoi(p); - if( l == 99 ) // Any weapon - { + if( l == 99 ) { // Any weapon skill_db[idx].weapon = 0; break; - } - else + } else skill_db[idx].weapon |= 1<<l; p = strchr(p,':'); if(!p) @@ -17574,55 +17476,49 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current) //FIXME: document this p = split[8]; - for( j = 0; j < 32; j++ ) - { + for( j = 0; j < 32; j++ ) { int l = atoi(p); - if( l == 99 ) // Any ammo type - { + if( l == 99 ) { // Any ammo type skill_db[idx].ammo = 0xFFFFFFFF; break; - } - else if( l ) // 0 stands for no requirement + } else if( l ) // 0 stands for no requirement skill_db[idx].ammo |= 1<<l; p = strchr(p,':'); if( !p ) break; p++; } - skill_split_atoi(split[9],skill_db[idx].ammo_qty); - - if( strcmpi(split[10],"hiding")==0 ) skill_db[idx].state = ST_HIDING; - else if( strcmpi(split[10],"cloaking")==0 ) skill_db[idx].state = ST_CLOAKING; - else if( strcmpi(split[10],"hidden")==0 ) skill_db[idx].state = ST_HIDDEN; - else if( strcmpi(split[10],"riding")==0 ) skill_db[idx].state = ST_RIDING; - else if( strcmpi(split[10],"falcon")==0 ) skill_db[idx].state = ST_FALCON; - else if( strcmpi(split[10],"cart")==0 ) skill_db[idx].state = ST_CART; - else if( strcmpi(split[10],"shield")==0 ) skill_db[idx].state = ST_SHIELD; - else if( strcmpi(split[10],"sight")==0 ) skill_db[idx].state = ST_SIGHT; - else if( strcmpi(split[10],"explosionspirits")==0 ) skill_db[idx].state = ST_EXPLOSIONSPIRITS; - else if( strcmpi(split[10],"cartboost")==0 ) skill_db[idx].state = ST_CARTBOOST; - else if( strcmpi(split[10],"recover_weight_rate")==0 ) skill_db[idx].state = ST_RECOV_WEIGHT_RATE; - else if( strcmpi(split[10],"move_enable")==0 ) skill_db[idx].state = ST_MOVE_ENABLE; - else if( strcmpi(split[10],"water")==0 ) skill_db[idx].state = ST_WATER; - /** - * New States - **/ - else if( strcmpi(split[10],"dragon")==0 ) skill_db[idx].state = ST_RIDINGDRAGON; - else if( strcmpi(split[10],"warg")==0 ) skill_db[idx].state = ST_WUG; - else if( strcmpi(split[10],"ridingwarg")==0 ) skill_db[idx].state = ST_RIDINGWUG; - else if( strcmpi(split[10],"mado")==0 ) skill_db[idx].state = ST_MADO; - else if( strcmpi(split[10],"elementalspirit")==0 ) skill_db[idx].state = ST_ELEMENTALSPIRIT; - else if (strcmpi(split[10], "poisonweapon") == 0) skill_db[idx].state = ST_POISONINGWEAPON; - else if (strcmpi(split[10], "rollingcutter") == 0) skill_db[idx].state = ST_ROLLINGCUTTER; - else if (strcmpi(split[10], "mh_fighting") == 0) skill_db[idx].state = ST_MH_FIGHTING; - else if (strcmpi(split[10], "mh_grappling") == 0) skill_db[idx].state = ST_MH_GRAPPLING; - + skill->split_atoi(split[9],skill_db[idx].ammo_qty); + + if( strcmpi(split[10],"hiding") == 0 ) skill_db[idx].state = ST_HIDING; + else if( strcmpi(split[10],"cloaking") == 0 ) skill_db[idx].state = ST_CLOAKING; + else if( strcmpi(split[10],"hidden") == 0 ) skill_db[idx].state = ST_HIDDEN; + else if( strcmpi(split[10],"riding") == 0 ) skill_db[idx].state = ST_RIDING; + else if( strcmpi(split[10],"falcon") == 0 ) skill_db[idx].state = ST_FALCON; + else if( strcmpi(split[10],"cart") == 0 ) skill_db[idx].state = ST_CART; + else if( strcmpi(split[10],"shield") == 0 ) skill_db[idx].state = ST_SHIELD; + else if( strcmpi(split[10],"sight") == 0 ) skill_db[idx].state = ST_SIGHT; + else if( strcmpi(split[10],"explosionspirits") == 0 ) skill_db[idx].state = ST_EXPLOSIONSPIRITS; + else if( strcmpi(split[10],"cartboost") == 0 ) skill_db[idx].state = ST_CARTBOOST; + else if( strcmpi(split[10],"recover_weight_rate") == 0 ) skill_db[idx].state = ST_RECOV_WEIGHT_RATE; + else if( strcmpi(split[10],"move_enable") == 0 ) skill_db[idx].state = ST_MOVE_ENABLE; + else if( strcmpi(split[10],"water") == 0 ) skill_db[idx].state = ST_WATER; + else if( strcmpi(split[10],"dragon") == 0 ) skill_db[idx].state = ST_RIDINGDRAGON; + else if( strcmpi(split[10],"warg") == 0 ) skill_db[idx].state = ST_WUG; + else if( strcmpi(split[10],"ridingwarg") == 0 ) skill_db[idx].state = ST_RIDINGWUG; + else if( strcmpi(split[10],"mado") == 0 ) skill_db[idx].state = ST_MADO; + else if( strcmpi(split[10],"elementalspirit") == 0 ) skill_db[idx].state = ST_ELEMENTALSPIRIT; + else if( strcmpi(split[10],"poisonweapon") == 0 ) skill_db[idx].state = ST_POISONINGWEAPON; + else if( strcmpi(split[10],"rollingcutter") == 0 ) skill_db[idx].state = ST_ROLLINGCUTTER; + else if( strcmpi(split[10],"mh_fighting") == 0 ) skill_db[idx].state = ST_MH_FIGHTING; + else if( strcmpi(split[10],"mh_grappling") == 0 ) skill_db[idx].state = ST_MH_GRAPPLING; + else if( strcmpi(split[10],"peco") == 0 ) skill_db[idx].state = ST_PECO; /** * Unknown or no state **/ else skill_db[idx].state = ST_NONE; - skill_split_atoi(split[11],skill_db[idx].spiritball); + skill->split_atoi(split[11],skill_db[idx].spiritball); for( j = 0; j < MAX_SKILL_ITEM_REQUIRE; j++ ) { skill_db[idx].itemid[j] = atoi(split[12+ 2*j]); skill_db[idx].amount[j] = atoi(split[13+ 2*j]); @@ -17631,62 +17527,50 @@ static bool skill_parse_row_requiredb(char* split[], int columns, int current) return true; } -static bool skill_parse_row_castdb(char* split[], int columns, int current) -{// skill_id,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2 +bool skill_parse_row_castdb(char* split[], int columns, int current) { +// skill_id,CastingTime,AfterCastActDelay,AfterCastWalkDelay,Duration1,Duration2 uint16 skill_id = atoi(split[0]); - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); if( !idx ) // invalid skill id return false; - skill_split_atoi(split[1],skill_db[idx].cast); - skill_split_atoi(split[2],skill_db[idx].delay); - skill_split_atoi(split[3],skill_db[idx].walkdelay); - skill_split_atoi(split[4],skill_db[idx].upkeep_time); - skill_split_atoi(split[5],skill_db[idx].upkeep_time2); - skill_split_atoi(split[6],skill_db[idx].cooldown); + skill->split_atoi(split[1],skill_db[idx].cast); + skill->split_atoi(split[2],skill_db[idx].delay); + skill->split_atoi(split[3],skill_db[idx].walkdelay); + skill->split_atoi(split[4],skill_db[idx].upkeep_time); + skill->split_atoi(split[5],skill_db[idx].upkeep_time2); + skill->split_atoi(split[6],skill_db[idx].cooldown); #ifdef RENEWAL_CAST - skill_split_atoi(split[7],skill_db[idx].fixed_cast); + skill->split_atoi(split[7],skill_db[idx].fixed_cast); #endif return true; } -static bool skill_parse_row_castnodexdb(char* split[], int columns, int current) -{// Skill id,Cast,Delay (optional) +bool skill_parse_row_castnodexdb(char* split[], int columns, int current) { +// Skill id,Cast,Delay (optional) uint16 skill_id = atoi(split[0]); - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); if( !idx ) // invalid skill id return false; - skill_split_atoi(split[1],skill_db[idx].castnodex); + skill->split_atoi(split[1],skill_db[idx].castnodex); if( split[2] ) // optional column - skill_split_atoi(split[2],skill_db[idx].delaynodex); - - return true; -} - -static bool skill_parse_row_nocastdb(char* split[], int columns, int current) -{// skill_id,Flag - uint16 skill_id = atoi(split[0]); - uint16 idx = skill_get_index(skill_id); - if( !idx ) // invalid skill id - return false; - - skill_db[idx].nocast |= atoi(split[1]); + skill->split_atoi(split[2],skill_db[idx].delaynodex); return true; } -static bool skill_parse_row_unitdb(char* split[], int columns, int current) -{// ID,unit ID,unit ID 2,layout,range,interval,target,flag +bool skill_parse_row_unitdb(char* split[], int columns, int current) { +// ID,unit ID,unit ID 2,layout,range,interval,target,flag uint16 skill_id = atoi(split[0]); - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); if( !idx ) // invalid skill id return false; skill_db[idx].unit_id[0] = strtol(split[1],NULL,16); skill_db[idx].unit_id[1] = strtol(split[2],NULL,16); - skill_split_atoi(split[3],skill_db[idx].unit_layout_type); - skill_split_atoi(split[4],skill_db[idx].unit_range); + skill->split_atoi(split[3],skill_db[idx].unit_layout_type); + skill->split_atoi(split[4],skill_db[idx].unit_range); skill_db[idx].unit_interval = atoi(split[5]); if( strcmpi(split[6],"noenemy")==0 ) skill_db[idx].unit_target = BCT_NOENEMY; @@ -17717,8 +17601,8 @@ static bool skill_parse_row_unitdb(char* split[], int columns, int current) return true; } -static bool skill_parse_row_producedb(char* split[], int columns, int current) -{// ProduceItemID,ItemLV,RequireSkill,Requireskill_lv,MaterialID1,MaterialAmount1,...... +bool skill_parse_row_producedb(char* split[], int columns, int current) { +// ProduceItemID,ItemLV,RequireSkill,Requireskill_lv,MaterialID1,MaterialAmount1,...... int x,y; int i = atoi(split[0]); @@ -17730,17 +17614,16 @@ static bool skill_parse_row_producedb(char* split[], int columns, int current) skill_produce_db[current].req_skill = atoi(split[2]); skill_produce_db[current].req_skill_lv = atoi(split[3]); - for( x = 4, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_PRODUCE_RESOURCE; x += 2, y++ ) - { + for( x = 4, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_PRODUCE_RESOURCE; x += 2, y++ ) { skill_produce_db[current].mat_id[y] = atoi(split[x]); skill_produce_db[current].mat_amount[y] = atoi(split[x+1]); } - + return true; } -static bool skill_parse_row_createarrowdb(char* split[], int columns, int current) -{// SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5 +bool skill_parse_row_createarrowdb(char* split[], int columns, int current) { +// SourceID,MakeID1,MakeAmount1,...,MakeID5,MakeAmount5 int x,y; int i = atoi(split[0]); @@ -17749,29 +17632,27 @@ static bool skill_parse_row_createarrowdb(char* split[], int columns, int curren skill_arrow_db[current].nameid = i; - for( x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESOURCE; x += 2, y++ ) - { + for( x = 1, y = 0; x+1 < columns && split[x] && split[x+1] && y < MAX_ARROW_RESOURCE; x += 2, y++ ) { skill_arrow_db[current].cre_id[y] = atoi(split[x]); skill_arrow_db[current].cre_amount[y] = atoi(split[x+1]); } return true; } -static bool skill_parse_row_spellbookdb(char* split[], int columns, int current) -{// skill_id,PreservePoints +bool skill_parse_row_spellbookdb(char* split[], int columns, int current) { +// skill_id,PreservePoints uint16 skill_id = atoi(split[0]); int points = atoi(split[1]); int nameid = atoi(split[2]); - if( !skill_get_index(skill_id) || !skill_get_max(skill_id) ) + if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) ShowError("spellbook_db: Invalid skill ID %d\n", skill_id); - if ( !skill_get_inf(skill_id) ) - ShowError("spellbook_db: Passive skills cannot be memorized (%d/%s)\n", skill_id, skill_get_name(skill_id)); + if ( !skill->get_inf(skill_id) ) + ShowError("spellbook_db: Passive skills cannot be memorized (%d/%s)\n", skill_id, skill->get_name(skill_id)); if( points < 1 ) - ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skill_id, skill_get_name(skill_id)); - else - { + ShowError("spellbook_db: PreservePoints have to be 1 or above! (%d/%s)\n", skill_id, skill->get_name(skill_id)); + else { skill_spellbook_db[current].skill_id = skill_id; skill_spellbook_db[current].point = points; skill_spellbook_db[current].nameid = nameid; @@ -17781,21 +17662,21 @@ static bool skill_parse_row_spellbookdb(char* split[], int columns, int current) return false; } -static bool skill_parse_row_improvisedb(char* split[], int columns, int current) -{// SkillID,Rate +bool skill_parse_row_improvisedb(char* split[], int columns, int current) { +// SkillID,Rate uint16 skill_id = atoi(split[0]); short j = atoi(split[1]); - if( !skill_get_index(skill_id) || !skill_get_max(skill_id) ) { + if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) { ShowError("skill_improvise_db: Invalid skill ID %d\n", skill_id); return false; } - if ( !skill_get_inf(skill_id) ) { - ShowError("skill_improvise_db: Passive skills cannot be casted (%d/%s)\n", skill_id, skill_get_name(skill_id)); + if ( !skill->get_inf(skill_id) ) { + ShowError("skill_improvise_db: Passive skills cannot be casted (%d/%s)\n", skill_id, skill->get_name(skill_id)); return false; } if( j < 1 ) { - ShowError("skill_improvise_db: Chances have to be 1 or above! (%d/%s)\n", skill_id, skill_get_name(skill_id)); + ShowError("skill_improvise_db: Chances have to be 1 or above! (%d/%s)\n", skill_id, skill->get_name(skill_id)); return false; } if( current >= MAX_SKILL_IMPROVISE_DB ) { @@ -17806,18 +17687,16 @@ static bool skill_parse_row_improvisedb(char* split[], int columns, int current) return true; } -static bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) -{// SkillID +bool skill_parse_row_magicmushroomdb(char* split[], int column, int current) { +// SkillID uint16 skill_id = atoi(split[0]); - if( !skill_get_index(skill_id) || !skill_get_max(skill_id) ) - { + if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) { ShowError("magicmushroom_db: Invalid skill ID %d\n", skill_id); return false; } - if ( !skill_get_inf(skill_id) ) - { - ShowError("magicmushroom_db: Passive skills cannot be casted (%d/%s)\n", skill_id, skill_get_name(skill_id)); + if ( !skill->get_inf(skill_id) ) { + ShowError("magicmushroom_db: Passive skills cannot be casted (%d/%s)\n", skill_id, skill->get_name(skill_id)); return false; } @@ -17826,9 +17705,9 @@ static bool skill_parse_row_magicmushroomdb(char* split[], int column, int curre return true; } -static bool skill_parse_row_reproducedb(char* split[], int column, int current) { +bool skill_parse_row_reproducedb(char* split[], int column, int current) { uint16 skill_id = atoi(split[0]); - uint16 idx = skill_get_index(skill_id); + uint16 idx = skill->get_index(skill_id); if( !idx ) return false; @@ -17838,17 +17717,15 @@ static bool skill_parse_row_reproducedb(char* split[], int column, int current) } -static bool skill_parse_row_abradb(char* split[], int columns, int current) -{// skill_id,DummyName,RequiredHocusPocusLevel,Rate +bool skill_parse_row_abradb(char* split[], int columns, int current) { +// skill_id,DummyName,RequiredHocusPocusLevel,Rate uint16 skill_id = atoi(split[0]); - if( !skill_get_index(skill_id) || !skill_get_max(skill_id) ) - { + if( !skill->get_index(skill_id) || !skill->get_max(skill_id) ) { ShowError("abra_db: Invalid skill ID %d\n", skill_id); return false; } - if ( !skill_get_inf(skill_id) ) - { - ShowError("abra_db: Passive skills cannot be casted (%d/%s)\n", skill_id, skill_get_name(skill_id)); + if ( !skill->get_inf(skill_id) ) { + ShowError("abra_db: Passive skills cannot be casted (%d/%s)\n", skill_id, skill->get_name(skill_id)); return false; } @@ -17859,8 +17736,8 @@ static bool skill_parse_row_abradb(char* split[], int columns, int current) return true; } -static bool skill_parse_row_changematerialdb(char* split[], int columns, int current) -{// ProductID,BaseRate,MakeAmount1,MakeAmountRate1...,MakeAmount5,MakeAmountRate5 +bool skill_parse_row_changematerialdb(char* split[], int columns, int current) { +// ProductID,BaseRate,MakeAmount1,MakeAmountRate1...,MakeAmount5,MakeAmountRate5 uint16 skill_id = atoi(split[0]); short j = atoi(split[1]); int x,y; @@ -17883,8 +17760,7 @@ static bool skill_parse_row_changematerialdb(char* split[], int columns, int cur skill_changematerial_db[current].itemid = skill_id; skill_changematerial_db[current].rate = j; - for( x = 2, y = 0; x+1 < columns && split[x] && split[x+1] && y < 5; x += 2, y++ ) - { + for( x = 2, y = 0; x+1 < columns && split[x] && split[x+1] && y < 5; x += 2, y++ ) { skill_changematerial_db[current].qty[y] = atoi(split[x]); skill_changematerial_db[current].qty_rate[y] = atoi(split[x+1]); } @@ -17904,8 +17780,7 @@ static bool skill_parse_row_changematerialdb(char* split[], int columns, int cur * create_arrow_db.txt * abra_db.txt *------------------------------*/ -static void skill_readdb(void) -{ +void skill_readdb(void) { // init skill db structures db_clear(skilldb_name2id); memset(skill_db,0,sizeof(skill_db)); @@ -17921,51 +17796,63 @@ static void skill_readdb(void) safestrncpy(skill_db[0].name, "UNKNOWN_SKILL", sizeof(skill_db[0].name)); safestrncpy(skill_db[0].desc, "Unknown Skill", sizeof(skill_db[0].desc)); - sv_readdb(db_path, DBPATH"skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill_parse_row_skilldb); - sv_readdb(db_path, DBPATH"skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill_parse_row_requiredb); + sv->readdb(db_path, DBPATH"skill_db.txt" , ',', 17, 17, MAX_SKILL_DB, skill->parse_row_skilldb); + sv->readdb(db_path, DBPATH"skill_require_db.txt" , ',', 32, 32, MAX_SKILL_DB, skill->parse_row_requiredb); #ifdef RENEWAL_CAST - sv_readdb(db_path, "re/skill_cast_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_castdb); + sv->readdb(db_path, "re/skill_cast_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill->parse_row_castdb); #else - sv_readdb(db_path, "pre-re/skill_cast_db.txt" , ',', 7, 7, MAX_SKILL_DB, skill_parse_row_castdb); + sv->readdb(db_path, "pre-re/skill_cast_db.txt" , ',', 7, 7, MAX_SKILL_DB, skill->parse_row_castdb); #endif - sv_readdb(db_path, DBPATH"skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill_parse_row_castnodexdb); - sv_readdb(db_path, DBPATH"skill_unit_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill_parse_row_unitdb); - - sv_readdb(db_path, DBPATH"skill_nocast_db.txt" , ',', 2, 2, MAX_SKILL_DB, skill_parse_row_nocastdb); + sv->readdb(db_path, DBPATH"skill_castnodex_db.txt", ',', 2, 3, MAX_SKILL_DB, skill->parse_row_castnodexdb); + sv->readdb(db_path, DBPATH"skill_unit_db.txt" , ',', 8, 8, MAX_SKILL_DB, skill->parse_row_unitdb); - skill_init_unit_layout(); - sv_readdb(db_path, "produce_db.txt" , ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill_parse_row_producedb); - sv_readdb(db_path, "create_arrow_db.txt" , ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill_parse_row_createarrowdb); - sv_readdb(db_path, "abra_db.txt" , ',', 4, 4, MAX_SKILL_ABRA_DB, skill_parse_row_abradb); + skill->init_unit_layout(); + sv->readdb(db_path, "produce_db.txt" , ',', 4, 4+2*MAX_PRODUCE_RESOURCE, MAX_SKILL_PRODUCE_DB, skill->parse_row_producedb); + sv->readdb(db_path, "create_arrow_db.txt" , ',', 1+2, 1+2*MAX_ARROW_RESOURCE, MAX_SKILL_ARROW_DB, skill->parse_row_createarrowdb); + sv->readdb(db_path, "abra_db.txt" , ',', 4, 4, MAX_SKILL_ABRA_DB, skill->parse_row_abradb); //Warlock - sv_readdb(db_path, "spellbook_db.txt" , ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill_parse_row_spellbookdb); + sv->readdb(db_path, "spellbook_db.txt" , ',', 3, 3, MAX_SKILL_SPELLBOOK_DB, skill->parse_row_spellbookdb); //Guillotine Cross - sv_readdb(db_path, "magicmushroom_db.txt" , ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill_parse_row_magicmushroomdb); - sv_readdb(db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill_parse_row_reproducedb); - sv_readdb(db_path, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill_parse_row_improvisedb); - sv_readdb(db_path, "skill_changematerial_db.txt" , ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill_parse_row_changematerialdb); - + sv->readdb(db_path, "magicmushroom_db.txt" , ',', 1, 1, MAX_SKILL_MAGICMUSHROOM_DB, skill->parse_row_magicmushroomdb); + sv->readdb(db_path, "skill_reproduce_db.txt", ',', 1, 1, MAX_SKILL_DB, skill->parse_row_reproducedb); + sv->readdb(db_path, "skill_improvise_db.txt" , ',', 2, 2, MAX_SKILL_IMPROVISE_DB, skill->parse_row_improvisedb); + sv->readdb(db_path, "skill_changematerial_db.txt" , ',', 4, 4+2*5, MAX_SKILL_PRODUCE_DB, skill->parse_row_changematerialdb); } void skill_reload (void) { struct s_mapiterator *iter; struct map_session_data *sd; - skill_readdb(); + int i,c,k; + + skill->read_db(); + + //[Ind/Hercules] refresh index cache + for(c = 0; c < CLASS_COUNT; c++) { + for( i = 0; i < MAX_SKILL_TREE; i++ ) { + if( skill_tree[c][i].id ) { + skill_tree[c][i].idx = skill->get_index(skill_tree[c][i].id); + for(k = 0; k < MAX_PC_SKILL_REQUIRE; k++) { + if( skill_tree[c][i].need[k].id ) + skill_tree[c][i].need[k].idx = skill->get_index(skill_tree[c][i].need[k].id); + } + } + } + } + chrif_skillid2idx(0); /* lets update all players skill tree : so that if any skill modes were changed they're properly updated */ iter = mapit_getallusers(); - for( sd = (TBL_PC*)mapit_first(iter); mapit_exists(iter); sd = (TBL_PC*)mapit_next(iter) ) - clif_skillinfoblock(sd); - mapit_free(iter); + for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) + clif->skillinfoblock(sd); + mapit->free(iter); } /*========================================== * *------------------------------------------*/ -int do_init_skill (void) -{ +int do_init_skill (void) { skilldb_name2id = strdb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, 0); - skill_readdb(); + skill->read_db(); group_db = idb_alloc(DB_OPT_BASE); skillunit_db = idb_alloc(DB_OPT_BASE); @@ -17974,13 +17861,13 @@ int do_init_skill (void) skill_unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_NONE); skill_timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE); - add_timer_func_list(skill_unit_timer,"skill_unit_timer"); - add_timer_func_list(skill_castend_id,"skill_castend_id"); - add_timer_func_list(skill_castend_pos,"skill_castend_pos"); - add_timer_func_list(skill_timerskill,"skill_timerskill"); - add_timer_func_list(skill_blockpc_end, "skill_blockpc_end"); + add_timer_func_list(skill->unit_timer,"skill_unit_timer"); + add_timer_func_list(skill->castend_id,"skill_castend_id"); + add_timer_func_list(skill->castend_pos,"skill_castend_pos"); + add_timer_func_list(skill->timerskill,"skill_timerskill"); + add_timer_func_list(skill->blockpc_end, "skill_blockpc_end"); - add_timer_interval(gettick()+SKILLUNITTIMER_INTERVAL,skill_unit_timer,0,0,SKILLUNITTIMER_INTERVAL); + add_timer_interval(gettick()+SKILLUNITTIMER_INTERVAL,skill->unit_timer,0,0,SKILLUNITTIMER_INTERVAL); return 0; } @@ -17996,3 +17883,194 @@ int do_final_skill(void) ers_destroy(skill_timer_ers); return 0; } +/* initialize the interface */ +void skill_defaults(void) { + skill = &skill_s; + skill->init = do_init_skill; + skill->final = do_final_skill; + skill->reload = skill_reload; + skill->read_db = skill_readdb; + /* accesssors */ + skill->get_index = skill_get_index; + skill->get_type = skill_get_type; + skill->get_hit = skill_get_hit; + skill->get_inf = skill_get_inf; + skill->get_ele = skill_get_ele; + skill->get_nk = skill_get_nk; + skill->get_max = skill_get_max; + skill->get_range = skill_get_range; + skill->get_range2 = skill_get_range2; + skill->get_splash = skill_get_splash; + skill->get_hp = skill_get_hp; + skill->get_mhp = skill_get_mhp; + skill->get_sp = skill_get_sp; + skill->get_state = skill_get_state; + skill->get_zeny = skill_get_zeny; + skill->get_num = skill_get_num; + skill->get_cast = skill_get_cast; + skill->get_delay = skill_get_delay; + skill->get_walkdelay = skill_get_walkdelay; + skill->get_time = skill_get_time; + skill->get_time2 = skill_get_time2; + skill->get_castnodex = skill_get_castnodex; + skill->get_delaynodex = skill_get_delaynodex; + skill->get_castdef = skill_get_castdef; + skill->get_weapontype = skill_get_weapontype; + skill->get_ammotype = skill_get_ammotype; + skill->get_ammo_qty = skill_get_ammo_qty; + skill->get_unit_id = skill_get_unit_id; + skill->get_inf2 = skill_get_inf2; + skill->get_castcancel = skill_get_castcancel; + skill->get_maxcount = skill_get_maxcount; + skill->get_blewcount = skill_get_blewcount; + skill->get_unit_flag = skill_get_unit_flag; + skill->get_unit_target = skill_get_unit_target; + skill->get_unit_interval = skill_get_unit_interval; + skill->get_unit_bl_target = skill_get_unit_bl_target; + skill->get_spiritball = skill_get_spiritball; + skill->get_unit_layout_type = skill_get_unit_layout_type; + skill->get_unit_range = skill_get_unit_range; + skill->get_cooldown = skill_get_cooldown; + skill->tree_get_max = skill_tree_get_max; + skill->get_name = skill_get_name; + skill->get_desc = skill_get_desc; + skill->chk = skill_chk; + skill->get_casttype = skill_get_casttype; + skill->get_casttype2 = skill_get_casttype2; + skill->name2id = skill_name2id; + skill->isammotype = skill_isammotype; + skill->castend_id = skill_castend_id; + skill->castend_pos = skill_castend_pos; + skill->castend_map = skill_castend_map; + skill->cleartimerskill = skill_cleartimerskill; + skill->addtimerskill = skill_addtimerskill; + skill->additional_effect = skill_additional_effect; + skill->counter_additional_effect = skill_counter_additional_effect; + skill->blown = skill_blown; + skill->break_equip = skill_break_equip; + skill->strip_equip = skill_strip_equip; + skill->id2group = skill_id2group; + skill->unitsetting = skill_unitsetting; + skill->initunit = skill_initunit; + skill->delunit = skill_delunit; + skill->init_unitgroup = skill_initunitgroup; + skill->del_unitgroup = skill_delunitgroup; + skill->clear_unitgroup = skill_clear_unitgroup; + skill->clear_group = skill_clear_group; + skill->unit_onplace = skill_unit_onplace; + skill->unit_ondamaged = skill_unit_ondamaged; + skill->cast_fix = skill_castfix; + skill->cast_fix_sc = skill_castfix_sc; +#ifdef RENEWAL_CAST + skill->vf_cast_fix = skill_vfcastfix; +#endif + skill->delay_fix = skill_delay_fix; + skill->check_condition_castbegin = skill_check_condition_castbegin; + skill->check_condition_castend = skill_check_condition_castend; + skill->get_requirement = skill_get_requirement; + skill->check_pc_partner = skill_check_pc_partner; + skill->consume_requirement = skill_consume_requirement; + skill->unit_move = skill_unit_move; + skill->unit_move_unit_group = skill_unit_move_unit_group; + skill->unit_onleft = skill_unit_onleft; + skill->unit_onout = skill_unit_onout; + skill->guildaura_sub = skill_guildaura_sub; + skill->sit = skill_sit; + skill->brandishspear = skill_brandishspear; + skill->repairweapon = skill_repairweapon; + skill->identify = skill_identify; + skill->weaponrefine = skill_weaponrefine; + skill->autospell = skill_autospell; + skill->calc_heal = skill_calc_heal; + skill->check_cloaking = skill_check_cloaking; + skill->enchant_elemental_end = skill_enchant_elemental_end; + skill->not_ok = skillnotok; + skill->not_ok_hom = skillnotok_hom; + skill->not_ok_mercenary = skillnotok_mercenary; + skill->chastle_mob_changetarget = skill_chastle_mob_changetarget; + skill->can_produce_mix = skill_can_produce_mix; + skill->produce_mix = skill_produce_mix; + skill->arrow_create = skill_arrow_create; + skill->castend_nodamage_id = skill_castend_nodamage_id; + skill->castend_damage_id = skill_castend_damage_id; + skill->castend_pos2 = skill_castend_pos2; + skill->blockpc_start = skill_blockpc_start_; + skill->blockhomun_start = skill_blockhomun_start; + skill->blockmerc_start = skill_blockmerc_start; + skill->attack = skill_attack; + skill->attack_area = skill_attack_area; + skill->area_sub = skill_area_sub; + skill->area_sub_count = skill_area_sub_count; + skill->check_unit_range = skill_check_unit_range; + skill->check_unit_range_sub = skill_check_unit_range_sub; + skill->check_unit_range2 = skill_check_unit_range2; + skill->check_unit_range2_sub = skill_check_unit_range2_sub; + skill->toggle_magicpower = skill_toggle_magicpower; + skill->magic_reflect = skill_magic_reflect; + skill->onskillusage = skill_onskillusage; + skill->cell_overlap = skill_cell_overlap; + skill->timerskill = skill_timerskill; + skill->trap_splash = skill_trap_splash; + skill->check_condition_mercenary = skill_check_condition_mercenary; + skill->locate_element_field = skill_locate_element_field; + skill->graffitiremover = skill_graffitiremover; + skill->activate_reverberation = skill_activate_reverbetion; + skill->dance_overlap = skill_dance_overlap; + skill->dance_overlap_sub = skill_dance_overlap_sub; + skill->get_unit_layout = skill_get_unit_layout; + skill->frostjoke_scream = skill_frostjoke_scream; + skill->greed = skill_greed; + skill->destroy_trap = skill_destroy_trap; + skill->icewall_block = skill_icewall_block; + skill->unitgrouptickset_search = skill_unitgrouptickset_search; + skill->dance_switch = skill_dance_switch; + skill->check_condition_char_sub = skill_check_condition_char_sub; + skill->check_condition_mob_master_sub = skill_check_condition_mob_master_sub; + skill->brandishspear_first = skill_brandishspear_first; + skill->brandishspear_dir = skill_brandishspear_dir; +#ifdef RENEWAL_CAST + skill->get_fixed_cast = skill_get_fixed_cast; +#endif + skill->sit_count = skill_sit_count; + skill->sit_in = skill_sit_in; + skill->sit_out = skill_sit_out; + skill->unitsetmapcell = skill_unitsetmapcell; + skill->unit_onplace_timer = skill_unit_onplace_timer; + skill->unit_effect = skill_unit_effect; + skill->unit_timer_sub_onplace = skill_unit_timer_sub_onplace; + skill->unit_move_sub = skill_unit_move_sub; + skill->blockpc_end = skill_blockpc_end; + skill->blockhomun_end = skill_blockhomun_end; + skill->blockmerc_end = skill_blockmerc_end; + skill->split_atoi = skill_split_atoi; + skill->unit_timer = skill_unit_timer; + skill->unit_timer_sub = skill_unit_timer_sub; + skill->init_unit_layout = skill_init_unit_layout; + skill->parse_row_skilldb = skill_parse_row_skilldb; + skill->parse_row_requiredb = skill_parse_row_requiredb; + skill->parse_row_castdb = skill_parse_row_castdb; + skill->parse_row_castnodexdb = skill_parse_row_castnodexdb; + skill->parse_row_unitdb = skill_parse_row_unitdb; + skill->parse_row_producedb = skill_parse_row_producedb; + skill->parse_row_createarrowdb = skill_parse_row_createarrowdb; + skill->parse_row_abradb = skill_parse_row_abradb; + skill->parse_row_spellbookdb = skill_parse_row_spellbookdb; + skill->parse_row_magicmushroomdb = skill_parse_row_magicmushroomdb; + skill->parse_row_reproducedb = skill_parse_row_reproducedb; + skill->parse_row_improvisedb = skill_parse_row_improvisedb; + skill->parse_row_changematerialdb = skill_parse_row_changematerialdb; + skill->usave_add = skill_usave_add; + skill->usave_trigger = skill_usave_trigger; + skill->cooldown_load = skill_cooldown_load; + skill->spellbook = skill_spellbook; + skill->block_check = skill_block_check; + skill->detonator = skill_detonator; + skill->check_camouflage = skill_check_camouflage; + skill->magicdecoy = skill_magicdecoy; + skill->poisoningweapon = skill_poisoningweapon; + skill->select_menu = skill_select_menu; + skill->elementalanalysis = skill_elementalanalysis; + skill->changematerial = skill_changematerial; + skill->get_elemental_type = skill_get_elemental_type; + +} diff --git a/src/map/skill.h b/src/map/skill.h index dc7499857..553dabd6d 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -1,30 +1,60 @@ -// 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 _SKILL_H_ #define _SKILL_H_ #include "../common/mmo.h" // MAX_SKILL, struct square +#include "../common/db.h" #include "map.h" // struct block_list + +/** + * Declarations + **/ struct map_session_data; struct homun_data; struct skill_unit; struct skill_unit_group; struct status_change_entry; +struct square; +/** + * Defines + **/ #define MAX_SKILL_DB MAX_SKILL #define MAX_SKILL_PRODUCE_DB 270 -#define MAX_PRODUCE_RESOURCE 12 -#define MAX_SKILL_ARROW_DB 150 +#define MAX_PRODUCE_RESOURCE 10 +#define MAX_SKILL_ARROW_DB 140 #define MAX_ARROW_RESOURCE 5 -#define MAX_SKILL_ABRA_DB 350 -#define MAX_SKILL_IMPROVISE_DB 50 +#define MAX_SKILL_ABRA_DB 210 +#define MAX_SKILL_IMPROVISE_DB 30 +#define MAX_SKILL_LEVEL 10 +#define MAX_SKILL_UNIT_LAYOUT 45 +#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit +#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1)) +#define MAX_SKILLTIMERSKILL 15 +#define MAX_SKILLUNITGROUP 25 +#define MAX_SKILL_ITEM_REQUIRE 10 +#define MAX_SKILLUNITGROUPTICKSET 25 + +// (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names) +#define skill_ischangesex(id) ( \ + ((id) >= BD_ADAPTATION && (id) <= DC_SERVICEFORYOU) || ((id) >= CG_ARROWVULCAN && (id) <= CG_MARIONETTE) || \ + ((id) >= CG_LONGINGFREEDOM && (id) <= CG_TAROTCARD) || ((id) >= WA_SWING_DANCE && (id) <= WM_UNLIMITED_HUMMING_VOICE)) -#define MAX_SKILL_LEVEL 100 +#define MAX_SKILL_SPELLBOOK_DB 17 +#define MAX_SKILL_MAGICMUSHROOM_DB 23 + +//Walk intervals at which chase-skills are attempted to be triggered. +#define WALK_SKILL_INTERVAL 5 + +/** + * Enumerations + **/ //Constants to identify the skill's inf value: -enum e_skill_inf -{ +enum e_skill_inf { INF_ATTACK_SKILL = 0x01, INF_GROUND_SKILL = 0x02, INF_SELF_SKILL = 0x04, // Skills casted on self where target is automatically chosen @@ -36,8 +66,7 @@ enum e_skill_inf //Constants to identify a skill's nk value (damage properties) //The NK value applies only to non INF_GROUND_SKILL skills //when determining skill castend function to invoke. -enum e_skill_nk -{ +enum e_skill_nk { NK_NO_DAMAGE = 0x01, NK_SPLASH = 0x02|0x04, // 0x4 = splash & split NK_SPLASHSPLIT = 0x04, @@ -50,8 +79,7 @@ enum e_skill_nk //A skill with 3 would be no damage + splash: area of effect. //Constants to identify a skill's inf2 value. -enum e_skill_inf2 -{ +enum e_skill_inf2 { INF2_QUEST_SKILL = 0x0001, INF2_NPC_SKILL = 0x0002, //NPC skills are those that players can't have in their skill tree. INF2_WEDDING_SKILL = 0x0004, @@ -69,118 +97,15 @@ enum e_skill_inf2 INF2_CHORUS_SKILL = 0x4000, // Chorus skill }; -//Walk intervals at which chase-skills are attempted to be triggered. -#define WALK_SKILL_INTERVAL 5 // Flags passed to skill_attack/skill_area_sub -enum e_skill_display -{ +enum e_skill_display { SD_LEVEL = 0x1000, // skill_attack will send -1 instead of skill level (affects display of some skills) SD_ANIMATION = 0x2000, // skill_attack will use '5' instead of the skill's 'type' (this makes skills show an animation) SD_SPLASH = 0x4000, // skill_area_sub will count targets in skill_area_temp[2] SD_PREAMBLE = 0x8000, // skill_area_sub will transmit a 'magic' damage packet (-30000 dmg) for the first target selected }; -#define MAX_SKILL_ITEM_REQUIRE 10 -struct skill_condition { - int weapon,ammo,ammo_qty,hp,sp,zeny,spiritball,mhp,state; - int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; -}; - -// Database skills - -struct s_skill_db { - char name[NAME_LENGTH]; - char desc[40]; - int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max; - int num[MAX_SKILL_LEVEL]; - int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL]; -#ifdef RENEWAL_CAST - int fixed_cast[MAX_SKILL_LEVEL]; -#endif - int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL]; - int castcancel,cast_def_rate; - int inf2,maxcount[MAX_SKILL_LEVEL],skill_type; - int blewcount[MAX_SKILL_LEVEL]; - int hp[MAX_SKILL_LEVEL],sp[MAX_SKILL_LEVEL],mhp[MAX_SKILL_LEVEL],hp_rate[MAX_SKILL_LEVEL],sp_rate[MAX_SKILL_LEVEL],zeny[MAX_SKILL_LEVEL]; - int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL]; - int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; - int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL]; - int nocast; - int unit_id[2]; - int unit_layout_type[MAX_SKILL_LEVEL]; - int unit_range[MAX_SKILL_LEVEL]; - int unit_interval; - int unit_target; - int unit_flag; -}; -extern struct s_skill_db skill_db[MAX_SKILL_DB]; - -#define MAX_SKILL_UNIT_LAYOUT 50 -#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit -#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1)) -struct s_skill_unit_layout { - int count; - int dx[MAX_SKILL_UNIT_COUNT]; - int dy[MAX_SKILL_UNIT_COUNT]; -}; - -#define MAX_SKILLTIMERSKILL 15 -struct skill_timerskill { - int timer; - int src_id; - int target_id; - int map; - short x,y; - uint16 skill_id,skill_lv; - int type; // a BF_ type (NOTE: some places use this as general-purpose storage...) - int flag; -}; - -#define MAX_SKILLUNITGROUP 25 -struct skill_unit_group { - int src_id; - int party_id; - int guild_id; - int bg_id; - int map; - int target_flag; //Holds BCT_* flag for battle_check_target - int bl_flag; //Holds BL_* flag for map_foreachin* functions - unsigned int tick; - int limit,interval; - - uint16 skill_id,skill_lv; - int val1,val2,val3; - char *valstr; - int unit_id; - int group_id; - int unit_count,alive_count; - int item_id; //store item used. - struct skill_unit *unit; - struct { - unsigned ammo_consume : 1; - unsigned song_dance : 2; //0x1 Song/Dance, 0x2 Ensemble - unsigned guildaura : 1; - } state; -}; - -struct skill_unit { - struct block_list bl; - - struct skill_unit_group *group; - - int limit; - int val1,val2; - short alive,range; -}; - -#define MAX_SKILLUNITGROUPTICKSET 25 -struct skill_unit_group_tickset { - unsigned int tick; - int id; -}; - - enum { UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend' UF_NOREITERATION = 0x0002, // Spell cannot be stacked @@ -197,185 +122,15 @@ enum { UF_RANGEDSINGLEUNIT = 0x2000 // hack for ranged layout, only display center }; -// Create Database item - -struct s_skill_produce_db { - int nameid, trigger; - int req_skill,req_skill_lv,itemlv; - int mat_id[MAX_PRODUCE_RESOURCE],mat_amount[MAX_PRODUCE_RESOURCE]; -}; -extern struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; - -// Creating database arrow - -struct s_skill_arrow_db { - int nameid, trigger; - int cre_id[MAX_ARROW_RESOURCE],cre_amount[MAX_ARROW_RESOURCE]; -}; -extern struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; - -// Abracadabra database - -struct s_skill_abra_db { - uint16 skill_id; - int req_lv; - int per; -}; -extern struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB]; - -extern int enchant_eff[5]; -extern int deluge_eff[5]; - -int do_init_skill(void); -int do_final_skill(void); - //Returns the cast type of the skill: ground cast, castend damage, castend no damage enum { CAST_GROUND, CAST_DAMAGE, CAST_NODAMAGE }; -int skill_get_casttype(uint16 skill_id); //[Skotlex] -// Accessor to the skills database -// -int skill_get_index( uint16 skill_id ); -int skill_get_type( uint16 skill_id ); -int skill_get_hit( uint16 skill_id ); -int skill_get_inf( uint16 skill_id ); -int skill_get_ele( uint16 skill_id , uint16 skill_lv ); -int skill_get_nk( uint16 skill_id ); -int skill_get_max( uint16 skill_id ); -int skill_get_range( uint16 skill_id , uint16 skill_lv ); -int skill_get_range2(struct block_list *bl, uint16 skill_id, uint16 skill_lv); -int skill_get_splash( uint16 skill_id , uint16 skill_lv ); -int skill_get_hp( uint16 skill_id ,uint16 skill_lv ); -int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ); -int skill_get_sp( uint16 skill_id ,uint16 skill_lv ); -int skill_get_state(uint16 skill_id); -int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ); -int skill_get_num( uint16 skill_id ,uint16 skill_lv ); -int skill_get_cast( uint16 skill_id ,uint16 skill_lv ); -int skill_get_delay( uint16 skill_id ,uint16 skill_lv ); -int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ); -int skill_get_time( uint16 skill_id ,uint16 skill_lv ); -int skill_get_time2( uint16 skill_id ,uint16 skill_lv ); -int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ); -int skill_get_castdef( uint16 skill_id ); -int skill_get_weapontype( uint16 skill_id ); -int skill_get_ammotype( uint16 skill_id ); -int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ); -int skill_get_nocast( uint16 skill_id ); -int skill_get_unit_id(uint16 skill_id,int flag); -int skill_get_inf2( uint16 skill_id ); -int skill_get_castcancel( uint16 skill_id ); -int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ); -int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ); -int skill_get_unit_flag( uint16 skill_id ); -int skill_get_unit_target( uint16 skill_id ); -int skill_tree_get_max( uint16 skill_id, int b_class ); // Celest -const char* skill_get_name( uint16 skill_id ); // [Skotlex] -const char* skill_get_desc( uint16 skill_id ); // [Skotlex] - -int skill_name2id(const char* name); - -int skill_isammotype(struct map_session_data *sd, int skill); -int skill_castend_id(int tid, unsigned int tick, int id, intptr_t data); -int skill_castend_pos(int tid, unsigned int tick, int id, intptr_t data); -int skill_castend_map( struct map_session_data *sd,uint16 skill_id, const char *map); - -int skill_cleartimerskill(struct block_list *src); -int skill_addtimerskill(struct block_list *src,unsigned int tick,int target,int x,int y,uint16 skill_id,uint16 skill_lv,int type,int flag); - -// Results? Added -int skill_additional_effect( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,int dmg_lv,unsigned int tick); -int skill_counter_additional_effect( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,unsigned int tick); -int skill_blown(struct block_list* src, struct block_list* target, int count, int8 dir, int flag); -int skill_break_equip(struct block_list *bl, unsigned short where, int rate, int flag); -int skill_strip_equip(struct block_list *bl, unsigned short where, int rate, int lv, int time); -// Skills unit -struct skill_unit_group* skill_id2group(int group_id); -struct skill_unit_group *skill_unitsetting(struct block_list* src, uint16 skill_id, uint16 skill_lv, short x, short y, int flag); -struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2); -int skill_delunit(struct skill_unit *unit); -struct skill_unit_group *skill_initunitgroup(struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval); -int skill_delunitgroup_(struct skill_unit_group *group, const char* file, int line, const char* func); -#define skill_delunitgroup(group) skill_delunitgroup_(group,__FILE__,__LINE__,__func__) -int skill_clear_unitgroup(struct block_list *src); -int skill_clear_group(struct block_list *bl, int flag); -void ext_skill_unit_onplace(struct skill_unit *src, struct block_list *bl, unsigned int tick); - -int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl,int damage,unsigned int tick); - -int skill_castfix( struct block_list *bl, uint16 skill_id, uint16 skill_lv); -int skill_castfix_sc( struct block_list *bl, int time); -#ifdef RENEWAL_CAST -int skill_vfcastfix( struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv); -#endif -int skill_delayfix( struct block_list *bl, uint16 skill_id, uint16 skill_lv); - -// Skill conditions check and remove [Inkfish] -int skill_check_condition_castbegin(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); -int skill_check_condition_castend(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); -int skill_consume_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type); -struct skill_condition skill_get_requirement(struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); - -int skill_check_pc_partner(struct map_session_data *sd, uint16 skill_id, short* skill_lv, int range, int cast_flag); -// -- moonsoul (added skill_check_unit_cell) -int skill_check_unit_cell(uint16 skill_id,int16 m,int16 x,int16 y,int unit_id); -int skill_unit_out_all( struct block_list *bl,unsigned int tick,int range); -int skill_unit_move(struct block_list *bl,unsigned int tick,int flag); -int skill_unit_move_unit_group( struct skill_unit_group *group, int16 m,int16 dx,int16 dy); - -struct skill_unit_group *skill_check_dancing( struct block_list *src ); - -// Guild skills [celest] -int skill_guildaura_sub (struct map_session_data* sd, int id, int strvit, int agidex); - -// Chant canceled -int skill_castcancel(struct block_list *bl,int type); - -int skill_sit (struct map_session_data *sd, int type); -void skill_brandishspear(struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag); -void skill_repairweapon(struct map_session_data *sd, int idx); -void skill_identify(struct map_session_data *sd,int idx); -void skill_weaponrefine(struct map_session_data *sd,int idx); // [Celest] -int skill_autospell(struct map_session_data *md,uint16 skill_id); - -int skill_calc_heal(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal); - -bool skill_check_cloaking(struct block_list *bl, struct status_change_entry *sce); - -// Abnormal status -int skill_enchant_elemental_end(struct block_list *bl, int type); -int skillnotok(uint16 skill_id, struct map_session_data *sd); -int skillnotok_hom(uint16 skill_id, struct homun_data *hd); -int skillnotok_mercenary(uint16 skill_id, struct mercenary_data *md); - -int skill_chastle_mob_changetarget(struct block_list *bl,va_list ap); - -// Item creation -int skill_can_produce_mix( struct map_session_data *sd, int nameid, int trigger, int qty); -int skill_produce_mix( struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty ); - -int skill_arrow_create( struct map_session_data *sd,int nameid); - -// skills for the mob -int skill_castend_nodamage_id( struct block_list *src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); -int skill_castend_damage_id( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); -int skill_castend_pos2( struct block_list *src, int x,int y,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag); - -int skill_blockpc_start_(struct map_session_data*, uint16 skill_id, int, bool); -int skill_blockhomun_start (struct homun_data*,uint16 skill_id,int); -int skill_blockmerc_start (struct mercenary_data*,uint16 skill_id,int); - -#define skill_blockpc_start(sd, skill_id, tick) skill_blockpc_start_( sd, skill_id, tick, false ) - -// (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names) -#define skill_ischangesex(id) ( \ - ((id) >= BD_ADAPTATION && (id) <= DC_SERVICEFORYOU) || ((id) >= CG_ARROWVULCAN && (id) <= CG_MARIONETTE) || \ - ((id) >= CG_LONGINGFREEDOM && (id) <= CG_TAROTCARD) || ((id) >= WA_SWING_DANCE && (id) <= WM_UNLIMITED_HUMMING_VOICE)) - -// Skill action, (return dmg,heal) -int skill_attack( int attack_type, struct block_list* src, struct block_list *dsrc,struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); - -void skill_reload(void); +enum wl_spheres { + WLS_FIRE = 0x44, + WLS_WIND, + WLS_WATER, + WLS_STONE, +}; enum { ST_NONE, @@ -392,9 +147,6 @@ enum { ST_RECOV_WEIGHT_RATE, ST_MOVE_ENABLE, ST_WATER, - /** - * 3rd States - **/ ST_RIDINGDRAGON, ST_WUG, ST_RIDINGWUG, @@ -404,11 +156,12 @@ enum { ST_ROLLINGCUTTER, ST_MH_FIGHTING, ST_MH_GRAPPLING, + ST_PECO, }; enum e_skill { NV_BASIC = 1, - + SM_SWORD, SM_TWOHAND, SM_RECOVERY, @@ -416,7 +169,7 @@ enum e_skill { SM_PROVOKE, SM_MAGNUM, SM_ENDURE, - + MG_SRECOVERY, MG_SIGHT, MG_NAPALMBEAT, @@ -430,7 +183,7 @@ enum e_skill { MG_FIREBOLT, MG_LIGHTNINGBOLT, MG_THUNDERSTORM, - + AL_DP, AL_DEMONBANE, AL_RUWACH, @@ -445,7 +198,7 @@ enum e_skill { AL_ANGELUS, AL_BLESSING, AL_CURE, - + MC_INCCARRY, MC_DISCOUNT, MC_OVERCHARGE, @@ -453,22 +206,22 @@ enum e_skill { MC_IDENTIFY, MC_VENDING, MC_MAMMONITE, - + AC_OWL, AC_VULTURE, AC_CONCENTRATION, AC_DOUBLE, AC_SHOWER, - + TF_DOUBLE, TF_MISS, TF_STEAL, TF_HIDING, TF_POISON, TF_DETOXIFY, - + ALL_RESURRECTION, - + KN_SPEARMASTERY, KN_PIERCE, KN_BRANDISHSPEAR, @@ -479,7 +232,7 @@ enum e_skill { KN_BOWLINGBASH, KN_RIDING, KN_CAVALIERMASTERY, - + PR_MACEMASTERY, PR_IMPOSITIO, PR_SUFFRAGIUM, @@ -495,7 +248,7 @@ enum e_skill { PR_TURNUNDEAD, PR_LEXAETERNA, PR_MAGNUS, - + WZ_FIREPILLAR, WZ_SIGHTRASHER, WZ_FIREIVY, @@ -510,7 +263,7 @@ enum e_skill { WZ_HEAVENDRIVE, WZ_QUAGMIRE, WZ_ESTIMATION, - + BS_IRON, BS_STEEL, BS_ENCHANTEDSTONE, @@ -532,7 +285,7 @@ enum e_skill { BS_WEAPONPERFECT, BS_OVERTHRUST, BS_MAXIMIZE, - + HT_SKIDTRAP, HT_LANDMINE, HT_ANKLESNARE, @@ -550,7 +303,7 @@ enum e_skill { HT_BLITZBEAT, HT_DETECTING, HT_SPRINGTRAP, - + AS_RIGHT, AS_LEFT, AS_KATAR, @@ -561,7 +314,7 @@ enum e_skill { AS_POISONREACT, AS_VENOMDUST, AS_SPLASHER, - + NV_FIRSTAID, NV_TRICKDEAD, SM_MOVINGRECOVERY, @@ -578,7 +331,7 @@ enum e_skill { MC_LOUD, AL_HOLYLIGHT, MG_ENERGYCOAT, - + NPC_PIERCINGATT, NPC_MENTALBREAKER, NPC_RANGEATTACK, @@ -631,7 +384,7 @@ enum e_skill { NPC_HALLUCINATION, NPC_REBIRTH, NPC_SUMMONMONSTER, - + RG_SNATCHER, RG_STEALCOIN, RG_BACKSTAP, @@ -648,7 +401,7 @@ enum e_skill { RG_GANGSTER, RG_COMPULSION, RG_PLAGIARISM, - + AM_AXEMASTERY, AM_LEARNINGPOTION, AM_PHARMACY, @@ -671,7 +424,7 @@ enum e_skill { AM_DRILLMASTER, AM_HEALHOMUN, AM_RESURRECTHOMUN, - + CR_TRUST, CR_AUTOGUARD, CR_SHIELDCHARGE, @@ -683,7 +436,7 @@ enum e_skill { CR_PROVIDENCE, CR_DEFENDER, CR_SPEARQUICKEN, - + MO_IRONHAND, MO_SPIRITSRECOVERY, MO_CALLSPIRITS, @@ -699,7 +452,7 @@ enum e_skill { MO_EXTREMITYFIST, MO_CHAINCOMBO, MO_COMBOFINISH, - + SA_ADVANCEDBOOK, SA_CASTCANCEL, SA_MAGICROD, @@ -730,7 +483,7 @@ enum e_skill { SA_INSTANTDEATH, SA_FULLRECOVERY, SA_COMA, - + BD_ADAPTATION, BD_ENCORE, BD_LULLABY, @@ -742,7 +495,7 @@ enum e_skill { BD_INTOABYSS, BD_SIEGFRIED, BD_RAGNAROK, - + BA_MUSICALLESSON, BA_MUSICALSTRIKE, BA_DISSONANCE, @@ -751,7 +504,7 @@ enum e_skill { BA_ASSASSINCROSS, BA_POEMBRAGI, BA_APPLEIDUN, - + DC_DANCINGLESSON, DC_THROWARROW, DC_UGLYDANCE, @@ -760,17 +513,17 @@ enum e_skill { DC_DONTFORGETME, DC_FORTUNEKISS, DC_SERVICEFORYOU, - + NPC_RANDOMMOVE, NPC_SPEEDUP, NPC_REVENGE, - + WE_MALE, WE_FEMALE, WE_CALLPARTNER, - + ITM_TOMAHAWK, - + NPC_DARKCROSS, NPC_GRANDDARKNESS, NPC_DARKSTRIKE, @@ -788,7 +541,7 @@ enum e_skill { NPC_CALLSLAVE, NPC_INVISIBLE, NPC_RUN, - + LK_AURABLADE, LK_PARRYING, LK_CONCENTRATION, @@ -845,7 +598,7 @@ enum e_skill { WE_BABY, WE_CALLPARENT, WE_CALLBABY, - + TK_RUN, TK_READYSTORM, TK_STORMKICK, @@ -862,7 +615,7 @@ enum e_skill { TK_POWER, TK_SEVENWIND, TK_HIGHJUMP, - + SG_FEEL, SG_SUN_WARM, SG_MOON_WARM, @@ -881,7 +634,7 @@ enum e_skill { SG_FRIEND, SG_KNOWLEDGE, SG_FUSION, - + SL_ALCHEMIST, AM_BERSERKPITCHER, SL_MONK, @@ -910,7 +663,7 @@ enum e_skill { SL_SWOO, SL_SKE, SL_SKA, - + SM_SELFPROVOKE, NPC_EMOTION_ON, ST_PRESERVE, @@ -938,7 +691,7 @@ enum e_skill { AM_TWILIGHT2, AM_TWILIGHT3, HT_POWER, - + GS_GLITTERING, GS_FLING, GS_TRIPLEACTION, @@ -961,7 +714,7 @@ enum e_skill { GS_FULLBUSTER, GS_SPREADATTACK, GS_GROUNDDRIFT, - + NJ_TOBIDOUGU, NJ_SYURIKEN, NJ_KUNAI, @@ -985,7 +738,7 @@ enum e_skill { NJ_KAMAITACHI, NJ_NEN, NJ_ISSEN, - + MB_FIGHTING, MB_NEUTRAL, MB_TAIMING_PUTI, @@ -1013,7 +766,7 @@ enum e_skill { MB_M_WALLCRASH, MB_M_REINCARNATION, MB_B_EQUIP, - + SL_DEATHKNIGHT, SL_COLLECTOR, SL_NINJA, @@ -1022,7 +775,7 @@ enum e_skill { DA_RESET, DE_BERSERKAIZER, DA_DARKPOWER, - + DE_PASSIVE, DE_PATTACK, DE_PSPEED, @@ -1062,7 +815,7 @@ enum e_skill { DE_TWINATTACK, DE_WINDATTACK, DE_WATERATTACK, - + DA_ENERGY, DA_CLOUD, DA_FIRSTSLOT, @@ -1097,7 +850,7 @@ enum e_skill { ALL_TIMEIN, DA_ZENYRANK, DA_ACCESSORYMIX, - + NPC_EARTHQUAKE, NPC_FIREBREATH, NPC_ICEBREATH, @@ -1126,7 +879,7 @@ enum e_skill { NPC_WIDESTUN, NPC_VAMPIRE_GIFT, NPC_WIDESOULDRAIN, - + ALL_INCCARRY, NPC_TALK, NPC_HELLPOWER, @@ -1155,7 +908,7 @@ enum e_skill { NPC_VENOMFOG, NPC_MILLENNIUMSHIELD, NPC_COMET, - + KN_CHARGEATK = 1001, CR_SHRINK, AS_SONICACCEL, @@ -1175,7 +928,7 @@ enum e_skill { SA_ELEMENTGROUND, SA_ELEMENTFIRE, SA_ELEMENTWIND, - + RK_ENCHANTBLADE = 2001, RK_SONICWAVE, RK_DEATHBOUND, @@ -1196,7 +949,7 @@ enum e_skill { RK_FIGHTINGSPIRIT, RK_ABUNDANCE, RK_PHANTOMTHRUST, - + GC_VENOMIMPRESS, GC_CROSSIMPACT, GC_DARKILLUSION, @@ -1214,7 +967,7 @@ enum e_skill { GC_HALLUCINATIONWALK, GC_ROLLINGCUTTER, GC_CROSSRIPPERSLASHER, - + AB_JUDEX, AB_ANCILLA, AB_ADORAMUS, @@ -1235,7 +988,7 @@ enum e_skill { AB_DUPLELIGHT_MELEE, AB_DUPLELIGHT_MAGIC, AB_SILENTIUM, - + WL_WHITEIMPRISON = 2201, WL_SOULEXPANSION, WL_FROSTMISTY, @@ -1268,7 +1021,7 @@ enum e_skill { WL_RELEASE, WL_READING_SB, WL_FREEZE_SP, - + RA_ARROWSTORM, RA_FEARBREEZE, RA_RANGERMAIN, @@ -1291,7 +1044,7 @@ enum e_skill { RA_VERDURETRAP, RA_FIRINGTRAP, RA_ICEBOUNDTRAP, - + NC_MADOLICENCE, NC_BOOSTKNUCKLE, NC_PILEBUNKER, @@ -1321,7 +1074,7 @@ enum e_skill { NC_SILVERSNIPER, NC_MAGICDECOY, NC_DISJOINT, - + SC_FATALMENACE, SC_REPRODUCE, SC_AUTOSHADOWSPELL, @@ -1343,7 +1096,7 @@ enum e_skill { SC_MAELSTROM, SC_BLOODYLUST, SC_FEINTBOMB, - + LG_CANNONSPEAR = 2307, LG_BANISHINGPOINT, LG_TRAMPLE, @@ -1363,7 +1116,7 @@ enum e_skill { LG_EARTHDRIVE, LG_HESPERUSLIT, LG_INSPIRATION, - + SR_DRAGONCOMBO, SR_SKYNETBLOW, SR_EARTHSHAKER, @@ -1387,15 +1140,15 @@ enum e_skill { SR_GENTLETOUCH_ENERGYGAIN, SR_GENTLETOUCH_CHANGE, SR_GENTLETOUCH_REVITALIZE, - + WA_SWING_DANCE = 2350, WA_SYMPHONY_OF_LOVER, WA_MOONLIT_SERENADE, - + MI_RUSH_WINDMILL = 2381, MI_ECHOSONG, MI_HARMONIZE, - + WM_LESSON = 2412, WM_METALICSOUND, WM_REVERBERATION, @@ -1419,7 +1172,7 @@ enum e_skill { WM_MELODYOFSINK, WM_BEYOND_OF_WARCRY, WM_UNLIMITED_HUMMING_VOICE, - + SO_FIREWALK = 2443, SO_ELECTRICWALK, SO_SPELLFIST, @@ -1446,7 +1199,7 @@ enum e_skill { SO_WATER_INSIGNIA, SO_WIND_INSIGNIA, SO_EARTH_INSIGNIA, - + GN_TRAINING_SWORD = 2474, GN_REMODELING_CART, GN_CART_TORNADO, @@ -1472,14 +1225,14 @@ enum e_skill { GN_MAKEBOMB, GN_S_PHARMACY, GN_SLINGITEM_RANGEMELEEATK, - + AB_SECRAMENT = 2515, WM_SEVERE_RAINSTORM_MELEE, SR_HOWLINGOFLION, SR_RIDEINLIGHTNING, LG_OVERBRAND_BRANDISH, LG_OVERBRAND_PLUSATK, - + ALL_ODINS_RECALL = 2533, RETURN_TO_ELDICASTES, ALL_BUYING_STORE, @@ -1492,7 +1245,7 @@ enum e_skill { ALL_TETANY, ALL_RAY_OF_PROTECTION, MC_CARTDECORATE, - + KO_YAMIKUMO = 3001, KO_RIGHT, KO_LEFT, @@ -1522,13 +1275,13 @@ enum e_skill { OB_OBOROGENSOU, OB_OBOROGENSOU_TRANSITION_ATK, OB_AKAITSUKI, - + ECL_SNOWFLIP = 3031, ECL_PEONYMAMY, ECL_SADAGUI, ECL_SEQUOIADUST, ECLAGE_RECALL, - + HLIF_HEAL = 8001, HLIF_AVOID, HLIF_BRAIN, @@ -1572,7 +1325,7 @@ enum e_skill { MH_LAVA_SLIDE, MH_PYROCLASTIC, MH_VOLCANIC_ASH, - + MS_BASH = 8201, MS_MAGNUM, MS_BOWLINGBASH, @@ -1613,7 +1366,7 @@ enum e_skill { MER_KYRIE, MER_BLESSING, MER_INCAGI, - + EL_CIRCLE_OF_FIRE = 8401, EL_FIRE_CLOAK, EL_FIRE_MANTLE, @@ -1788,7 +1541,7 @@ enum { UNT_ZENKAI_WIND, UNT_MAKIBISHI, UNT_VENOMFOG, - + /** * Guild Auras **/ @@ -1796,51 +1549,10 @@ enum { UNT_GD_GLORYWOUNDS = 0xc2, UNT_GD_SOULCOLD = 0xc3, UNT_GD_HAWKEYES = 0xc4, - + UNT_MAX = 0x190 }; -/** - * Skill Unit Save - **/ -void skill_usave_add(struct map_session_data * sd, uint16 skill_id, uint16 skill_lv); -void skill_usave_trigger(struct map_session_data *sd); -/** - * Skill Cool Downs - load from pc.c when the character logs in - **/ -void skill_cooldown_load(struct map_session_data * sd); -/** - * Warlock - **/ -#define MAX_SKILL_SPELLBOOK_DB 17 -enum wl_spheres { - WLS_FIRE = 0x44, - WLS_WIND, - WLS_WATER, - WLS_STONE, -}; -int skill_spellbook (struct map_session_data *sd, int nameid); -int skill_block_check(struct block_list *bl, enum sc_type type, uint16 skill_id); -/** - * Guilottine Cross - **/ -#define MAX_SKILL_MAGICMUSHROOM_DB 23 -struct s_skill_magicmushroom_db { - uint16 skill_id; -}; -extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; -/** - * Ranger - **/ -int skill_detonator(struct block_list *bl, va_list ap); -bool skill_check_camouflage(struct block_list *bl, struct status_change_entry *sce); -/** - * Mechanic - **/ -int skill_magicdecoy(struct map_session_data *sd, int nameid); -/** - * Guiltoine Cross - **/ -int skill_poisoningweapon( struct map_session_data *sd, int nameid); + enum gx_poison { PO_PARALYSE = 12717, PO_LEECHESEND, @@ -1851,13 +1563,340 @@ enum gx_poison { PO_MAGICMUSHROOM, PO_VENOMBLEED }; + +/** + * Structures + **/ + +struct skill_condition { + int weapon,ammo,ammo_qty,hp,sp,zeny,spiritball,mhp,state; + int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; +}; + +// Database skills +struct s_skill_db { + unsigned short nameid; + char name[NAME_LENGTH]; + char desc[40]; + int range[MAX_SKILL_LEVEL],hit,inf,element[MAX_SKILL_LEVEL],nk,splash[MAX_SKILL_LEVEL],max; + int num[MAX_SKILL_LEVEL]; + int cast[MAX_SKILL_LEVEL],walkdelay[MAX_SKILL_LEVEL],delay[MAX_SKILL_LEVEL]; +#ifdef RENEWAL_CAST + int fixed_cast[MAX_SKILL_LEVEL]; +#endif + int upkeep_time[MAX_SKILL_LEVEL],upkeep_time2[MAX_SKILL_LEVEL],cooldown[MAX_SKILL_LEVEL]; + int castcancel,cast_def_rate; + int inf2,maxcount[MAX_SKILL_LEVEL],skill_type; + int blewcount[MAX_SKILL_LEVEL]; + int hp[MAX_SKILL_LEVEL],sp[MAX_SKILL_LEVEL],mhp[MAX_SKILL_LEVEL],hp_rate[MAX_SKILL_LEVEL],sp_rate[MAX_SKILL_LEVEL],zeny[MAX_SKILL_LEVEL]; + int weapon,ammo,ammo_qty[MAX_SKILL_LEVEL],state,spiritball[MAX_SKILL_LEVEL]; + int itemid[MAX_SKILL_ITEM_REQUIRE],amount[MAX_SKILL_ITEM_REQUIRE]; + int castnodex[MAX_SKILL_LEVEL], delaynodex[MAX_SKILL_LEVEL]; + int nocast; + int unit_id[2]; + int unit_layout_type[MAX_SKILL_LEVEL]; + int unit_range[MAX_SKILL_LEVEL]; + int unit_interval; + int unit_target; + int unit_flag; +}; +extern struct s_skill_db skill_db[MAX_SKILL_DB]; + +struct s_skill_unit_layout { + int count; + int dx[MAX_SKILL_UNIT_COUNT]; + int dy[MAX_SKILL_UNIT_COUNT]; +}; + +struct skill_timerskill { + int timer; + int src_id; + int target_id; + int map; + short x,y; + uint16 skill_id,skill_lv; + int type; // a BF_ type (NOTE: some places use this as general-purpose storage...) + int flag; +}; + +struct skill_unit_group { + int src_id; + int party_id; + int guild_id; + int bg_id; + int map; + int target_flag; //Holds BCT_* flag for battle_check_target + int bl_flag; //Holds BL_* flag for map_foreachin* functions + unsigned int tick; + int limit,interval; + + uint16 skill_id,skill_lv; + int val1,val2,val3; + char *valstr; + int unit_id; + int group_id; + int unit_count,alive_count; + int item_id; //store item used. + struct skill_unit *unit; + struct { + unsigned ammo_consume : 1; + unsigned song_dance : 2; //0x1 Song/Dance, 0x2 Ensemble + unsigned guildaura : 1; + } state; +}; + +struct skill_unit { + struct block_list bl; + + struct skill_unit_group *group; + + int limit; + int val1,val2; + short alive,range; +}; + +struct skill_unit_group_tickset { + unsigned int tick; + int id; +}; + +// Create Database item +struct s_skill_produce_db { + int nameid, trigger; + int req_skill,req_skill_lv,itemlv; + int mat_id[MAX_PRODUCE_RESOURCE],mat_amount[MAX_PRODUCE_RESOURCE]; +}; +extern struct s_skill_produce_db skill_produce_db[MAX_SKILL_PRODUCE_DB]; + +// Creating database arrow +struct s_skill_arrow_db { + int nameid, trigger; + int cre_id[MAX_ARROW_RESOURCE],cre_amount[MAX_ARROW_RESOURCE]; +}; +extern struct s_skill_arrow_db skill_arrow_db[MAX_SKILL_ARROW_DB]; + +// Abracadabra database +struct s_skill_abra_db { + uint16 skill_id; + int req_lv; + int per; +}; +extern struct s_skill_abra_db skill_abra_db[MAX_SKILL_ABRA_DB]; + +//GCross magic mushroom database +struct s_skill_magicmushroom_db { + uint16 skill_id; +}; +extern struct s_skill_magicmushroom_db skill_magicmushroom_db[MAX_SKILL_MAGICMUSHROOM_DB]; + /** - * Auto Shadow Spell (Shadow Chaser) + * Vars **/ -int skill_select_menu(struct map_session_data *sd,uint16 skill_id); +extern int enchant_eff[5]; +extern int deluge_eff[5]; +DBMap* skilldb_name2id; -int skill_elementalanalysis(struct map_session_data *sd, int n, uint16 skill_lv, unsigned short *item_list); // Sorcerer Four Elemental Analisys. -int skill_changematerial(struct map_session_data *sd, int n, unsigned short *item_list); // Genetic Change Material. -int skill_get_elemental_type(uint16 skill_id, uint16 skill_lv); +/** + * Skill.c Interface + **/ +struct skill_interface { + int (*init) (void); + int (*final) (void); + void (*reload) (void); + void (*read_db) (void); + /* accesssors */ + int (*get_index) ( uint16 skill_id ); + int (*get_type) ( uint16 skill_id ); + int (*get_hit) ( uint16 skill_id ); + int (*get_inf) ( uint16 skill_id ); + int (*get_ele) ( uint16 skill_id, uint16 skill_lv ); + int (*get_nk) ( uint16 skill_id ); + int (*get_max) ( uint16 skill_id ); + int (*get_range) ( uint16 skill_id, uint16 skill_lv ); + int (*get_range2) (struct block_list *bl, uint16 skill_id, uint16 skill_lv); + int (*get_splash) ( uint16 skill_id, uint16 skill_lv ); + int (*get_hp) ( uint16 skill_id, uint16 skill_lv ); + int (*get_mhp) ( uint16 skill_id, uint16 skill_lv ); + int (*get_sp) ( uint16 skill_id, uint16 skill_lv ); + int (*get_state) (uint16 skill_id); + int (*get_spiritball) (uint16 skill_id, uint16 skill_lv); + int (*get_zeny) ( uint16 skill_id, uint16 skill_lv ); + int (*get_num) ( uint16 skill_id, uint16 skill_lv ); + int (*get_cast) ( uint16 skill_id, uint16 skill_lv ); + int (*get_delay) ( uint16 skill_id, uint16 skill_lv ); + int (*get_walkdelay) ( uint16 skill_id, uint16 skill_lv ); + int (*get_time) ( uint16 skill_id, uint16 skill_lv ); + int (*get_time2) ( uint16 skill_id, uint16 skill_lv ); + int (*get_castnodex) ( uint16 skill_id, uint16 skill_lv ); + int (*get_delaynodex) ( uint16 skill_id ,uint16 skill_lv ); + int (*get_castdef) ( uint16 skill_id ); + int (*get_weapontype) ( uint16 skill_id ); + int (*get_ammotype) ( uint16 skill_id ); + int (*get_ammo_qty) ( uint16 skill_id, uint16 skill_lv ); + int (*get_unit_id) (uint16 skill_id,int flag); + int (*get_inf2) ( uint16 skill_id ); + int (*get_castcancel) ( uint16 skill_id ); + int (*get_maxcount) ( uint16 skill_id, uint16 skill_lv ); + int (*get_blewcount) ( uint16 skill_id, uint16 skill_lv ); + int (*get_unit_flag) ( uint16 skill_id ); + int (*get_unit_target) ( uint16 skill_id ); + int (*get_unit_interval) ( uint16 skill_id ); + int (*get_unit_bl_target) ( uint16 skill_id ); + int (*get_unit_layout_type) ( uint16 skill_id ,uint16 skill_lv ); + int (*get_unit_range) ( uint16 skill_id, uint16 skill_lv ); + int (*get_cooldown) ( uint16 skill_id, uint16 skill_lv ); + int (*tree_get_max) ( uint16 skill_id, int b_class ); + const char* (*get_name) ( uint16 skill_id ); + const char* (*get_desc) ( uint16 skill_id ); + /* check */ + void (*chk) (int16* skill_id); + /* whether its CAST_GROUND, CAST_DAMAGE or CAST_NODAMAGE */ + int (*get_casttype) (uint16 skill_id); + int (*get_casttype2) (uint16 index); + int (*name2id) (const char* name); + int (*isammotype) (struct map_session_data *sd, int skill); + int (*castend_id) (int tid, unsigned int tick, int id, intptr_t data); + int (*castend_pos) (int tid, unsigned int tick, int id, intptr_t data); + int (*castend_map) ( struct map_session_data *sd,uint16 skill_id, const char *map); + int (*cleartimerskill) (struct block_list *src); + int (*addtimerskill) (struct block_list *src,unsigned int tick,int target,int x,int y,uint16 skill_id,uint16 skill_lv,int type,int flag); + int (*additional_effect) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,int dmg_lv,unsigned int tick); + int (*counter_additional_effect) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,int attack_type,unsigned int tick); + int (*blown) (struct block_list* src, struct block_list* target, int count, int8 dir, int flag); + int (*break_equip) (struct block_list *bl, unsigned short where, int rate, int flag); + int (*strip_equip) (struct block_list *bl, unsigned short where, int rate, int lv, int time); + struct skill_unit_group* (*id2group) (int group_id); + struct skill_unit_group *(*unitsetting) (struct block_list* src, uint16 skill_id, uint16 skill_lv, short x, short y, int flag); + struct skill_unit *(*initunit) (struct skill_unit_group *group, int idx, int x, int y, int val1, int val2); + int (*delunit) (struct skill_unit *unit); + struct skill_unit_group *(*init_unitgroup) (struct block_list* src, int count, uint16 skill_id, uint16 skill_lv, int unit_id, int limit, int interval); + int (*del_unitgroup) (struct skill_unit_group *group, const char* file, int line, const char* func); + int (*clear_unitgroup) (struct block_list *src); + int (*clear_group) (struct block_list *bl, int flag); + int (*unit_onplace) (struct skill_unit *src, struct block_list *bl, unsigned int tick); + int (*unit_ondamaged) (struct skill_unit *src,struct block_list *bl,int damage,unsigned int tick); + int (*cast_fix) ( struct block_list *bl, uint16 skill_id, uint16 skill_lv); + int (*cast_fix_sc) ( struct block_list *bl, int time); +#ifdef RENEWAL_CAST + int (*vf_cast_fix) ( struct block_list *bl, double time, uint16 skill_id, uint16 skill_lv); +#endif + int (*delay_fix) ( struct block_list *bl, uint16 skill_id, uint16 skill_lv); + int (*check_condition_castbegin) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); + int (*check_condition_castend) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); + int (*consume_requirement) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv, short type); + struct skill_condition (*get_requirement) (struct map_session_data *sd, uint16 skill_id, uint16 skill_lv); + int (*check_pc_partner) (struct map_session_data *sd, uint16 skill_id, short* skill_lv, int range, int cast_flag); + int (*unit_move) (struct block_list *bl,unsigned int tick,int flag); + int (*unit_onleft) (uint16 skill_id, struct block_list *bl,unsigned int tick); + int (*unit_onout) (struct skill_unit *src, struct block_list *bl, unsigned int tick); + int (*unit_move_unit_group) ( struct skill_unit_group *group, int16 m,int16 dx,int16 dy); + int (*guildaura_sub) (struct map_session_data* sd, int id, int strvit, int agidex); + int (*sit) (struct map_session_data *sd, int type); + void (*brandishspear) (struct block_list* src, struct block_list* bl, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag); + void (*repairweapon) (struct map_session_data *sd, int idx); + void (*identify) (struct map_session_data *sd,int idx); + void (*weaponrefine) (struct map_session_data *sd,int idx); + int (*autospell) (struct map_session_data *md,uint16 skill_id); + int (*calc_heal) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, bool heal); + bool (*check_cloaking) (struct block_list *bl, struct status_change_entry *sce); + int (*enchant_elemental_end) (struct block_list *bl, int type); + int (*not_ok) (uint16 skill_id, struct map_session_data *sd); + int (*not_ok_hom) (uint16 skill_id, struct homun_data *hd); + int (*not_ok_mercenary) (uint16 skill_id, struct mercenary_data *md); + int (*chastle_mob_changetarget) (struct block_list *bl,va_list ap); + int (*can_produce_mix) ( struct map_session_data *sd, int nameid, int trigger, int qty); + int (*produce_mix) ( struct map_session_data *sd, uint16 skill_id, int nameid, int slot1, int slot2, int slot3, int qty ); + int (*arrow_create) ( struct map_session_data *sd,int nameid); + int (*castend_nodamage_id) ( struct block_list *src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); + int (*castend_damage_id) ( struct block_list* src, struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); + int (*castend_pos2) ( struct block_list *src, int x,int y,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag); + int (*blockpc_start) (struct map_session_data*, uint16 skill_id, int, bool); + int (*blockhomun_start) (struct homun_data*,uint16 skill_id,int); + int (*blockmerc_start) (struct mercenary_data*,uint16 skill_id,int); + int (*attack) ( int attack_type, struct block_list* src, struct block_list *dsrc,struct block_list *bl,uint16 skill_id,uint16 skill_lv,unsigned int tick,int flag ); + int (*attack_area) (struct block_list *bl,va_list ap); + int (*area_sub) (struct block_list *bl, va_list ap); + int (*area_sub_count) (struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, unsigned int tick, int flag); + int (*check_unit_range) (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); + int (*check_unit_range_sub) (struct block_list *bl, va_list ap); + int (*check_unit_range2) (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv); + int (*check_unit_range2_sub) (struct block_list *bl, va_list ap); + void (*toggle_magicpower) (struct block_list *bl, uint16 skill_id); + int (*magic_reflect) (struct block_list* src, struct block_list* bl, int type); + int (*onskillusage) (struct map_session_data *sd, struct block_list *bl, uint16 skill_id, unsigned int tick); + int (*cell_overlap) (struct block_list *bl, va_list ap); + int (*timerskill) (int tid, unsigned int tick, int id, intptr_t data); + int (*trap_splash) (struct block_list *bl, va_list ap); + int (*check_condition_mercenary) (struct block_list *bl, int skill_id, int lv, int type); + struct skill_unit_group *(*locate_element_field) (struct block_list *bl); + int (*graffitiremover) (struct block_list *bl, va_list ap); + int (*activate_reverberation) ( struct block_list *bl, va_list ap); + int (*dance_overlap_sub) (struct block_list* bl, va_list ap); + int (*dance_overlap) (struct skill_unit* unit, int flag); + struct s_skill_unit_layout *(*get_unit_layout) (uint16 skill_id, uint16 skill_lv, struct block_list* src, int x, int y); + int (*frostjoke_scream) (struct block_list *bl, va_list ap); + int (*greed) (struct block_list *bl, va_list ap); + int (*destroy_trap) ( struct block_list *bl, va_list ap ); + int (*icewall_block) (struct block_list *bl,va_list ap); + struct skill_unit_group_tickset *(*unitgrouptickset_search) (struct block_list *bl, struct skill_unit_group *group, int tick); + bool (*dance_switch) (struct skill_unit* unit, int flag); + int (*check_condition_char_sub) (struct block_list *bl, va_list ap); + int (*check_condition_mob_master_sub) (struct block_list *bl, va_list ap); + void (*brandishspear_first) (struct square *tc, uint8 dir, int16 x, int16 y); + void (*brandishspear_dir) (struct square* tc, uint8 dir, int are); +#ifdef RENEWAL_CAST + int (*get_fixed_cast) ( uint16 skill_id ,uint16 skill_lv ); +#endif + int (*sit_count) (struct block_list *bl, va_list ap); + int (*sit_in) (struct block_list *bl, va_list ap); + int (*sit_out) (struct block_list *bl, va_list ap); + void (*unitsetmapcell) (struct skill_unit *src, uint16 skill_id, uint16 skill_lv, cell_t cell, bool flag); + int (*unit_onplace_timer) (struct skill_unit *src, struct block_list *bl, unsigned int tick); + int (*unit_effect) (struct block_list* bl, va_list ap); + int (*unit_timer_sub_onplace) (struct block_list* bl, va_list ap); + int (*unit_move_sub) (struct block_list* bl, va_list ap); + int (*blockpc_end) (int tid, unsigned int tick, int id, intptr_t data); + int (*blockhomun_end) (int tid, unsigned int tick, int id, intptr_t data); + int (*blockmerc_end) (int tid, unsigned int tick, int id, intptr_t data); + int (*split_atoi) (char *str, int *val); + int (*unit_timer) (int tid, unsigned int tick, int id, intptr_t data); + int (*unit_timer_sub) (DBKey key, DBData *data, va_list ap); + void (*init_unit_layout) (void); + bool (*parse_row_skilldb) (char* split[], int columns, int current); + bool (*parse_row_requiredb) (char* split[], int columns, int current); + bool (*parse_row_castdb) (char* split[], int columns, int current); + bool (*parse_row_castnodexdb) (char* split[], int columns, int current); + bool (*parse_row_unitdb) (char* split[], int columns, int current); + bool (*parse_row_producedb) (char* split[], int columns, int current); + bool (*parse_row_createarrowdb) (char* split[], int columns, int current); + bool (*parse_row_abradb) (char* split[], int columns, int current); + bool (*parse_row_spellbookdb) (char* split[], int columns, int current); + bool (*parse_row_magicmushroomdb) (char* split[], int column, int current); + bool (*parse_row_reproducedb) (char* split[], int column, int current); + bool (*parse_row_improvisedb) (char* split[], int columns, int current); + bool (*parse_row_changematerialdb) (char* split[], int columns, int current); + /* save new unit skill */ + void (*usave_add) (struct map_session_data * sd, uint16 skill_id, uint16 skill_lv); + /* trigger saved unit skills */ + void (*usave_trigger) (struct map_session_data *sd); + /* load all stored skill cool downs */ + void (*cooldown_load) (struct map_session_data * sd); + /* run spellbook of nameid id */ + int (*spellbook) (struct map_session_data *sd, int nameid); + /* */ + int (*block_check) (struct block_list *bl, enum sc_type type, uint16 skill_id); + int (*detonator) (struct block_list *bl, va_list ap); + bool (*check_camouflage) (struct block_list *bl, struct status_change_entry *sce); + int (*magicdecoy) (struct map_session_data *sd, int nameid); + int (*poisoningweapon) ( struct map_session_data *sd, int nameid); + int (*select_menu) (struct map_session_data *sd,uint16 skill_id); + int (*elementalanalysis) (struct map_session_data *sd, int n, uint16 skill_lv, unsigned short *item_list); + int (*changematerial) (struct map_session_data *sd, int n, unsigned short *item_list); + int (*get_elemental_type) (uint16 skill_id, uint16 skill_lv); +} skill_s; + +struct skill_interface *skill; + +void skill_defaults(void); #endif /* _SKILL_H_ */ diff --git a/src/map/sql/CMakeLists.txt b/src/map/sql/CMakeLists.txt index 47c8e495c..1b2c19979 100644 --- a/src/map/sql/CMakeLists.txt +++ b/src/map/sql/CMakeLists.txt @@ -3,7 +3,7 @@ # map sql # if( BUILD_SQL_SERVERS ) -message( STATUS "Creating target map-server_sql" ) +message( STATUS "Creating target map-server" ) set( SQL_MAP_HEADERS "${SQL_MAP_SOURCE_DIR}/atcommand.h" "${SQL_MAP_SOURCE_DIR}/battle.h" @@ -17,8 +17,9 @@ set( SQL_MAP_HEADERS "${SQL_MAP_SOURCE_DIR}/elemental.h" "${SQL_MAP_SOURCE_DIR}/guild.h" "${SQL_MAP_SOURCE_DIR}/homunculus.h" - "${SQL_MAP_SOURCE_DIR}/instance.h" + "${SQL_MAP_SOURCE_DIR}/instance.h" "${SQL_MAP_SOURCE_DIR}/intif.h" + "${SQL_MAP_SOURCE_DIR}/irc-bot.h" "${SQL_MAP_SOURCE_DIR}/itemdb.h" "${SQL_MAP_SOURCE_DIR}/log.h" "${SQL_MAP_SOURCE_DIR}/mail.h" @@ -27,6 +28,8 @@ set( SQL_MAP_HEADERS "${SQL_MAP_SOURCE_DIR}/mercenary.h" "${SQL_MAP_SOURCE_DIR}/mob.h" "${SQL_MAP_SOURCE_DIR}/npc.h" + "${SQL_MAP_SOURCE_DIR}/packets.h" + "${SQL_MAP_SOURCE_DIR}/packets_struct.h" "${SQL_MAP_SOURCE_DIR}/party.h" "${SQL_MAP_SOURCE_DIR}/path.h" "${SQL_MAP_SOURCE_DIR}/pc.h" @@ -57,6 +60,7 @@ set( SQL_MAP_SOURCES "${SQL_MAP_SOURCE_DIR}/homunculus.c" "${SQL_MAP_SOURCE_DIR}/instance.c" "${SQL_MAP_SOURCE_DIR}/intif.c" + "${SQL_MAP_SOURCE_DIR}/irc-bot.c" "${SQL_MAP_SOURCE_DIR}/itemdb.c" "${SQL_MAP_SOURCE_DIR}/log.c" "${SQL_MAP_SOURCE_DIR}/mail.c" @@ -97,16 +101,16 @@ set( SOURCE_FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ${SQL_MAP_HEADERS source_group( common FILES ${COMMON_BASE_HEADERS} ${COMMON_SQL_HEADERS} ) source_group( map FILES ${SQL_MAP_HEADERS} ${SQL_MAP_SOURCES} ) include_directories( ${INCLUDE_DIRS} ) -add_executable( map-server_sql ${SOURCE_FILES} ) -add_dependencies( map-server_sql ${DEPENDENCIES} ) -target_link_libraries( map-server_sql ${LIBRARIES} ${DEPENDENCIES} ) -set_target_properties( map-server_sql PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) +add_executable( map-server ${SOURCE_FILES} ) +add_dependencies( map-server ${DEPENDENCIES} ) +target_link_libraries( map-server ${LIBRARIES} ${DEPENDENCIES} ) +set_target_properties( map-server PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) if( INSTALL_COMPONENT_RUNTIME ) - cpack_add_component( Runtime_mapserver_sql DESCRIPTION "map-server (sql version)" DISPLAY_NAME "map-server_sql" GROUP Runtime ) - install( TARGETS map-server_sql + cpack_add_component( Runtime_mapserver_sql DESCRIPTION "map-server (sql version)" DISPLAY_NAME "map-server" GROUP Runtime ) + install( TARGETS map-server DESTINATION "." COMPONENT Runtime_mapserver_sql ) endif( INSTALL_COMPONENT_RUNTIME ) -set( TARGET_LIST ${TARGET_LIST} map-server_sql CACHE INTERNAL "" ) -message( STATUS "Creating target map-server_sql - done" ) +set( TARGET_LIST ${TARGET_LIST} map-server CACHE INTERNAL "" ) +message( STATUS "Creating target map-server - done" ) endif( BUILD_SQL_SERVERS ) diff --git a/src/map/status.c b/src/map/status.c index 8a173f611..b7e906910 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1,5 +1,6 @@ -// 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 #include "../common/cbasetypes.h" #include "../common/timer.h" @@ -54,9 +55,9 @@ static int hp_coefficient2[CLASS_COUNT]; static int hp_sigma_val[CLASS_COUNT][MAX_LEVEL+1]; static int sp_coefficient[CLASS_COUNT]; #ifdef RENEWAL_ASPD -static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; + static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE+1]; #else -static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] + static int aspd_base[CLASS_COUNT][MAX_WEAPON_TYPE]; //[blackhole89] #endif // bonus values and upgrade chances for refining equipment @@ -77,23 +78,14 @@ int current_equip_card_id; //To prevent card-stacking (from jA) [Skotlex] //we need it for new cards 15 Feb 2005, to check if the combo cards are insrerted into the CURRENT weapon only //to avoid cards exploits -static sc_type SkillStatusChangeTable[MAX_SKILL]; // skill -> status -static int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) -static unsigned int StatusChangeFlagTable[SC_MAX]; // status -> flags -static int StatusSkillChangeTable[SC_MAX]; // status -> skill -static int StatusRelevantBLTypes[SI_MAX]; // "icon" -> enum bl_type (for clif_status_change to identify for which bl types to send packets) -static unsigned int StatusChangeStateTable[SC_MAX]; // status -> flags - - /** * Returns the status change associated with a skill. * @param skill The skill to look up * @return The status registered for this skill **/ -sc_type status_skill2sc(int skill) -{ - int idx = skill_get_index(skill); - if( idx == 0 ) { +sc_type status_skill2sc(int skill_id) { + int idx; + if( (idx = skill->get_index(skill_id)) == 0 ) { ShowError("status_skill2sc: Unsupported skill id %d\n", skill); return SC_NONE; } @@ -150,10 +142,9 @@ int status_type2relevant_bl_types(int type) // indicates that the status displays a visual effect for the affected unit, and should be sent to the client for all supported units #define set_sc_with_vfx(skill, sc, icon, flag) set_sc((skill), (sc), (icon), (flag)); if((icon) < SI_MAX) StatusRelevantBLTypes[(icon)] |= BL_SCEFFECT -static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) -{ - uint16 idx = skill_get_index(skill_id); - if( idx == 0 ) { +static void set_sc(uint16 skill_id, sc_type sc, int icon, unsigned int flag) { + uint16 idx; + if( (idx = skill->get_index(skill_id)) == 0 ) { ShowError("set_sc: Unsupported skill id %d\n", skill_id); return; } @@ -186,8 +177,7 @@ void initChangeTables(void) { memset(StatusSkillChangeTable, 0, sizeof(StatusSkillChangeTable)); memset(StatusChangeFlagTable, 0, sizeof(StatusChangeFlagTable)); - memset(StatusChangeStateTable, 0, sizeof(StatusChangeStateTable)); - + memset(StatusDisplayType, 0, sizeof(StatusDisplayType)); //First we define the skill for common ailments. These are used in skill_additional_effect through sc cards. [Skotlex] set_sc( NPC_PETRIFYATTACK , SC_STONE , SI_BLANK , SCB_DEF_ELE|SCB_DEF|SCB_MDEF ); @@ -555,7 +545,7 @@ void initChangeTables(void) { set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_REUSE_MILLENNIUMSHIELD , SCB_NONE ); set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE ); set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR ); - set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE ); + set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_DEF|SCB_MDEF ); set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN ); set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD ); set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE ); @@ -907,6 +897,7 @@ void initChangeTables(void) { StatusIconChangeTable[SC_CURSED_SOIL] = SI_CURSED_SOIL; StatusIconChangeTable[SC_UPHEAVAL] = SI_UPHEAVAL; StatusIconChangeTable[SC_PUSH_CART] = SI_ON_PUSH_CART; + StatusIconChangeTable[SC_ALL_RIDING] = SI_ALL_RIDING; //Other SC which are not necessarily associated to skills. StatusChangeFlagTable[SC_ASPDPOTION0] = SCB_ASPD; @@ -988,6 +979,32 @@ void initChangeTables(void) { StatusChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; StatusChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; + StatusChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; + + /* StatusDisplayType Table [Ind/Hercules] */ + StatusDisplayType[SC_ALL_RIDING] = true; + StatusDisplayType[SC_PUSH_CART] = true; + StatusDisplayType[SC_SPHERE_1] = true; + StatusDisplayType[SC_SPHERE_2] = true; + StatusDisplayType[SC_SPHERE_3] = true; + StatusDisplayType[SC_SPHERE_4] = true; + StatusDisplayType[SC_SPHERE_5] = true; + StatusDisplayType[SC_CAMOUFLAGE] = true; + StatusDisplayType[SC_DUPLELIGHT] = true; + StatusDisplayType[SC_ORATIO] = true; + StatusDisplayType[SC_FREEZING] = true; + StatusDisplayType[SC_VENOMIMPRESS] = true; + StatusDisplayType[SC_HALLUCINATIONWALK] = true; + StatusDisplayType[SC_ROLLINGCUTTER] = true; + StatusDisplayType[SC_BANDING] = true; + StatusDisplayType[SC_CRYSTALIZE] = true; + StatusDisplayType[SC_DEEPSLEEP] = true; + StatusDisplayType[SC_CURSEDCIRCLE_ATKER]= true; + StatusDisplayType[SC_CURSEDCIRCLE_TARGET]= true; + StatusDisplayType[SC_BLOODSUCKER] = true; + StatusDisplayType[SC__SHADOWFORM] = true; + StatusDisplayType[SC__MANHOLE] = true; + #ifdef RENEWAL_EDP // renewal EDP increases your weapon atk StatusChangeFlagTable[SC_EDP] |= SCB_WATK; @@ -995,66 +1012,6 @@ void initChangeTables(void) { if( !battle_config.display_hallucination ) //Disable Hallucination. StatusIconChangeTable[SC_HALLUCINATION] = SI_BLANK; - - /* StatusChangeState (SCS_) NOMOVE */ - StatusChangeStateTable[SC_ANKLE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NOMOVE; - StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOMOVE; - StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOMOVE; - StatusChangeStateTable[SC_BLADESTOP_WAIT] |= SCS_NOMOVE; - StatusChangeStateTable[SC_GOSPEL] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_BASILICA] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_STOP] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CLOSECONFINE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CLOSECONFINE2] |= SCS_NOMOVE; - StatusChangeStateTable[SC_MADNESSCANCEL] |= SCS_NOMOVE; - StatusChangeStateTable[SC_GRAVITATION] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOMOVE; - StatusChangeStateTable[SC_ELECTRICSHOCKER] |= SCS_NOMOVE; - StatusChangeStateTable[SC_BITE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_THORNSTRAP] |= SCS_NOMOVE; - StatusChangeStateTable[SC_MAGNETICFIELD] |= SCS_NOMOVE; - StatusChangeStateTable[SC__MANHOLE] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CURSEDCIRCLE_ATKER] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_NETHERWORLD] |= SCS_NOMOVE; - StatusChangeStateTable[SC_CAMOUFLAGE] |= SCS_NOMOVE|SCS_NOMOVECOND; - StatusChangeStateTable[SC_MEIKYOUSISUI] |= SCS_NOMOVE; - StatusChangeStateTable[SC_KAGEHUMI] |= SCS_NOMOVE; - StatusChangeStateTable[SC_KYOUGAKU] |= SCS_NOMOVE; - - /* StatusChangeState (SCS_) NOPICKUPITEMS */ - StatusChangeStateTable[SC_HIDING] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_CLOAKING] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_TRICKDEAD] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_BLADESTOP] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_CLOAKINGEXCEED] |= SCS_NOPICKITEM; - StatusChangeStateTable[SC_NOCHAT] |= SCS_NOPICKITEM|SCS_NOPICKITEMCOND; - - /* StatusChangeState (SCS_) NODROPITEMS */ - StatusChangeStateTable[SC_AUTOCOUNTER] |= SCS_NODROPITEM; - StatusChangeStateTable[SC_BLADESTOP] |= SCS_NODROPITEM; - StatusChangeStateTable[SC_NOCHAT] |= SCS_NODROPITEM|SCS_NODROPITEMCOND; - - /* StatusChangeState (SCS_) NOCAST (skills) */ - StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; - StatusChangeStateTable[SC_STEELBODY] |= SCS_NOCAST; - StatusChangeStateTable[SC_BERSERK] |= SCS_NOCAST; - StatusChangeStateTable[SC__BLOODYLUST] |= SCS_NOCAST; - StatusChangeStateTable[SC_OBLIVIONCURSE] |= SCS_NOCAST; - StatusChangeStateTable[SC_WHITEIMPRISON] |= SCS_NOCAST; - StatusChangeStateTable[SC__INVISIBILITY] |= SCS_NOCAST; - StatusChangeStateTable[SC_CRYSTALIZE] |= SCS_NOCAST|SCS_NOCASTCOND; - StatusChangeStateTable[SC__IGNORANCE] |= SCS_NOCAST; - StatusChangeStateTable[SC_DEEPSLEEP] |= SCS_NOCAST; - StatusChangeStateTable[SC_SATURDAYNIGHTFEVER] |= SCS_NOCAST; - StatusChangeStateTable[SC_CURSEDCIRCLE_TARGET] |= SCS_NOCAST; - StatusChangeStateTable[SC_SILENCE] |= SCS_NOCAST; - - //Homon S - StatusChangeStateTable[SC_PARALYSIS] |= SCS_NOMOVE; - } static void initDummyData(void) @@ -1152,7 +1109,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s } if (target->type == BL_SKILL) - return skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick()); + return skill->unit_ondamaged((struct skill_unit *)target, src, hp, gettick()); status = status_get_status_data(target); if( status == &dummy_status ) @@ -1206,9 +1163,9 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_change_end(target, SC_ENDURE, INVALID_TIMER); } if ((sce=sc->data[SC_GRAVITATION]) && sce->val3 == BCT_SELF) { - struct skill_unit_group* sg = skill_id2group(sce->val4); + struct skill_unit_group* sg = skill->id2group(sce->val4); if (sg) { - skill_delunitgroup(sg); + skill->del_unitgroup(sg, ALC_MARK); sce->val4 = 0; status_change_end(target, SC_GRAVITATION, INVALID_TIMER); } @@ -1244,7 +1201,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s switch (target->type) { case BL_PC: pc_damage((TBL_PC*)target,src,hp,sp); break; case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); break; - case BL_HOM: merc_damage((TBL_HOM*)target); break; + case BL_HOM: homun->damaged((TBL_HOM*)target); break; case BL_MER: mercenary_heal((TBL_MER*)target,hp,sp); break; case BL_ELEM: elemental_heal((TBL_ELEM*)target,hp,sp); break; } @@ -1269,7 +1226,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s switch (target->type) { case BL_PC: flag = pc_dead((TBL_PC*)target,src); break; case BL_MOB: flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); break; - case BL_HOM: flag = merc_hom_dead((TBL_HOM*)target); break; + case BL_HOM: flag = homun->dead((TBL_HOM*)target); break; case BL_MER: flag = mercenary_dead((TBL_MER*)target); break; case BL_ELEM: flag = elemental_dead((TBL_ELEM*)target); break; default: //Unhandled case, do nothing to object. @@ -1284,7 +1241,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status->hp = 0; if (battle_config.clear_unit_ondeath && battle_config.clear_unit_ondeath&target->type) - skill_clear_unitgroup(target); + skill->clear_unitgroup(target); if(target->type&BL_REGEN) { //Reset regen ticks. @@ -1300,14 +1257,14 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s if( sc && sc->data[SC_KAIZEL] && !map_flag_gvg(target->m) ) { //flag&8 = disable Kaizel - int time = skill_get_time2(SL_KAIZEL,sc->data[SC_KAIZEL]->val1); + int time = skill->get_time2(SL_KAIZEL,sc->data[SC_KAIZEL]->val1); //Look for Osiris Card's bonus effect on the character and revive 100% or revive normally if ( target->type == BL_PC && BL_CAST(BL_PC,target)->special_state.restart_full_recover ) status_revive(target, 100, 100); else status_revive(target, sc->data[SC_KAIZEL]->val2, 0); status_change_clear(target,0); - clif_skill_nodamage(target,target,ALL_RESURRECTION,1,1); + clif->skill_nodamage(target,target,ALL_RESURRECTION,1,1); sc_start(target,status_skill2sc(PR_KYRIE),100,10,time); if( target->type == BL_MOB ) @@ -1319,8 +1276,8 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s TBL_PC *sd = BL_CAST(BL_PC,target); TBL_HOM *hd = sd->hd; if(hd && hd->sc.data[SC_LIGHT_OF_REGENE]){ - clif_skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill_get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage - clif_skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0)); + clif->skillcasting(&hd->bl, hd->bl.id, target->id, 0,0, MH_LIGHT_OF_REGENE, skill->get_ele(MH_LIGHT_OF_REGENE, 1), 10); //just to display usage + clif->skill_nodamage(&sd->bl, target, ALL_RESURRECTION, 1, status_revive(&sd->bl,10*hd->sc.data[SC_LIGHT_OF_REGENE]->val1,0)); status_change_end(&sd->hd->bl,SC_LIGHT_OF_REGENE,INVALID_TIMER); return hp + sp; } @@ -1345,9 +1302,9 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s unit_stop_attack(target); unit_stop_walking(target,1); unit_skillcastcancel(target,0); - clif_clearunit_area(target,CLR_DEAD); - skill_unit_move(target,gettick(),4); - skill_cleartimerskill(target); + clif->clearunit_area(target,CLR_DEAD); + skill->unit_move(target,gettick(),4); + skill->cleartimerskill(target); } return hp+sp; @@ -1413,11 +1370,11 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) // send hp update to client switch(bl->type) { - case BL_PC: pc_heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break; - case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break; - case BL_HOM: merc_hom_heal((TBL_HOM*)bl); break; - case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break; - case BL_ELEM: elemental_heal((TBL_ELEM*)bl,hp,sp); break; + case BL_PC: pc_heal((TBL_PC*)bl,hp,sp,flag&2?1:0); break; + case BL_MOB: mob_heal((TBL_MOB*)bl,hp); break; + case BL_HOM: homun->healed((TBL_HOM*)bl); break; + case BL_MER: mercenary_heal((TBL_MER*)bl,hp,sp); break; + case BL_ELEM: elemental_heal((TBL_ELEM*)bl,hp,sp); break; } return hp+sp; @@ -1515,11 +1472,11 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per status->sp += sp; if (bl->prev) //Animation only if character is already on a map. - clif_resurrection(bl, 1); + clif->resurrection(bl, 1); switch (bl->type) { case BL_PC: pc_revive((TBL_PC*)bl, hp, sp); break; case BL_MOB: mob_revive((TBL_MOB*)bl, hp); break; - case BL_HOM: merc_hom_revive((TBL_HOM*)bl, hp, sp); break; + case BL_HOM: homun->revive((TBL_HOM*)bl, hp, sp); break; } return 1; } @@ -1557,38 +1514,57 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin return 0; } - switch( skill_id ) { - case PA_PRESSURE: - if( flag && target ) { - //Gloria Avoids pretty much everything.... - tsc = status_get_sc(target); - if(tsc && tsc->option&OPTION_HIDE) + if( skill_id ) { + + if( src ) { + int i; + + for(i = 0; i < map[src->m].zone->disabled_skills_count; i++) { + if( skill_id == map[src->m].zone->disabled_skills[i]->nameid && (map[src->m].zone->disabled_skills[i]->type&src->type) ) { + if( src->type == BL_PC ) + clif->msg((TBL_PC*)src, SKILL_CANT_USE_AREA); // This skill cannot be used within this area + else if( src->type == BL_MOB && map[src->m].zone->disabled_skills[i]->subtype != MZS_NONE ) { + if( (status->mode&MD_BOSS) && !(map[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS) ) + break; + } return 0; + } } - break; - case GN_WALLOFTHORN: - if( target && status_isdead(target) ) - return 0; - break; - case AL_TELEPORT: - //Should fail when used on top of Land Protector [Skotlex] - if (src && map_getcell(src->m, src->x, src->y, CELL_CHKLANDPROTECTOR) - && !(status->mode&MD_BOSS) - && (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id)) - return 0; - break; - default: - break; + } + + switch( skill_id ) { + case PA_PRESSURE: + if( flag && target ) { + //Gloria Avoids pretty much everything.... + tsc = status_get_sc(target); + if(tsc && tsc->option&OPTION_HIDE) + return 0; + } + break; + case GN_WALLOFTHORN: + if( target && status_isdead(target) ) + return 0; + break; + case AL_TELEPORT: + //Should fail when used on top of Land Protector [Skotlex] + if (src && map_getcell(src->m, src->x, src->y, CELL_CHKLANDPROTECTOR) + && !(status->mode&MD_BOSS) + && (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id)) + return 0; + break; + default: + break; + } } if ( src ) sc = status_get_sc(src); if( sc && sc->count ) { - if (skill_id != RK_REFRESH && sc->opt1 >0 && (sc->opt1 != OPT1_CRYSTALIZE && src->type != BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc + if (skill_id != RK_REFRESH && sc->opt1 >0 && !(sc->opt1 == OPT1_CRYSTALIZE && src->type == BL_MOB) && sc->opt1 != OPT1_BURNING && skill_id != SR_GENTLETOUCH_CURE) { //Stuned/Frozen/etc if (flag != 1) //Can't cast, casted stuff can't damage. return 0; - if (!(skill_get_inf(skill_id)&INF_GROUND_SKILL)) + if (!(skill->get_inf(skill_id)&INF_GROUND_SKILL)) return 0; //Targetted spells can't come off. } @@ -1603,7 +1579,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if (sc->data[SC_WINKCHARM] && target && !flag) { //Prevents skill usage if( unit_bl2ud(src) && (unit_bl2ud(src))->walktimer == INVALID_TIMER ) unit_walktobl(src, map_id2bl(sc->data[SC_WINKCHARM]->val2), 3, 1); - clif_emotion(src, E_LV); + clif->emotion(src, E_LV); return 0; } @@ -1625,7 +1601,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin return 0; } else if(sc->data[SC_LONGING]) { //Allow everything except dancing/re-dancing. [Skotlex] if (skill_id == BD_ENCORE || - skill_get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL) + skill->get_inf2(skill_id)&(INF2_SONG_DANCE|INF2_ENSEMBLE_SKILL) ) return 0; } else { @@ -1647,11 +1623,22 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin (src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id) ) { //Skills blocked through status changes... if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through - sc->cant.cast || + sc->data[SC_SILENCE] || + sc->data[SC_STEELBODY] || + sc->data[SC_BERSERK] || + sc->data[SC__BLOODYLUST] || + sc->data[SC_OBLIVIONCURSE] || + sc->data[SC_WHITEIMPRISON] || + sc->data[SC__INVISIBILITY] || + (sc->data[SC_CRYSTALIZE] && src->type != BL_MOB) || + sc->data[SC__IGNORANCE] || + sc->data[SC_DEEPSLEEP] || + sc->data[SC_SATURDAYNIGHTFEVER] || + sc->data[SC_CURSEDCIRCLE_TARGET] || (sc->data[SC_MARIONETTE] && skill_id != CG_MARIONETTE) || //Only skill you can use is marionette again to cancel it (sc->data[SC_MARIONETTE2] && skill_id == CG_MARIONETTE) || //Cannot use marionette if you are being buffed by another - (sc->data[SC_STASIS] && skill_block_check(src, SC_STASIS, skill_id)) || - (sc->data[SC_KAGEHUMI] && skill_block_check(src, SC_KAGEHUMI, skill_id)) + (sc->data[SC_STASIS] && skill->block_check(src, SC_STASIS, skill_id)) || + (sc->data[SC_KAGEHUMI] && skill->block_check(src, SC_KAGEHUMI, skill_id)) )) return 0; @@ -1659,7 +1646,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin if ( (sc->data[SC_VOLCANO] && skill_id == WZ_ICEWALL) || (sc->data[SC_ROKISWEIL] && skill_id != BD_ADAPTATION) || - (sc->data[SC_HERMODE] && skill_get_inf(skill_id) & INF_SUPPORT_SKILL) || + (sc->data[SC_HERMODE] && skill->get_inf(skill_id) & INF_SUPPORT_SKILL) || (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOSKILL) ) return 0; @@ -1678,26 +1665,26 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin } } - if (sc && sc->option) - { - if (sc->option&OPTION_HIDE) - switch (skill_id) { //Usable skills while hiding. - case TF_HIDING: - case AS_GRIMTOOTH: - case RG_BACKSTAP: - case RG_RAID: - case NJ_SHADOWJUMP: - case NJ_KIRIKAGE: - case KO_YAMIKUMO: - break; - default: - //Non players can use all skills while hidden. - if (!skill_id || src->type == BL_PC) - return 0; + if (sc && sc->option) { + if (sc->option&OPTION_HIDE) { + switch (skill_id) { //Usable skills while hiding. + case TF_HIDING: + case AS_GRIMTOOTH: + case RG_BACKSTAP: + case RG_RAID: + case NJ_SHADOWJUMP: + case NJ_KIRIKAGE: + case KO_YAMIKUMO: + break; + default: + //Non players can use all skills while hidden. + if (!skill_id || src->type == BL_PC) + return 0; + } } if (sc->option&OPTION_CHASEWALK && skill_id != ST_CHASEWALK) return 0; - if(sc->option&OPTION_MOUNTING) + if( sc->data[SC_ALL_RIDING] ) return 0;//New mounts can't attack nor use skills in the client; this check makes it cheat-safe [Ind] } @@ -1723,7 +1710,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK); //You cannot hide from ground skills. - if( skill_get_ele(skill_id,1) == ELE_EARTH ) //TODO: Need Skill Lv here :/ + if( skill->get_ele(skill_id,1) == ELE_EARTH ) //TODO: Need Skill Lv here :/ hide_flag &= ~OPTION_HIDE; switch( target->type ) { @@ -1751,9 +1738,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin case BL_HOM: case BL_MER: case BL_ELEM: - if( target->type == BL_HOM && skill_id && battle_config.hom_setting&0x1 && skill_get_inf(skill_id)&INF_SUPPORT_SKILL && battle_get_master(target) != src ) + if( target->type == BL_HOM && skill_id && battle_config.hom_setting&0x1 && skill->get_inf(skill_id)&INF_SUPPORT_SKILL && battle->get_master(target) != src ) return 0; // Can't use support skills on Homunculus (only Master/Self) - if( target->type == BL_MER && (skill_id == PR_ASPERSIO || (skill_id >= SA_FLAMELAUNCHER && skill_id <= SA_SEISMICWEAPON)) && battle_get_master(target) != src ) + if( target->type == BL_MER && (skill_id == PR_ASPERSIO || (skill_id >= SA_FLAMELAUNCHER && skill_id <= SA_SEISMICWEAPON)) && battle->get_master(target) != src ) return 0; // Can't use Weapon endow skills on Mercenary (only Master) if( skill_id == AM_POTIONPITCHER && ( target->type == BL_MER || target->type == BL_ELEM) ) return 0; // Can't use Potion Pitcher on Mercenaries @@ -2109,7 +2096,7 @@ int status_calc_mob_(struct mob_data* md, bool first) if(flag&4) { // Strengthen Guardians - custom value +10% / lv struct guild_castle *gc; - gc=guild_mapname2gc(map[md->bl.m].name); + gc=guild->mapname2gc(map[md->bl.m].name); if (!gc) ShowError("status_calc_mob: No castle set at map %s\n", map[md->bl.m].name); else @@ -2169,7 +2156,7 @@ int status_calc_pet_(struct pet_data *pd, bool first) struct status_data *bstat = &pd->db->status, *status = &pd->status; pd->pet.level = lv; if (!first) //Lv Up animation - clif_misceffect(&pd->bl, 0); + clif->misceffect(&pd->bl, 0); status->rhw.atk = (bstat->rhw.atk*lv)/pd->db->lv; status->rhw.atk2 = (bstat->rhw.atk2*lv)/pd->db->lv; status->str = (bstat->str*lv)/pd->db->lv; @@ -2191,7 +2178,7 @@ int status_calc_pet_(struct pet_data *pd, bool first) status_calc_misc(&pd->bl, &pd->status, lv); if (!first) //Not done the first time because the pet is not visible yet - clif_send_petstatus(sd); + clif->send_petstatus(sd); } } else if (first) { status_calc_misc(&pd->bl, &pd->status, pd->db->lv); @@ -2280,7 +2267,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) const struct status_change *sc = &sd->sc; struct s_skill b_skill[MAX_SKILL]; // previous skill tree int b_weight, b_max_weight, b_cart_weight_max, // previous weight - i, index, skill,refinedef=0; + i, k, index, skill,refinedef=0; int64 i64; if (++calculating > 10) //Too many recursive calls! @@ -2366,13 +2353,14 @@ int status_calc_pc_(struct map_session_data* sd, bool first) memset (&sd->left_weapon.overrefine, 0, sizeof(sd->left_weapon) - sizeof(sd->left_weapon.atkmods)); if (sd->special_state.intravision && !sd->sc.data[SC_INTRAVISION]) //Clear intravision as long as nothing else is using it - clif_status_load(&sd->bl, SI_INTRAVISION, 0); + clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_INTRAVISION); memset(&sd->special_state,0,sizeof(sd->special_state)); memset(&status->max_hp, 0, sizeof(struct status_data)-(sizeof(status->hp)+sizeof(status->sp))); //FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex] - status->speed = DEFAULT_WALK_SPEED; + if (!sd->state.permanent_speed) + status->speed = DEFAULT_WALK_SPEED; //Give them all modes except these (useful for clones) status->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK); @@ -2416,6 +2404,7 @@ int status_calc_pc_(struct map_session_data* sd, bool first) + sizeof(sd->skillcooldown) + sizeof(sd->skillfixcast) + sizeof(sd->skillvarcast) + + sizeof(sd->skillfixcastrate) ); memset (&sd->bonus, 0,sizeof(sd->bonus)); @@ -2443,6 +2432,15 @@ int status_calc_pc_(struct map_session_data* sd, bool first) if(!sd->inventory_data[index]) continue; + for(k = 0; k < map[sd->bl.m].zone->disabled_items_count; k++) { + if( map[sd->bl.m].zone->disabled_items[k] == sd->inventory_data[index]->nameid ) { + break; + } + } + + if( k < map[sd->bl.m].zone->disabled_items_count ) + continue; + status->def += sd->inventory_data[index]->def; if(first && sd->inventory_data[index]->equip_script) @@ -2577,28 +2575,24 @@ int status_calc_pc_(struct map_session_data* sd, bool first) data = itemdb_exists(c); if(!data) continue; - if(first && data->equip_script) - { //Execute equip-script on login + if(first && data->equip_script) {//Execute equip-script on login run_script(data->equip_script,0,sd->bl.id,0); if (!calculating) return 1; } if(!data->script) continue; - if(data->flag.no_equip) { //Card restriction checks. - if(map[sd->bl.m].flag.restricted && data->flag.no_equip&(8*map[sd->bl.m].zone)) - continue; - if(!map_flag_vs(sd->bl.m) && data->flag.no_equip&1) - continue; - if(map[sd->bl.m].flag.pvp && data->flag.no_equip&2) - continue; - if(map_flag_gvg(sd->bl.m) && data->flag.no_equip&4) - continue; - if(map[sd->bl.m].flag.battleground && data->flag.no_equip&8) - continue; + + for(k = 0; k < map[sd->bl.m].zone->disabled_items_count; k++) { + if( map[sd->bl.m].zone->disabled_items[k] == sd->inventory_data[index]->nameid ) { + break; + } } - if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) - { //Left hand status. + + if( k < map[sd->bl.m].zone->disabled_items_count ) + continue; + + if(i == EQI_HAND_L && sd->status.inventory[index].equip == EQP_HAND_L) { //Left hand status. sd->state.lr_flag = 1; run_script(data->script,0,sd->bl.id,0); sd->state.lr_flag = 0; @@ -3078,15 +3072,15 @@ int status_calc_pc_(struct map_session_data* sd, bool first) return 0; } if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill))) - clif_skillinfoblock(sd); + clif->skillinfoblock(sd); if(b_weight != sd->weight) - clif_updatestatus(sd,SP_WEIGHT); + clif->updatestatus(sd,SP_WEIGHT); if(b_max_weight != sd->max_weight) { - clif_updatestatus(sd,SP_MAXWEIGHT); + clif->updatestatus(sd,SP_MAXWEIGHT); pc_updateweightstatus(sd); } if( b_cart_weight_max != sd->cart_weight_max ) { - clif_updatestatus(sd,SP_CARTINFO); + clif->updatestatus(sd,SP_CARTINFO); } calculating = 0; @@ -3153,21 +3147,20 @@ int status_calc_homunculus_(struct homun_data *hd, bool first) status->max_hp = hom->max_hp ; status->max_sp = hom->max_sp ; - merc_hom_calc_skilltree(hd, 0); + homun->calc_skilltree(hd, 0); - if((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) + if((skill=homun->checkskill(hd,HAMI_SKIN)) > 0) status->def += skill * 4; - if((skill = merc_hom_checkskill(hd,HVAN_INSTRUCT)) > 0) - { + if((skill = homun->checkskill(hd,HVAN_INSTRUCT)) > 0) { status->int_ += 1 +skill/2 +skill/4 +skill/5; status->str += 1 +skill/3 +skill/3 +skill/4; } - if((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) + if((skill=homun->checkskill(hd,HAMI_SKIN)) > 0) status->max_hp += skill * 2 * status->max_hp / 100; - if((skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0) + if((skill = homun->checkskill(hd,HLIF_BRAIN)) > 0) status->max_sp += (1 +skill/2 -skill/4 +skill/5) * status->max_sp / 100 ; if (first) { @@ -3379,11 +3372,11 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct if( bl->type == BL_HOM ) { struct homun_data *hd = (TBL_HOM*)bl; - if( (skill = merc_hom_checkskill(hd,HAMI_SKIN)) > 0 ) { + if( (skill = homun->checkskill(hd,HAMI_SKIN)) > 0 ) { val = regen->hp*(100+5*skill)/100; regen->hp = cap_value(val, 1, SHRT_MAX); } - if( (skill = merc_hom_checkskill(hd,HLIF_BRAIN)) > 0 ) { + if( (skill = homun->checkskill(hd,HLIF_BRAIN)) > 0 ) { val = regen->sp*(100+3*skill)/100; regen->sp = cap_value(val, 1, SHRT_MAX); } @@ -3486,63 +3479,6 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str regen->rate.hp *= 2; } -void status_calc_state( struct block_list *bl, struct status_change *sc, enum scs_flag flag, bool start ) { - - /* no sc at all, we can zero without any extra weight over our conciousness */ - if( !sc->count ) { - memset(&sc->cant, 0, sizeof (sc->cant)); - return; - } - - /* can move? */ - if( flag&SCS_NOMOVE ) { - if( !(flag&SCS_NOMOVECOND) ) { - sc->cant.move += ( start ? 1 : -1 ); - } else if( - (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect - || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move - || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) - || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) - || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 - && !(sc->data[SC_CAMOUFLAGE]->val3&1)) - ) { - sc->cant.move += ( start ? 1 : -1 ); - } - } - - /* can't use skills */ - if( flag&SCS_NOCAST ) { - if( !(flag&SCS_NOCASTCOND) ) { - sc->cant.cast += ( start ? 1 : -1 ); - } else if( (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) ){ - sc->cant.cast += ( start ? 1 : -1 ); - } - } - - /* player-only states */ - if( bl->type == BL_PC ) { - - /* can pick items? */ - if( flag&SCS_NOPICKITEM ) { - if( !(flag&SCS_NOPICKITEMCOND) ) { - sc->cant.pickup += ( start ? 1 : -1 ); - } else if( (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM) ) { - sc->cant.pickup += ( start ? 1 : -1 ); - } - } - - /* can drop items? */ - if( flag&SCS_NODROPITEM ) { - if( !(flag&SCS_NODROPITEMCOND) ) { - sc->cant.drop += ( start ? 1 : -1 ); - } else if( (sc->data[SC_NOCHAT] && sc->data[SC_NOCHAT]->val1&MANNER_NOITEM) ) { - sc->cant.drop += ( start ? 1 : -1 ); - } - } - } - - return; -} /// Recalculates parts of an object's battle status according to the specified flags. /// @param flag bitfield of values from enum scb_flag void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) @@ -3821,7 +3757,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if( status->hp > status->max_hp ) //FIXME: Should perhaps a status_zap should be issued? { status->hp = status->max_hp; - if( sd ) clif_updatestatus(sd,SP_HP); + if( sd ) clif->updatestatus(sd,SP_HP); } } @@ -3844,7 +3780,7 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) if( status->sp > status->max_sp ) { status->sp = status->max_sp; - if( sd ) clif_updatestatus(sd,SP_SP); + if( sd ) clif->updatestatus(sd,SP_SP); } } @@ -4027,37 +3963,37 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) { TBL_PC* sd = BL_CAST(BL_PC, bl); if(b_status.str != status->str) - clif_updatestatus(sd,SP_STR); + clif->updatestatus(sd,SP_STR); if(b_status.agi != status->agi) - clif_updatestatus(sd,SP_AGI); + clif->updatestatus(sd,SP_AGI); if(b_status.vit != status->vit) - clif_updatestatus(sd,SP_VIT); + clif->updatestatus(sd,SP_VIT); if(b_status.int_ != status->int_) - clif_updatestatus(sd,SP_INT); + clif->updatestatus(sd,SP_INT); if(b_status.dex != status->dex) - clif_updatestatus(sd,SP_DEX); + clif->updatestatus(sd,SP_DEX); if(b_status.luk != status->luk) - clif_updatestatus(sd,SP_LUK); + clif->updatestatus(sd,SP_LUK); if(b_status.hit != status->hit) - clif_updatestatus(sd,SP_HIT); + clif->updatestatus(sd,SP_HIT); if(b_status.flee != status->flee) - clif_updatestatus(sd,SP_FLEE1); + clif->updatestatus(sd,SP_FLEE1); if(b_status.amotion != status->amotion) - clif_updatestatus(sd,SP_ASPD); + clif->updatestatus(sd,SP_ASPD); if(b_status.speed != status->speed) - clif_updatestatus(sd,SP_SPEED); + clif->updatestatus(sd,SP_SPEED); if(b_status.batk != status->batk #ifndef RENEWAL || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk #endif ) - clif_updatestatus(sd,SP_ATK1); + clif->updatestatus(sd,SP_ATK1); if(b_status.def != status->def){ - clif_updatestatus(sd,SP_DEF1); + clif->updatestatus(sd,SP_DEF1); #ifdef RENEWAL - clif_updatestatus(sd,SP_DEF2); + clif->updatestatus(sd,SP_DEF2); #endif } @@ -4066,91 +4002,91 @@ void status_calc_bl_(struct block_list* bl, enum scb_flag flag, bool first) || b_status.rhw.atk != status->rhw.atk || b_status.lhw.atk != status->lhw.atk #endif ) - clif_updatestatus(sd,SP_ATK2); + clif->updatestatus(sd,SP_ATK2); if(b_status.def2 != status->def2){ - clif_updatestatus(sd,SP_DEF2); + clif->updatestatus(sd,SP_DEF2); #ifdef RENEWAL - clif_updatestatus(sd,SP_DEF1); + clif->updatestatus(sd,SP_DEF1); #endif } if(b_status.flee2 != status->flee2) - clif_updatestatus(sd,SP_FLEE2); + clif->updatestatus(sd,SP_FLEE2); if(b_status.cri != status->cri) - clif_updatestatus(sd,SP_CRITICAL); + clif->updatestatus(sd,SP_CRITICAL); #ifndef RENEWAL if(b_status.matk_max != status->matk_max) - clif_updatestatus(sd,SP_MATK1); + clif->updatestatus(sd,SP_MATK1); if(b_status.matk_min != status->matk_min) - clif_updatestatus(sd,SP_MATK2); + clif->updatestatus(sd,SP_MATK2); #else if(b_status.matk_max != status->matk_max || b_status.matk_min != status->matk_min){ - clif_updatestatus(sd,SP_MATK2); - clif_updatestatus(sd,SP_MATK1); + clif->updatestatus(sd,SP_MATK2); + clif->updatestatus(sd,SP_MATK1); } #endif if(b_status.mdef != status->mdef){ - clif_updatestatus(sd,SP_MDEF1); + clif->updatestatus(sd,SP_MDEF1); #ifdef RENEWAL - clif_updatestatus(sd,SP_MDEF2); + clif->updatestatus(sd,SP_MDEF2); #endif } if(b_status.mdef2 != status->mdef2){ - clif_updatestatus(sd,SP_MDEF2); + clif->updatestatus(sd,SP_MDEF2); #ifdef RENEWAL - clif_updatestatus(sd,SP_MDEF1); + clif->updatestatus(sd,SP_MDEF1); #endif } if(b_status.rhw.range != status->rhw.range) - clif_updatestatus(sd,SP_ATTACKRANGE); + clif->updatestatus(sd,SP_ATTACKRANGE); if(b_status.max_hp != status->max_hp) - clif_updatestatus(sd,SP_MAXHP); + clif->updatestatus(sd,SP_MAXHP); if(b_status.max_sp != status->max_sp) - clif_updatestatus(sd,SP_MAXSP); + clif->updatestatus(sd,SP_MAXSP); if(b_status.hp != status->hp) - clif_updatestatus(sd,SP_HP); + clif->updatestatus(sd,SP_HP); if(b_status.sp != status->sp) - clif_updatestatus(sd,SP_SP); + clif->updatestatus(sd,SP_SP); } else if( bl->type == BL_HOM ) { TBL_HOM* hd = BL_CAST(BL_HOM, bl); if( hd->master && memcmp(&b_status, status, sizeof(struct status_data)) != 0 ) - clif_hominfo(hd->master,hd,0); + clif->hominfo(hd->master,hd,0); } else if( bl->type == BL_MER ) { TBL_MER* md = BL_CAST(BL_MER, bl); if( b_status.rhw.atk != status->rhw.atk || b_status.rhw.atk2 != status->rhw.atk2 ) - clif_mercenary_updatestatus(md->master, SP_ATK1); + clif->mercenary_updatestatus(md->master, SP_ATK1); if( b_status.matk_max != status->matk_max ) - clif_mercenary_updatestatus(md->master, SP_MATK1); + clif->mercenary_updatestatus(md->master, SP_MATK1); if( b_status.hit != status->hit ) - clif_mercenary_updatestatus(md->master, SP_HIT); + clif->mercenary_updatestatus(md->master, SP_HIT); if( b_status.cri != status->cri ) - clif_mercenary_updatestatus(md->master, SP_CRITICAL); + clif->mercenary_updatestatus(md->master, SP_CRITICAL); if( b_status.def != status->def ) - clif_mercenary_updatestatus(md->master, SP_DEF1); + clif->mercenary_updatestatus(md->master, SP_DEF1); if( b_status.mdef != status->mdef ) - clif_mercenary_updatestatus(md->master, SP_MDEF1); + clif->mercenary_updatestatus(md->master, SP_MDEF1); if( b_status.flee != status->flee ) - clif_mercenary_updatestatus(md->master, SP_MERCFLEE); + clif->mercenary_updatestatus(md->master, SP_MERCFLEE); if( b_status.amotion != status->amotion ) - clif_mercenary_updatestatus(md->master, SP_ASPD); + clif->mercenary_updatestatus(md->master, SP_ASPD); if( b_status.max_hp != status->max_hp ) - clif_mercenary_updatestatus(md->master, SP_MAXHP); + clif->mercenary_updatestatus(md->master, SP_MAXHP); if( b_status.max_sp != status->max_sp ) - clif_mercenary_updatestatus(md->master, SP_MAXSP); + clif->mercenary_updatestatus(md->master, SP_MAXSP); if( b_status.hp != status->hp ) - clif_mercenary_updatestatus(md->master, SP_HP); + clif->mercenary_updatestatus(md->master, SP_HP); if( b_status.sp != status->sp ) - clif_mercenary_updatestatus(md->master, SP_SP); + clif->mercenary_updatestatus(md->master, SP_SP); } else if( bl->type == BL_ELEM ) { TBL_ELEM* ed = BL_CAST(BL_ELEM, bl); if( b_status.max_hp != status->max_hp ) - clif_elemental_updatestatus(ed->master, SP_MAXHP); + clif->elemental_updatestatus(ed->master, SP_MAXHP); if( b_status.max_sp != status->max_sp ) - clif_elemental_updatestatus(ed->master, SP_MAXSP); + clif->elemental_updatestatus(ed->master, SP_MAXSP); if( b_status.hp != status->hp ) - clif_elemental_updatestatus(ed->master, SP_HP); + clif->elemental_updatestatus(ed->master, SP_HP); if( b_status.sp != status->sp ) - clif_mercenary_updatestatus(ed->master, SP_SP); + clif->mercenary_updatestatus(ed->master, SP_SP); } } @@ -4674,7 +4610,7 @@ static unsigned short status_calc_matk(struct block_list *bl, struct status_chan if (sc->data[SC_IZAYOI]) matk += 50 * sc->data[SC_IZAYOI]->val1; #endif - if (sc->data[SC_MAGICPOWER]) + if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4) matk += matk * sc->data[SC_MAGICPOWER]->val3/100; if (sc->data[SC_MINDBREAKER]) matk += matk * sc->data[SC_MINDBREAKER]->val2/100; @@ -4891,7 +4827,7 @@ static defType status_calc_def(struct block_list *bl, struct status_change *sc, def -= 20; if( sc->data[SC_ANGRIFFS_MODUS] ) def -= 30 + 20 * sc->data[SC_ANGRIFFS_MODUS]->val1; - if(sc->data[SC_STONEHARDSKIN])// Final DEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + if(sc->data[SC_STONEHARDSKIN]) def += sc->data[SC_STONEHARDSKIN]->val1; if(sc->data[SC_STONE] && sc->opt1 == OPT1_STONE) def >>=1; @@ -5020,7 +4956,7 @@ static defType status_calc_mdef(struct block_list *bl, struct status_change *sc, mdef += (sc->data[SC_ENDURE]->val4 == 0) ? sc->data[SC_ENDURE]->val1 : 1; if(sc->data[SC_CONCENTRATION]) mdef += 1; //Skill info says it adds a fixed 1 Mdef point. - if(sc->data[SC_STONEHARDSKIN])// Final MDEF increase divided by 10 since were using classic (pre-renewal) mechanics. [Rytech] + if(sc->data[SC_STONEHARDSKIN]) mdef += sc->data[SC_STONEHARDSKIN]->val1; if(sc->data[SC_WATER_BARRIER]) mdef += sc->data[SC_WATER_BARRIER]->val2; @@ -5076,6 +5012,9 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha if( sc == NULL ) return cap_value(speed,10,USHRT_MAX); + if (sd && sd->state.permanent_speed) + return (short)cap_value(speed,10,USHRT_MAX); + if( sd && sd->ud.skilltimer != INVALID_TIMER && (pc_checkskill(sd,SA_FREECAST) > 0 || sd->ud.skill_id == LG_EXEEDBREAK) ) { if( sd->ud.skill_id == LG_EXEEDBREAK ) @@ -5094,7 +5033,7 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha if( sc->data[SC_FUSION] ) val = 25; else if( sd ) { - if( pc_isriding(sd) || sd->sc.option&(OPTION_DRAGON|OPTION_MOUNTING) ) + if( pc_isriding(sd) || sd->sc.option&(OPTION_DRAGON) || sd->sc.data[SC_ALL_RIDING] ) val = 25;//Same bonus else if( pc_isridingwug(sd) ) val = 15 + 5 * pc_checkskill(sd, RA_WUGRIDER); @@ -5820,7 +5759,7 @@ defType status_get_def(struct block_list *bl) { int def = status?status->def:0; ud = unit_bl2ud(bl); if (ud && ud->skilltimer != INVALID_TIMER) - def -= def * skill_get_castdef(ud->skill_id)/100; + def -= def * skill->get_castdef(ud->skill_id)/100; return cap_value(def, DEFTYPE_MIN, DEFTYPE_MAX); } @@ -5937,7 +5876,7 @@ int status_get_emblem_id(struct block_list *bl) { break; case BL_NPC: if (((TBL_NPC*)bl)->subtype == SCRIPT && ((TBL_NPC*)bl)->u.scr.guild_id > 0) { - struct guild *g = guild_search(((TBL_NPC*)bl)->u.scr.guild_id); + struct guild *g = guild->search(((TBL_NPC*)bl)->u.scr.guild_id); if (g) return g->emblem_id; } @@ -6011,7 +5950,7 @@ void status_set_viewdata(struct block_list *bl, int class_) else if (npcdb_checkid(class_) || (bl->type == BL_NPC && class_ == WARP_CLASS)) vd = npc_get_viewdata(class_); else if (homdb_checkid(class_)) - vd = merc_get_hom_viewdata(class_); + vd = homun->get_viewdata(class_); else if (merc_class(class_)) vd = merc_get_viewdata(class_); else if (elemental_class(class_)) @@ -6020,123 +5959,122 @@ void status_set_viewdata(struct block_list *bl, int class_) vd = NULL; switch (bl->type) { - case BL_PC: - { - TBL_PC* sd = (TBL_PC*)bl; - if (pcdb_checkid(class_)) { - if (sd->sc.option&OPTION_WEDDING) - class_ = JOB_WEDDING; - else if (sd->sc.option&OPTION_SUMMER) - class_ = JOB_SUMMER; - else if (sd->sc.option&OPTION_XMAS) - class_ = JOB_XMAS; - else if (sd->sc.option&OPTION_RIDING) { - switch (class_) { //Adapt class to a Mounted one. - case JOB_KNIGHT: - class_ = JOB_KNIGHT2; - break; - case JOB_CRUSADER: - class_ = JOB_CRUSADER2; - break; - case JOB_LORD_KNIGHT: - class_ = JOB_LORD_KNIGHT2; - break; - case JOB_PALADIN: - class_ = JOB_PALADIN2; - break; - case JOB_BABY_KNIGHT: - class_ = JOB_BABY_KNIGHT2; - break; - case JOB_BABY_CRUSADER: - class_ = JOB_BABY_CRUSADER2; - break; + case BL_PC: + { + TBL_PC* sd = (TBL_PC*)bl; + if (pcdb_checkid(class_)) { + if (sd->sc.option&OPTION_RIDING) { + switch (class_) { //Adapt class to a Mounted one. + case JOB_KNIGHT: + class_ = JOB_KNIGHT2; + break; + case JOB_CRUSADER: + class_ = JOB_CRUSADER2; + break; + case JOB_LORD_KNIGHT: + class_ = JOB_LORD_KNIGHT2; + break; + case JOB_PALADIN: + class_ = JOB_PALADIN2; + break; + case JOB_BABY_KNIGHT: + class_ = JOB_BABY_KNIGHT2; + break; + case JOB_BABY_CRUSADER: + class_ = JOB_BABY_CRUSADER2; + break; + } } - } - sd->vd.class_ = class_; - clif_get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); - sd->vd.head_top = sd->status.head_top; - sd->vd.head_mid = sd->status.head_mid; - sd->vd.head_bottom = sd->status.head_bottom; - sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style); - sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color); - sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color); - sd->vd.sex = sd->status.sex; - } else if (vd) - memcpy(&sd->vd, vd, sizeof(struct view_data)); - else - ShowError("status_set_viewdata (PC): No view data for class %d\n", class_); - } - break; - case BL_MOB: - { - TBL_MOB* md = (TBL_MOB*)bl; - if (vd) - md->vd = vd; - else - ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_); - } - break; - case BL_PET: - { - TBL_PET* pd = (TBL_PET*)bl; - if (vd) { - memcpy(&pd->vd, vd, sizeof(struct view_data)); - if (!pcdb_checkid(vd->class_)) { - pd->vd.hair_style = battle_config.pet_hair_style; - if(pd->pet.equip) { - pd->vd.head_bottom = itemdb_viewid(pd->pet.equip); - if (!pd->vd.head_bottom) - pd->vd.head_bottom = pd->pet.equip; + sd->vd.class_ = class_; + clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); + sd->vd.head_top = sd->status.head_top; + sd->vd.head_mid = sd->status.head_mid; + sd->vd.head_bottom = sd->status.head_bottom; + sd->vd.hair_style = cap_value(sd->status.hair,0,battle_config.max_hair_style); + sd->vd.hair_color = cap_value(sd->status.hair_color,0,battle_config.max_hair_color); + sd->vd.cloth_color = cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color); + sd->vd.robe = sd->status.robe; + sd->vd.sex = sd->status.sex; + + if ( sd->vd.cloth_color ) { + if( sd->sc.option&OPTION_WEDDING && battle_config.wedding_ignorepalette ) + sd->vd.cloth_color = 0; + if( sd->sc.option&OPTION_XMAS && battle_config.xmas_ignorepalette ) + sd->vd.cloth_color = 0; + if( sd->sc.option&OPTION_SUMMER && battle_config.summer_ignorepalette ) + sd->vd.cloth_color = 0; + if( sd->sc.option&OPTION_HANBOK && battle_config.hanbok_ignorepalette ) + sd->vd.cloth_color = 0; } - } - } else - ShowError("status_set_viewdata (PET): No view data for class %d\n", class_); - } - break; - case BL_NPC: - { - TBL_NPC* nd = (TBL_NPC*)bl; - if (vd) - nd->vd = vd; - else - ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_); - } - break; - case BL_HOM: //[blackhole89] - { - struct homun_data *hd = (struct homun_data*)bl; - if (vd) - hd->vd = vd; - else - ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_); - } + } else if (vd) + memcpy(&sd->vd, vd, sizeof(struct view_data)); + else + ShowError("status_set_viewdata (PC): No view data for class %d\n", class_); + } break; - case BL_MER: - { - struct mercenary_data *md = (struct mercenary_data*)bl; - if (vd) - md->vd = vd; - else - ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_); - } + case BL_MOB: + { + TBL_MOB* md = (TBL_MOB*)bl; + if (vd) + md->vd = vd; + else + ShowError("status_set_viewdata (MOB): No view data for class %d\n", class_); + } break; - case BL_ELEM: - { - struct elemental_data *ed = (struct elemental_data*)bl; - if (vd) - ed->vd = vd; - else - ShowError("status_set_viewdata (ELEMENTAL): No view data for class %d\n", class_); - } + case BL_PET: + { + TBL_PET* pd = (TBL_PET*)bl; + if (vd) { + memcpy(&pd->vd, vd, sizeof(struct view_data)); + if (!pcdb_checkid(vd->class_)) { + pd->vd.hair_style = battle_config.pet_hair_style; + if(pd->pet.equip) { + pd->vd.head_bottom = itemdb_viewid(pd->pet.equip); + if (!pd->vd.head_bottom) + pd->vd.head_bottom = pd->pet.equip; + } + } + } else + ShowError("status_set_viewdata (PET): No view data for class %d\n", class_); + } + break; + case BL_NPC: + { + TBL_NPC* nd = (TBL_NPC*)bl; + if (vd) + nd->vd = vd; + else + ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_); + } break; + case BL_HOM: //[blackhole89] + { + struct homun_data *hd = (struct homun_data*)bl; + if (vd) + hd->vd = vd; + else + ShowError("status_set_viewdata (HOMUNCULUS): No view data for class %d\n", class_); + } + break; + case BL_MER: + { + struct mercenary_data *md = (struct mercenary_data*)bl; + if (vd) + md->vd = vd; + else + ShowError("status_set_viewdata (MERCENARY): No view data for class %d\n", class_); + } + break; + case BL_ELEM: + { + struct elemental_data *ed = (struct elemental_data*)bl; + if (vd) + ed->vd = vd; + else + ShowError("status_set_viewdata (ELEMENTAL): No view data for class %d\n", class_); + } + break; } - vd = status_get_viewdata(bl); - if (vd && vd->cloth_color && ( - (vd->class_==JOB_WEDDING && battle_config.wedding_ignorepalette) - || (vd->class_==JOB_XMAS && battle_config.xmas_ignorepalette) - || (vd->class_==JOB_SUMMER && battle_config.summer_ignorepalette) - )) - vd->cloth_color = 0; } /// Returns the status_change data of bl or NULL if it doesn't exist. @@ -6165,7 +6103,12 @@ void status_change_init(struct block_list *bl) //the flag values are the same as in status_change_start. int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int tick, int flag) { - int sc_def = 0, tick_def = 0; + //Percentual resistance: 10000 = 100% Resist + //Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms + int sc_def = 0, tick_def = -1; //-1 = use sc_def + //Linear resistance substracted from rate and tick after percentual resistance was applied + //Example: 25% -> sc_def2=2000 -> 5%; 2500ms -> tick_def2=2000 -> 500ms + int sc_def2 = 0, tick_def2 = -1; //-1 = use sc_def2 struct status_data* status; struct status_change* sc; struct map_session_data *sd; @@ -6214,67 +6157,72 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti if( sc && !sc->count ) sc = NULL; switch (type) { - case SC_STUN: - case SC_POISON: - if( sc && sc->data[SC__UNLUCKY] ) - return tick; - case SC_DPOISON: - case SC_SILENCE: - case SC_BLEEDING: - sc_def = 3 +status->vit; - break; - case SC_SLEEP: - sc_def = 3 +status->int_; - break; - case SC_DEEPSLEEP: - tick_def = status->int_ / 10 + status_get_lv(bl) * 65 / 1000; // Seems to be -1 sec every 10 int and -5% chance every 10 int. - sc_def = 5 * status->int_ /10; - break; - case SC_DECREASEAGI: - case SC_ADORAMUS://Arch Bishop - if (sd) tick>>=1; //Half duration for players. - case SC_STONE: - case SC_FREEZE: - sc_def = 3 +status->mdef; - break; - case SC_CURSE: - //Special property: inmunity when luk is greater than level or zero - if (status->luk > status_get_lv(bl) || status->luk == 0) - return 0; - else - sc_def = 3 +status->luk; - tick_def = status->vit; - break; - case SC_BLIND: - if( sc && sc->data[SC__UNLUCKY] ) - return tick; - sc_def = 3 +(status->vit + status->int_)/2; - break; - case SC_CONFUSION: - sc_def = 3 +(status->str + status->int_)/2; - break; - case SC_ANKLE: - if(status->mode&MD_BOSS) // Lasts 5 times less on bosses - tick /= 5; - sc_def = status->agi / 2; - break; - case SC_MAGICMIRROR: - case SC_ARMORCHANGE: - if (sd) //Duration greatly reduced for players. - tick /= 15; - //No defense against it (buff). - rate -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; // Lineal Reduction of Rate - break; + case SC_STUN: + case SC_POISON: + if( sc && sc->data[SC__UNLUCKY] ) + return tick; + case SC_DPOISON: + case SC_SILENCE: + case SC_BLEEDING: + sc_def = status->vit*100; + sc_def2 = status->luk*10; + break; + case SC_SLEEP: + sc_def = status->int_*100; + sc_def2 = status->luk*10; + break; + case SC_DEEPSLEEP: + sc_def = status->int_*50; + tick_def = status->int_*10 + status_get_lv(bl) * 65 / 10; //Seems to be -1 sec every 10 int and -5% chance every 10 int. + break; + case SC_DECREASEAGI: + case SC_ADORAMUS: //Arch Bishop + if (sd) tick>>=1; //Half duration for players. + case SC_STONE: + //Impossible to reduce duration with stats + tick_def = 0; + tick_def2 = 0; + case SC_FREEZE: + sc_def = status->mdef*100; + sc_def2 = status->luk*10; + break; + case SC_CURSE: + //Special property: inmunity when luk is greater than level or zero + if (status->luk > status_get_lv(bl) || status->luk == 0) + return 0; + sc_def = status->luk*100; + sc_def2 = status->luk*10; + tick_def = status->vit*100; + break; + case SC_BLIND: + if( sc && sc->data[SC__UNLUCKY] ) + return tick; + sc_def = (status->vit + status->int_)*50; + sc_def2 = status->luk*10; + break; + case SC_CONFUSION: + sc_def = (status->str + status->int_)*50; + sc_def2 = status->luk*10; + break; + case SC_ANKLE: + if(status->mode&MD_BOSS) // Lasts 5 times less on bosses + tick /= 5; + sc_def = status->agi*50; + break; + case SC_MAGICMIRROR: + case SC_ARMORCHANGE: + if (sd) //Duration greatly reduced for players. + tick /= 15; + sc_def2 = status_get_lv(bl)*20 + status->vit*25 + status->agi*10; // Lineal Reduction of Rate + tick_def2 = 0; //No duration reduction + break; case SC_MARSHOFABYSS: //5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second } - tick -= (status->int_ + status->luk) / 20 * 1000; + tick_def2 = (status->int_ + status->luk)*50; break; case SC_STASIS: - //5 second (fixed) + { Stasis Skill level * 5 - (Target�s VIT + DEX) / 20 } - tick -= (status->vit + status->dex) / 20 * 1000; - break; - case SC_WHITEIMPRISON: - if( tick == 5000 ) // 100% on caster + //5 second (fixed) + { Stasis Skill level * 5 - (Target's VIT + DEX) / 20 } + tick_def2 = (status->vit + status->dex)*50; break; if( bl->type == BL_PC ) tick -= (status_get_lv(bl) / 5 + status->vit / 4 + status->agi / 10)*100; @@ -6323,51 +6271,58 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti if (sd) { - if (battle_config.pc_sc_def_rate != 100) + if (battle_config.pc_sc_def_rate != 100) { sc_def = sc_def*battle_config.pc_sc_def_rate/100; + sc_def2 = sc_def2*battle_config.pc_sc_def_rate/100; + } - if (sc_def < battle_config.pc_max_sc_def) - sc_def += (battle_config.pc_max_sc_def - sc_def)* - status->luk/battle_config.pc_luk_sc_def; - else - sc_def = battle_config.pc_max_sc_def; + sc_def = min(sc_def, battle_config.pc_max_sc_def*100); + sc_def2 = min(sc_def2, battle_config.pc_max_sc_def*100); - if (tick_def) { - if (battle_config.pc_sc_def_rate != 100) - tick_def = tick_def*battle_config.pc_sc_def_rate/100; + if (tick_def > 0 && battle_config.pc_sc_def_rate != 100) { + tick_def = tick_def*battle_config.pc_sc_def_rate/100; + tick_def2 = tick_def2*battle_config.pc_sc_def_rate/100; } - } else { - if (battle_config.mob_sc_def_rate != 100) + if (battle_config.mob_sc_def_rate != 100) { sc_def = sc_def*battle_config.mob_sc_def_rate/100; + sc_def2 = sc_def2*battle_config.mob_sc_def_rate/100; + } - if (sc_def < battle_config.mob_max_sc_def) - sc_def += (battle_config.mob_max_sc_def - sc_def)* - status->luk/battle_config.mob_luk_sc_def; - else - sc_def = battle_config.mob_max_sc_def; + sc_def = min(sc_def, battle_config.mob_max_sc_def*100); + sc_def2 = min(sc_def2, battle_config.mob_max_sc_def*100); - if (tick_def) { - if (battle_config.mob_sc_def_rate != 100) - tick_def = tick_def*battle_config.mob_sc_def_rate/100; + if (tick_def > 0 && battle_config.mob_sc_def_rate != 100) { + tick_def = tick_def*battle_config.mob_sc_def_rate/100; + tick_def2 = tick_def2*battle_config.mob_sc_def_rate/100; } } if (sc) { if (sc->data[SC_SCRESIST]) - sc_def += sc->data[SC_SCRESIST]->val1; //Status resist + sc_def += sc->data[SC_SCRESIST]->val1*100; //Status resist else if (sc->data[SC_SIEGFRIED]) - sc_def += sc->data[SC_SIEGFRIED]->val3; //Status resistance. + sc_def += sc->data[SC_SIEGFRIED]->val3*100; //Status resistance. } //When no tick def, reduction is the same for both. - if( !tick_def && type != SC_STONE ) //Recent tests show duration of petrify isn't reduced by MDEF. [Inkfish] + if(tick_def < 0) tick_def = sc_def; + if(tick_def2 < 0) + tick_def2 = sc_def2; //Natural resistance if (!(flag&8)) { - rate -= rate*sc_def/100; + rate -= rate*sc_def/10000; + rate -= sc_def2; + + //Minimum chances + switch (type) { + case SC_BITE: + rate = max(rate, 5000); //Minimum of 50% + break; + } //Item resistance (only applies to rate%) if(sd && SC_COMMON_MIN <= type && type <= SC_COMMON_MAX) @@ -6378,24 +6333,83 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti rate -= rate*sd->sc.data[SC_COMMONSC_RESIST]->val1/100; } } + if (!(rnd()%10000 < rate)) return 0; - //Why would a status start with no duration? Presume it has - //duration defined elsewhere. - if (!tick) return 1; + //Even if a status change doesn't have a duration, it should still trigger + if (tick < 1) return 1; //Rate reduction - if (flag&2) + if (flag&2) return tick; - tick -= tick*tick_def/100; - // Changed to 5 seconds according to recent tests [Playtester] - if (type == SC_ANKLE && tick < 5000) - tick = 5000; - return tick<=0?0:tick; -} + tick -= tick*tick_def/10000; + tick -= tick_def2; + + //Minimum durations + switch (type) { + case SC_ANKLE: + case SC_MARSHOFABYSS: + case SC_STASIS: + tick = max(tick, 5000); //Minimum duration 5s + break; + case SC_BURNING: + case SC_FREEZING: + tick = max(tick, 10000); //Minimum duration 10s + break; + default: + //Skills need to trigger even if the duration is reduced below 1ms + tick = max(tick, 1); + break; + } + return tick; +} +/* [Ind/Hercules] fast-checkin sc-display array */ +void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) { + struct sc_display_entry *entry = ers_alloc(pc_sc_display_ers, struct sc_display_entry); + + entry->type = type; + entry->val1 = dval1; + entry->val2 = dval2; + entry->val3 = dval3; + + RECREATE(sd->sc_display, struct sc_display_entry *, ++sd->sc_display_count); + sd->sc_display[ sd->sc_display_count - 1 ] = entry; +} +void status_display_remove(struct map_session_data *sd, enum sc_type type) { + int i; + + for( i = 0; i < sd->sc_display_count; i++ ) { + if( sd->sc_display[i]->type == type ) + break; + } + + if( i != sd->sc_display_count ) { + int cursor; + + ers_free(pc_sc_display_ers, sd->sc_display[i]); + sd->sc_display[i] = NULL; + + /* the all-mighty compact-o-matic */ + for( i = 0, cursor = 0; i < sd->sc_display_count; i++ ) { + if( sd->sc_display[i] == NULL ) + continue; + + if( i != cursor ) { + sd->sc_display[cursor] = sd->sc_display[i]; + } + + cursor++; + } + + if( !(sd->sc_display_count = cursor) ) { + aFree(sd->sc_display); + sd->sc_display = NULL; + } + } +} /*========================================== * Starts a status change. * 'type' = type, 'val1~4' depend on the type. @@ -6407,15 +6421,13 @@ int status_get_sc_def(struct block_list *bl, enum sc_type type, int rate, int ti * &4: sc_data loaded, no value has to be altered. * &8: rate should not be reduced *------------------------------------------*/ -int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) -{ +int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,int tick,int flag) { struct map_session_data *sd = NULL; struct status_change* sc; struct status_change_entry* sce; struct status_data *status; struct view_data *vd; int opt_flag, calc_flag, undead_flag, val_flag = 0, tick_time = 0; - bool sc_isnew = true; nullpo_ret(bl); sc = status_get_sc(bl); @@ -6499,7 +6511,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if( !tick ) return 0; } - undead_flag = battle_check_undead(status->race,status->def_ele); + undead_flag = battle->check_undead(status->race,status->def_ele); //Check for inmunities / sc fails switch (type) { case SC_ANGRIFFS_MODUS: @@ -6562,7 +6574,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind] break; case SC_ADRENALINE: - if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE))) + if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE))) return 0; if (sc->data[SC_QUAGMIRE] || sc->data[SC_DECREASEAGI] || @@ -6571,7 +6583,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; break; case SC_ADRENALINE2: - if(sd && !pc_check_weapontype(sd,skill_get_weapontype(BS_ADRENALINE2))) + if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE2))) return 0; if (sc->data[SC_QUAGMIRE] || sc->data[SC_DECREASEAGI] @@ -6609,7 +6621,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val //Due to the cloaking card, we have to check the wall versus to known //skill level rather than the used one. [Skotlex] //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL)) - if( sd && pc_checkskill(sd, AS_CLOAKING) < 3 && !skill_check_cloaking(bl,NULL) ) + if( sd && pc_checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(bl,NULL) ) return 0; break; case SC_MODECHANGE: @@ -6640,11 +6652,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val opt_flag = 0; //Reuse to check success condition. if(sd->bonus.unstripable_equip&EQP_WEAPON) return 0; - i = sd->equip_index[EQI_HAND_L]; - if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { - opt_flag|=1; - pc_unequipitem(sd,i,3); //L-hand weapon - } i = sd->equip_index[EQI_HAND_R]; if (i>=0 && sd->inventory_data[i] && sd->inventory_data[i]->type == IT_WEAPON) { @@ -6750,7 +6757,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val return 0; break; case SC_CAMOUFLAGE: - if( sd && pc_checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill_check_camouflage(bl,NULL) ) + if( sd && pc_checkskill(sd, RA_CAMOUFLAGE) < 3 && !skill->check_camouflage(bl,NULL) ) return 0; break; case SC__STRIPACCESSORY: @@ -7167,1448 +7174,1464 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val vd = status_get_viewdata(bl); calc_flag = StatusChangeFlagTable[type]; - if(!(flag&4)) //&4 - Do not parse val settings when loading SCs - switch(type) - { - case SC_DECREASEAGI: - case SC_INCREASEAGI: - val2 = 2 + val1; //Agi change - break; - case SC_ENDURE: - val2 = 7; // Hit-count [Celest] - if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4 ) - { - struct map_session_data *tsd; - if( sd ) + if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs + switch(type) { + case SC_DECREASEAGI: + case SC_INCREASEAGI: + val2 = 2 + val1; //Agi change + break; + case SC_ENDURE: + val2 = 7; // Hit-count [Celest] + if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map[bl->m].flag.battleground && !val4 ) { - int i; - for( i = 0; i < 5; i++ ) + struct map_session_data *tsd; + if( sd ) { - if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) - status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + int i; + for( i = 0; i < 5; i++ ) + { + if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); + } } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); } - else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status_change_start(&tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1); - } - //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) - if( val4 ) + //val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk) + if( val4 ) + tick = -1; + break; + case SC_AUTOBERSERK: + if (status->hp < status->max_hp>>2 && + (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) + sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); tick = -1; - break; - case SC_AUTOBERSERK: - if (status->hp < status->max_hp>>2 && - (!sc->data[SC_PROVOKE] || sc->data[SC_PROVOKE]->val2==0)) - sc_start4(bl,SC_PROVOKE,100,10,1,0,0,60000); - tick = -1; - break; - case SC_SIGNUMCRUCIS: - val2 = 10 + 4*val1; //Def reduction - tick = -1; - clif_emotion(bl,E_SWT); - break; - case SC_MAXIMIZEPOWER: - tick_time = val2 = tick>0?tick:60000; - tick = -1; // duration sent to the client should be infinite - break; - case SC_EDP: // [Celest] - val2 = val1 + 2; //Chance to Poison enemies. -#ifndef RENEWAL_EDP - val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) -#endif - if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds - tick += pc_checkskill(sd,GC_RESEARCHNEWPOISON)*3000; - break; - case SC_POISONREACT: - val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex] - val3=50; // + 5*val1; //Chance to counter. [Skotlex] - break; - case SC_MAGICROD: - val2 = val1*20; //SP gained - break; - case SC_KYRIE: - val2 = (int64)status->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb - val3 = (val1 / 2 + 5); //Hits - break; - case SC_MAGICPOWER: - //val1: Skill lv - val2 = 1; //Lasts 1 invocation - val3 = 5*val1; //Matk% increase - val4 = 0; // 0 = ready to be used, 1 = activated and running - break; - case SC_SACRIFICE: - val2 = 5; //Lasts 5 hits - tick = -1; - break; - case SC_ENCPOISON: - val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate - case SC_ASPERSIO: - case SC_FIREWEAPON: - case SC_WATERWEAPON: - case SC_WINDWEAPON: - case SC_EARTHWEAPON: - case SC_SHADOWWEAPON: - case SC_GHOSTWEAPON: - skill_enchant_elemental_end(bl,type); - break; - case SC_ELEMENTALCHANGE: - // val1 : Element Lvl (if called by skill lvl 1, takes random value between 1 and 4) - // val2 : Element (When no element, random one is picked) - // val3 : 0 = called by skill 1 = called by script (fixed level) - if( !val2 ) val2 = rnd()%ELE_MAX; - - if( val1 == 1 && val3 == 0 ) - val1 = 1 + rnd()%4; - else if( val1 > 4 ) - val1 = 4; // Max Level - val3 = 0; // Not need to keep this info. - break; - case SC_PROVIDENCE: - val2=val1*5; //Race/Ele resist - break; - case SC_REFLECTSHIELD: - val2=10+val1*3; // %Dmg reflected - if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) - { - struct map_session_data *tsd; - if( sd ) + break; + case SC_SIGNUMCRUCIS: + val2 = 10 + 4*val1; //Def reduction + tick = -1; + clif->emotion(bl,E_SWT); + break; + case SC_MAXIMIZEPOWER: + tick_time = val2 = tick>0?tick:60000; + tick = -1; // duration sent to the client should be infinite + break; + case SC_EDP: // [Celest] + val2 = val1 + 2; //Chance to Poison enemies. + #ifndef RENEWAL_EDP + val3 = 50*(val1+1); //Damage increase (+50 +50*lv%) + #endif + if( sd )//[Ind] - iROwiki says each level increases its duration by 3 seconds + tick += pc_checkskill(sd,GC_RESEARCHNEWPOISON)*3000; + break; + case SC_POISONREACT: + val2=(val1+1)/2 + val1/10; // Number of counters [Skotlex] + val3=50; // + 5*val1; //Chance to counter. [Skotlex] + break; + case SC_MAGICROD: + val2 = val1*20; //SP gained + break; + case SC_KYRIE: + val2 = (int64)status->max_hp * (val1 * 2 + 10) / 100; //%Max HP to absorb + val3 = (val1 / 2 + 5); //Hits + break; + case SC_MAGICPOWER: + //val1: Skill lv + val2 = 1; //Lasts 1 invocation + val3 = 5*val1; //Matk% increase + val4 = 0; // 0 = ready to be used, 1 = activated and running + break; + case SC_SACRIFICE: + val2 = 5; //Lasts 5 hits + tick = -1; + break; + case SC_ENCPOISON: + val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate + case SC_ASPERSIO: + case SC_FIREWEAPON: + case SC_WATERWEAPON: + case SC_WINDWEAPON: + case SC_EARTHWEAPON: + case SC_SHADOWWEAPON: + case SC_GHOSTWEAPON: + skill->enchant_elemental_end(bl,type); + break; + case SC_ELEMENTALCHANGE: + // val1 : Element Lvl (if called by skill lvl 1, takes random value between 1 and 4) + // val2 : Element (When no element, random one is picked) + // val3 : 0 = called by skill 1 = called by script (fixed level) + if( !val2 ) val2 = rnd()%ELE_MAX; + + if( val1 == 1 && val3 == 0 ) + val1 = 1 + rnd()%4; + else if( val1 > 4 ) + val1 = 4; // Max Level + val3 = 0; // Not need to keep this info. + break; + case SC_PROVIDENCE: + val2=val1*5; //Race/Ele resist + break; + case SC_REFLECTSHIELD: + val2=10+val1*3; // %Dmg reflected + if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) { - int i; - for( i = 0; i < 5; i++ ) + struct map_session_data *tsd; + if( sd ) { - if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + int i; + for( i = 0; i < 5; i++ ) + { + if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + } } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } - else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); - } - break; - case SC_STRIPWEAPON: - if (!sd) //Watk reduction - val2 = 25; - break; - case SC_STRIPSHIELD: - if (!sd) //Def reduction - val2 = 15; - break; - case SC_STRIPARMOR: - if (!sd) //Vit reduction - val2 = 40; - break; - case SC_STRIPHELM: - if (!sd) //Int reduction - val2 = 40; - break; - case SC_AUTOSPELL: - //Val1 Skill LV of Autospell - //Val2 Skill ID to cast - //Val3 Max Lv to cast - val4 = 5 + val1*2; //Chance of casting - break; - case SC_VOLCANO: - val2 = val1*10; //Watk increase -#ifndef RENEWAL - if (status->def_ele != ELE_FIRE) - val2 = 0; -#endif - break; - case SC_VIOLENTGALE: - val2 = val1*3; //Flee increase - #ifndef RENEWAL - if (status->def_ele != ELE_WIND) - val2 = 0; - #endif - break; - case SC_DELUGE: - val2 = deluge_eff[val1-1]; //HP increase -#ifndef RENEWAL - if(status->def_ele != ELE_WATER) - val2 = 0; -#endif - break; - case SC_SUITON: - if (!val2 || (sd && (sd->class_&MAPID_UPPERMASK) == MAPID_NINJA)) { - //No penalties. - val2 = 0; //Agi penalty - val3 = 0; //Walk speed penalty break; - } - val3 = 50; - val2 = 3*((val1+1)/3); - if (val1 > 4) val2--; - break; - case SC_ONEHAND: - case SC_TWOHANDQUICKEN: - val2 = 300; - if (val1 > 10) //For boss casted skills [Skotlex] - val2 += 20*(val1-10); - break; - case SC_MERC_QUICKEN: - val2 = 300; - break; -#ifndef RENEWAL - case SC_SPEARQUICKEN: - val2 = 200+10*val1; - break; -#endif - case SC_DANCING: - //val1 : Skill ID + LV - //val2 : Skill Group of the Dance. - //val3 : Brings the skill_lv (merged into val1 here) - //val4 : Partner - if (val1 == CG_MOONLIT) - clif_status_change(bl,SI_MOONLIT,1,tick,0, 0, 0); - val1|= (val3<<16); - val3 = tick/1000; //Tick duration - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_LONGING: - val2 = 500-100*val1; //Aspd penalty. - break; - case SC_EXPLOSIONSPIRITS: - val2 = 75 + 25*val1; //Cri bonus - break; - - case SC_ASPDPOTION0: - case SC_ASPDPOTION1: - case SC_ASPDPOTION2: - case SC_ASPDPOTION3: - val2 = 50*(2+type-SC_ASPDPOTION0); - break; + case SC_STRIPWEAPON: + if (!sd) //Watk reduction + val2 = 25; + break; + case SC_STRIPSHIELD: + if (!sd) //Def reduction + val2 = 15; + break; + case SC_STRIPARMOR: + if (!sd) //Vit reduction + val2 = 40; + break; + case SC_STRIPHELM: + if (!sd) //Int reduction + val2 = 40; + break; + case SC_AUTOSPELL: + //Val1 Skill LV of Autospell + //Val2 Skill ID to cast + //Val3 Max Lv to cast + val4 = 5 + val1*2; //Chance of casting + break; + case SC_VOLCANO: + val2 = val1*10; //Watk increase + #ifndef RENEWAL + if (status->def_ele != ELE_FIRE) + val2 = 0; + #endif + break; + case SC_VIOLENTGALE: + val2 = val1*3; //Flee increase + #ifndef RENEWAL + if (status->def_ele != ELE_WIND) + val2 = 0; + #endif + break; + case SC_DELUGE: + val2 = deluge_eff[val1-1]; //HP increase + #ifndef RENEWAL + if(status->def_ele != ELE_WATER) + val2 = 0; + #endif + break; + case SC_SUITON: + if (!val2 || (sd && (sd->class_&MAPID_BASEMASK) == MAPID_NINJA)) { + //No penalties. + val2 = 0; //Agi penalty + val3 = 0; //Walk speed penalty + break; + } + val3 = 50; + val2 = 3*((val1+1)/3); + if (val1 > 4) val2--; + break; + case SC_ONEHAND: + case SC_TWOHANDQUICKEN: + val2 = 300; + if (val1 > 10) //For boss casted skills [Skotlex] + val2 += 20*(val1-10); + break; + case SC_MERC_QUICKEN: + val2 = 300; + break; + #ifndef RENEWAL_ASPD + case SC_SPEARQUICKEN: + val2 = 200+10*val1; + break; + #endif + case SC_DANCING: + //val1 : Skill ID + LV + //val2 : Skill Group of the Dance. + //val3 : Brings the skill_lv (merged into val1 here) + //val4 : Partner + if (val1 == CG_MOONLIT) + clif->status_change(bl,SI_MOONLIT,1,tick,0, 0, 0); + val1|= (val3<<16); + val3 = tick/1000; //Tick duration + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_LONGING: + val2 = 500-100*val1; //Aspd penalty. + break; + case SC_EXPLOSIONSPIRITS: + val2 = 75 + 25*val1; //Cri bonus + break; - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - if (!vd) return 0; - //Store previous values as they could be removed. - val1 = vd->class_; - val2 = vd->weapon; - val3 = vd->shield; - val4 = vd->cloth_color; - unit_stop_attack(bl); - clif_changelook(bl,LOOK_WEAPON,0); - clif_changelook(bl,LOOK_SHIELD,0); - clif_changelook(bl,LOOK_BASE,type==SC_WEDDING?JOB_WEDDING:type==SC_XMAS?JOB_XMAS:JOB_SUMMER); - clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - break; - case SC_NOCHAT: - // [GodLesZ] FIXME: is this correct? a hardcoded interval of 60sec? what about configuration ?_? - tick = 60000; - val1 = battle_config.manner_system; //Mute filters. - if (sd) - { - clif_changestatus(sd,SP_MANNER,sd->status.manner); - clif_updatestatus(sd,SP_MANNER); - } - break; + case SC_ASPDPOTION0: + case SC_ASPDPOTION1: + case SC_ASPDPOTION2: + case SC_ASPDPOTION3: + val2 = 50*(2+type-SC_ASPDPOTION0); + break; - case SC_STONE: - val3 = tick/1000; //Petrified HP-damage iterations. - if(val3 < 1) val3 = 1; - tick = val4; //Petrifying time. - tick = max(tick, 1000); //Min time - calc_flag = 0; //Actual status changes take effect on petrified state. - break; + case SC_WEDDING: + case SC_XMAS: + case SC_SUMMER: + case SC_HANBOK: + if (!vd) return 0; + //Store previous values as they could be removed. + unit_stop_attack(bl); + break; + case SC_NOCHAT: + // [GodLesZ] FIXME: is this correct? a hardcoded interval of 60sec? what about configuration ?_? + tick = 60000; + val1 = battle_config.manner_system; //Mute filters. + if (sd) + { + clif->changestatus(sd,SP_MANNER,sd->status.manner); + clif->updatestatus(sd,SP_MANNER); + } + break; - case SC_DPOISON: - //Lose 10/15% of your life as long as it doesn't brings life below 25% - if (status->hp > status->max_hp>>2) { - int diff = status->max_hp*(bl->type==BL_PC?10:15)/100; - if (status->hp - diff < status->max_hp>>2) - diff = status->hp - (status->max_hp>>2); - if( val2 && bl->type == BL_MOB ) { - struct block_list* src = map_id2bl(val2); - if( src ) - mob_log_damage((TBL_MOB*)bl,src,diff); - } - status_zap(bl, diff, 0); - } - // fall through - case SC_POISON: - val3 = tick/1000; //Damage iterations - if(val3 < 1) val3 = 1; - tick_time = 1000; // [GodLesZ] tick time - //val4: HP damage - if (bl->type == BL_PC) - val4 = (type == SC_DPOISON) ? 3 + status->max_hp/50 : 3 + status->max_hp*3/200; - else - val4 = (type == SC_DPOISON) ? 3 + status->max_hp/100 : 3 + status->max_hp/200; + case SC_STONE: + val3 = tick/1000; //Petrified HP-damage iterations. + if(val3 < 1) val3 = 1; + tick = val4; //Petrifying time. + tick = max(tick, 1000); //Min time + calc_flag = 0; //Actual status changes take effect on petrified state. + break; - break; - case SC_CONFUSION: - clif_emotion(bl,E_WHAT); - break; - case SC_BLEEDING: - val4 = tick/10000; - if (!val4) val4 = 1; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - if( val1 == 0 ) return 0; - // val1 = heal percent/amout - // val2 = seconds between heals - // val4 = total of heals - if( val2 < 1 ) val2 = 1; - if( (val4 = tick/(val2 * 1000)) < 1 ) - val4 = 1; - tick_time = val2 * 1000; // [GodLesZ] tick time - break; - case SC_BOSSMAPINFO: - if( sd != NULL ) - { - struct mob_data *boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map - if( boss_md == NULL || boss_md->bl.prev == NULL ) - { // No MVP on this map - MVP is dead - clif_bossmapinfo(sd->fd, boss_md, 1); - return 0; // No need to start SC + case SC_DPOISON: + //Lose 10/15% of your life as long as it doesn't brings life below 25% + if (status->hp > status->max_hp>>2) { + int diff = status->max_hp*(bl->type==BL_PC?10:15)/100; + if (status->hp - diff < status->max_hp>>2) + diff = status->hp - (status->max_hp>>2); + if( val2 && bl->type == BL_MOB ) { + struct block_list* src = map_id2bl(val2); + if( src ) + mob_log_damage((TBL_MOB*)bl,src,diff); } - val1 = boss_md->bl.id; - if( (val4 = tick/1000) < 1 ) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time + status_zap(bl, diff, 0); } - break; - case SC_HIDING: - val2 = tick/1000; + // fall through + case SC_POISON: + val3 = tick/1000; //Damage iterations + if(val3 < 1) val3 = 1; tick_time = 1000; // [GodLesZ] tick time - val3 = 0; // unused, previously speed adjustment - val4 = val1+3; //Seconds before SP substraction happen. - break; - case SC_CHASEWALK: - val2 = tick>0?tick:10000; //Interval at which SP is drained. - val3 = 35 - 5 * val1; //Speed adjustment. - if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE) - val3 -= 40; - val4 = 10+val1*2; //SP cost. - if (map_flag_gvg(bl->m) || map[bl->m].flag.battleground) val4 *= 5; - break; - case SC_CLOAKING: - if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] - val1 = 10; - tick_time = val2 = tick>0?tick:60000; //SP consumption rate. - tick = -1; // duration sent to the client should be infinite - val3 = 0; // unused, previously walk speed adjustment - //val4&1 signals the presence of a wall. - //val4&2 makes cloak not end on normal attacks [Skotlex] - //val4&4 makes cloak not end on using skills - if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB*)bl)->special_state.clone) ) //Standard cloaking. - val4 |= battle_config.pc_cloak_check_type&7; + //val4: HP damage + if (bl->type == BL_PC) + val4 = (type == SC_DPOISON) ? 3 + status->max_hp/50 : 3 + status->max_hp*3/200; else - val4 |= battle_config.monster_cloak_check_type&7; - break; - case SC_SIGHT: /* splash status */ - case SC_RUWACH: - case SC_SIGHTBLASTER: - val3 = skill_get_splash(val2, val1); //Val2 should bring the skill-id. - val2 = tick/250; - tick_time = 10; // [GodLesZ] tick time - break; + val4 = (type == SC_DPOISON) ? 3 + status->max_hp/100 : 3 + status->max_hp/200; - //Permanent effects. - case SC_AETERNA: - case SC_MODECHANGE: - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_BROKENWEAPON: - case SC_BROKENARMOR: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYCOUNTER: - case SC_READYTURN: - case SC_DODGE: - case SC_PUSH_CART: - tick = -1; break; - - case SC_AUTOGUARD: - if( !(flag&1) ) - { - struct map_session_data *tsd; - int i,t; - for( i = val2 = 0; i < val1; i++) + case SC_CONFUSION: + clif->emotion(bl,E_WHAT); + break; + case SC_BLEEDING: + val4 = tick/10000; + if (!val4) val4 = 1; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + if( val1 == 0 ) return 0; + // val1 = heal percent/amout + // val2 = seconds between heals + // val4 = total of heals + if( val2 < 1 ) val2 = 1; + if( (val4 = tick/(val2 * 1000)) < 1 ) + val4 = 1; + tick_time = val2 * 1000; // [GodLesZ] tick time + break; + case SC_BOSSMAPINFO: + if( sd != NULL ) { - t = 5-(i>>1); - val2 += (t < 0)? 1:t; + struct mob_data *boss_md = map_getmob_boss(bl->m); // Search for Boss on this Map + if( boss_md == NULL || boss_md->bl.prev == NULL ) + { // No MVP on this map - MVP is dead + clif->bossmapinfo(sd->fd, boss_md, 1); + return 0; // No need to start SC + } + val1 = boss_md->bl.id; + if( (val4 = tick/1000) < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time } + break; + case SC_HIDING: + val2 = tick/1000; + tick_time = 1000; // [GodLesZ] tick time + val3 = 0; // unused, previously speed adjustment + val4 = val1+3; //Seconds before SP substraction happen. + break; + case SC_CHASEWALK: + val2 = tick>0?tick:10000; //Interval at which SP is drained. + val3 = 35 - 5 * val1; //Speed adjustment. + if (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE) + val3 -= 40; + val4 = 10+val1*2; //SP cost. + if (map_flag_gvg(bl->m) || map[bl->m].flag.battleground) val4 *= 5; + break; + case SC_CLOAKING: + if (!sd) //Monsters should be able to walk with no penalties. [Skotlex] + val1 = 10; + tick_time = val2 = tick>0?tick:60000; //SP consumption rate. + tick = -1; // duration sent to the client should be infinite + val3 = 0; // unused, previously walk speed adjustment + //val4&1 signals the presence of a wall. + //val4&2 makes cloak not end on normal attacks [Skotlex] + //val4&4 makes cloak not end on using skills + if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB*)bl)->special_state.clone) ) //Standard cloaking. + val4 |= battle_config.pc_cloak_check_type&7; + else + val4 |= battle_config.monster_cloak_check_type&7; + break; + case SC_SIGHT: /* splash status */ + case SC_RUWACH: + case SC_SIGHTBLASTER: + val3 = skill->get_splash(val2, val1); //Val2 should bring the skill-id. + val2 = tick/250; + tick_time = 10; // [GodLesZ] tick time + break; - if( bl->type&(BL_PC|BL_MER) ) + //Permanent effects. + case SC_AETERNA: + case SC_MODECHANGE: + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_BROKENWEAPON: + case SC_BROKENARMOR: + case SC_READYSTORM: + case SC_READYDOWN: + case SC_READYCOUNTER: + case SC_READYTURN: + case SC_DODGE: + case SC_PUSH_CART: + case SC_ALL_RIDING: + tick = -1; + break; + + case SC_AUTOGUARD: + if( !(flag&1) ) { - if( sd ) + struct map_session_data *tsd; + int i,t; + for( i = val2 = 0; i < val1; i++) { - for( i = 0; i < 5; i++ ) + t = 5-(i>>1); + val2 += (t < 0)? 1:t; + } + + if( bl->type&(BL_PC|BL_MER) ) + { + if( sd ) { - if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + for( i = 0; i < 5; i++ ) + { + if( sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i])) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); + } } + else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) + status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } - else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) ) - status_change_start(&tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1); } - } - break; - - case SC_DEFENDER: - if (!(flag&1)) - { - val2 = 5 + 15*val1; //Damage reduction - val3 = 0; // unused, previously speed adjustment - val4 = 250 - 50*val1; //Aspd adjustment + break; - if (sd) + case SC_DEFENDER: + if (!(flag&1)) { - struct map_session_data *tsd; - int i; - for (i = 0; i < 5; i++) - { //See if there are devoted characters, and pass the status to them. [Skotlex] - if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i]))) - status_change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); + val2 = 5 + 15*val1; //Damage reduction + val3 = 0; // unused, previously speed adjustment + val4 = 250 - 50*val1; //Aspd adjustment + + if (sd) + { + struct map_session_data *tsd; + int i; + for (i = 0; i < 5; i++) + { //See if there are devoted characters, and pass the status to them. [Skotlex] + if (sd->devotion[i] && (tsd = map_id2sd(sd->devotion[i]))) + status_change_start(&tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1); + } } } - } - break; + break; - case SC_TENSIONRELAX: - if (sd) { - pc_setsit(sd); - clif_sitting(&sd->bl); - } - val2 = 12; //SP cost - val4 = 10000; //Decrease at 10secs intervals. - val3 = tick/val4; - tick = -1; // duration sent to the client should be infinite - tick_time = val4; // [GodLesZ] tick time - break; - case SC_PARRYING: - val2 = 20 + val1*3; //Block Chance - break; + case SC_TENSIONRELAX: + if (sd) { + pc_setsit(sd); + clif->sitting(&sd->bl); + } + val2 = 12; //SP cost + val4 = 10000; //Decrease at 10secs intervals. + val3 = tick/val4; + tick = -1; // duration sent to the client should be infinite + tick_time = val4; // [GodLesZ] tick time + break; + case SC_PARRYING: + val2 = 20 + val1*3; //Block Chance + break; - case SC_WINDWALK: - val2 = (val1+1)/2; // Flee bonus is 1/1/2/2/3/3/4/4/5/5 - break; + case SC_WINDWALK: + val2 = (val1+1)/2; // Flee bonus is 1/1/2/2/3/3/4/4/5/5 + break; - case SC_JOINTBEAT: - if( val2&BREAK_NECK ) - sc_start2(bl,SC_BLEEDING,100,val1,val3,skill_get_time2(status_sc2skill(type),val1)); - break; + case SC_JOINTBEAT: + if( val2&BREAK_NECK ) + sc_start2(bl,SC_BLEEDING,100,val1,val3,skill->get_time2(status_sc2skill(type),val1)); + break; - case SC_BERSERK: - if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) - sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); - case SC__BLOODYLUST: - //HP healing is performing after the calc_status call. - //Val2 holds HP penalty - if (!val4) val4 = skill_get_time2(status_sc2skill(type),val1); - if (!val4) val4 = 10000; //Val4 holds damage interval - val3 = tick/val4; //val3 holds skill duration - tick_time = val4; // [GodLesZ] tick time - break; + case SC_BERSERK: + if (!sc->data[SC_ENDURE] || !sc->data[SC_ENDURE]->val4) + sc_start4(bl, SC_ENDURE, 100,10,0,0,2, tick); + case SC__BLOODYLUST: + //HP healing is performing after the calc_status call. + //Val2 holds HP penalty + if (!val4) val4 = skill->get_time2(status_sc2skill(type),val1); + if (!val4) val4 = 10000; //Val4 holds damage interval + val3 = tick/val4; //val3 holds skill duration + tick_time = val4; // [GodLesZ] tick time + break; - case SC_GOSPEL: - if(val4 == BCT_SELF) { // self effect - val2 = tick/10000; - tick_time = 10000; // [GodLesZ] tick time - status_change_clear_buffs(bl,3); //Remove buffs/debuffs - } - break; + case SC_GOSPEL: + if(val4 == BCT_SELF) { // self effect + val2 = tick/10000; + tick_time = 10000; // [GodLesZ] tick time + status_change_clear_buffs(bl,3); //Remove buffs/debuffs + } + break; - case SC_MARIONETTE: - { - int stat; + case SC_MARIONETTE: + { + int stat; - val3 = 0; - val4 = 0; - stat = ( sd ? sd->status.str : status_get_base_status(bl)->str ) / 2; val3 |= cap_value(stat,0,0xFF)<<16; - stat = ( sd ? sd->status.agi : status_get_base_status(bl)->agi ) / 2; val3 |= cap_value(stat,0,0xFF)<<8; - stat = ( sd ? sd->status.vit : status_get_base_status(bl)->vit ) / 2; val3 |= cap_value(stat,0,0xFF); - stat = ( sd ? sd->status.int_: status_get_base_status(bl)->int_) / 2; val4 |= cap_value(stat,0,0xFF)<<16; - stat = ( sd ? sd->status.dex : status_get_base_status(bl)->dex ) / 2; val4 |= cap_value(stat,0,0xFF)<<8; - stat = ( sd ? sd->status.luk : status_get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF); - break; - } - case SC_MARIONETTE2: - { - int stat,max_stat; - // fetch caster information - struct block_list *pbl = map_id2bl(val1); - struct status_change *psc = pbl?status_get_sc(pbl):NULL; - struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE]:NULL; - // fetch target's stats - struct status_data* status = status_get_status_data(bl); // battle status - - if (!psce) - return 0; + val3 = 0; + val4 = 0; + stat = ( sd ? sd->status.str : status_get_base_status(bl)->str ) / 2; val3 |= cap_value(stat,0,0xFF)<<16; + stat = ( sd ? sd->status.agi : status_get_base_status(bl)->agi ) / 2; val3 |= cap_value(stat,0,0xFF)<<8; + stat = ( sd ? sd->status.vit : status_get_base_status(bl)->vit ) / 2; val3 |= cap_value(stat,0,0xFF); + stat = ( sd ? sd->status.int_: status_get_base_status(bl)->int_) / 2; val4 |= cap_value(stat,0,0xFF)<<16; + stat = ( sd ? sd->status.dex : status_get_base_status(bl)->dex ) / 2; val4 |= cap_value(stat,0,0xFF)<<8; + stat = ( sd ? sd->status.luk : status_get_base_status(bl)->luk ) / 2; val4 |= cap_value(stat,0,0xFF); + break; + } + case SC_MARIONETTE2: + { + int stat,max_stat; + // fetch caster information + struct block_list *pbl = map_id2bl(val1); + struct status_change *psc = pbl?status_get_sc(pbl):NULL; + struct status_change_entry *psce = psc?psc->data[SC_MARIONETTE]:NULL; + // fetch target's stats + struct status_data* status = status_get_status_data(bl); // battle status + + if (!psce) + return 0; - val3 = 0; - val4 = 0; - max_stat = battle_config.max_parameter; //Cap to 99 (default) - stat = (psce->val3 >>16)&0xFF; stat = min(stat, max_stat - status->str ); val3 |= cap_value(stat,0,0xFF)<<16; - stat = (psce->val3 >> 8)&0xFF; stat = min(stat, max_stat - status->agi ); val3 |= cap_value(stat,0,0xFF)<<8; - stat = (psce->val3 >> 0)&0xFF; stat = min(stat, max_stat - status->vit ); val3 |= cap_value(stat,0,0xFF); - stat = (psce->val4 >>16)&0xFF; stat = min(stat, max_stat - status->int_); val4 |= cap_value(stat,0,0xFF)<<16; - stat = (psce->val4 >> 8)&0xFF; stat = min(stat, max_stat - status->dex ); val4 |= cap_value(stat,0,0xFF)<<8; - stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - status->luk ); val4 |= cap_value(stat,0,0xFF); - break; - } - case SC_REJECTSWORD: - val2 = 15*val1; //Reflect chance - val3 = 3; //Reflections - tick = -1; - break; + val3 = 0; + val4 = 0; + max_stat = battle_config.max_parameter; //Cap to 99 (default) + stat = (psce->val3 >>16)&0xFF; stat = min(stat, max_stat - status->str ); val3 |= cap_value(stat,0,0xFF)<<16; + stat = (psce->val3 >> 8)&0xFF; stat = min(stat, max_stat - status->agi ); val3 |= cap_value(stat,0,0xFF)<<8; + stat = (psce->val3 >> 0)&0xFF; stat = min(stat, max_stat - status->vit ); val3 |= cap_value(stat,0,0xFF); + stat = (psce->val4 >>16)&0xFF; stat = min(stat, max_stat - status->int_); val4 |= cap_value(stat,0,0xFF)<<16; + stat = (psce->val4 >> 8)&0xFF; stat = min(stat, max_stat - status->dex ); val4 |= cap_value(stat,0,0xFF)<<8; + stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - status->luk ); val4 |= cap_value(stat,0,0xFF); + break; + } + case SC_REJECTSWORD: + val2 = 15*val1; //Reflect chance + val3 = 3; //Reflections + tick = -1; + break; - case SC_MEMORIZE: - val2 = 5; //Memorized casts. - tick = -1; - break; + case SC_MEMORIZE: + val2 = 5; //Memorized casts. + tick = -1; + break; - case SC_GRAVITATION: - val2 = 50*val1; //aspd reduction - break; + case SC_GRAVITATION: + val2 = 50*val1; //aspd reduction + break; - case SC_REGENERATION: - if (val1 == 1) - val2 = 2; - else - val2 = val1; //HP Regerenation rate: 200% 200% 300% - val3 = val1; //SP Regeneration Rate: 100% 200% 300% - //if val4 comes set, this blocks regen rather than increase it. - break; + case SC_REGENERATION: + if (val1 == 1) + val2 = 2; + else + val2 = val1; //HP Regerenation rate: 200% 200% 300% + val3 = val1; //SP Regeneration Rate: 100% 200% 300% + //if val4 comes set, this blocks regen rather than increase it. + break; - case SC_DEVOTION: - { - struct block_list *d_bl; - struct status_change *d_sc; - - if( (d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count ) - { // Inherits Status From Source - const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; - enum sc_type type2; - int i = (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)?2:3; - while( i >= 0 ) - { - type2 = types[i]; - if( d_sc->data[type2] ) - sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill_get_time(status_sc2skill(type2),d_sc->data[type2]->val1)); - i--; + case SC_DEVOTION: + { + struct block_list *d_bl; + struct status_change *d_sc; + + if( (d_bl = map_id2bl(val1)) && (d_sc = status_get_sc(d_bl)) && d_sc->count ) + { // Inherits Status From Source + const enum sc_type types[] = { SC_AUTOGUARD, SC_DEFENDER, SC_REFLECTSHIELD, SC_ENDURE }; + enum sc_type type2; + int i = (map_flag_gvg(bl->m) || map[bl->m].flag.battleground)?2:3; + while( i >= 0 ) + { + type2 = types[i]; + if( d_sc->data[type2] ) + sc_start(bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status_sc2skill(type2),d_sc->data[type2]->val1)); + i--; + } } + break; } - break; - } - case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp - if( val3 && bl->type == BL_MOB ) { - struct block_list* src = map_id2bl(val3); - if( src ) - mob_log_damage((TBL_MOB*)bl,src,status->hp - 1); - } - status_zap(bl, status->hp-1, val2?0:status->sp); - return 1; - break; - case SC_CLOSECONFINE2: - { - struct block_list *src = val2?map_id2bl(val2):NULL; - struct status_change *sc2 = src?status_get_sc(src):NULL; - struct status_change_entry *sce2 = sc2?sc2->data[SC_CLOSECONFINE]:NULL; - if (src && sc2) { - if (!sce2) //Start lock on caster. - sc_start4(src,SC_CLOSECONFINE,100,val1,1,0,0,tick+1000); - else { //Increase count of locked enemies and refresh time. - (sce2->val2)++; - delete_timer(sce2->timer, status_change_timer); - sce2->timer = add_timer(gettick()+tick+1000, status_change_timer, src->id, SC_CLOSECONFINE); + case SC_COMA: //Coma. Sends a char to 1HP. If val2, do not zap sp + if( val3 && bl->type == BL_MOB ) { + struct block_list* src = map_id2bl(val3); + if( src ) + mob_log_damage((TBL_MOB*)bl,src,status->hp - 1); } - } else //Status failed. - return 0; - } - break; - case SC_KAITE: - val2 = 1+val1/5; //Number of bounces: 1 + skill_lv/5 - break; - case SC_KAUPE: - switch (val1) { - case 3: //33*3 + 1 -> 100% - val2++; - case 1: - case 2: //33, 66% - val2 += 33*val1; - val3 = 1; //Dodge 1 attack total. - break; - default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex] - val2 = 100; - val3 = val1-2; - break; + status_zap(bl, status->hp-1, val2?0:status->sp); + return 1; + break; + case SC_CLOSECONFINE2: + { + struct block_list *src = val2?map_id2bl(val2):NULL; + struct status_change *sc2 = src?status_get_sc(src):NULL; + struct status_change_entry *sce2 = sc2?sc2->data[SC_CLOSECONFINE]:NULL; + if (src && sc2) { + if (!sce2) //Start lock on caster. + sc_start4(src,SC_CLOSECONFINE,100,val1,1,0,0,tick+1000); + else { //Increase count of locked enemies and refresh time. + (sce2->val2)++; + delete_timer(sce2->timer, status_change_timer); + sce2->timer = add_timer(gettick()+tick+1000, status_change_timer, src->id, SC_CLOSECONFINE); + } + } else //Status failed. + return 0; } - break; + break; + case SC_KAITE: + val2 = 1+val1/5; //Number of bounces: 1 + skill_lv/5 + break; + case SC_KAUPE: + switch (val1) { + case 3: //33*3 + 1 -> 100% + val2++; + case 1: + case 2: //33, 66% + val2 += 33*val1; + val3 = 1; //Dodge 1 attack total. + break; + default: //Custom. For high level mob usage, higher level means more blocks. [Skotlex] + val2 = 100; + val3 = val1-2; + break; + } + break; - case SC_COMBO: { - //val1: Skill ID - //val2: When given, target (for autotargetting skills) - //val3: When set, this combo time should NOT delay attack/movement - //val3: TK: Last used kick - //val4: TK: Combo time - struct unit_data *ud = unit_bl2ud(bl); - if (ud && !val3) { - tick += 300 * battle_config.combo_delay_rate/100; - ud->attackabletime = gettick()+tick; - unit_set_walkdelay(bl, gettick(), tick, 1); + case SC_COMBO: { + //val1: Skill ID + //val2: When given, target (for autotargetting skills) + //val3: When set, this combo time should NOT delay attack/movement + //val3: TK: Last used kick + //val4: TK: Combo time + struct unit_data *ud = unit_bl2ud(bl); + if (ud && !val3) { + tick += 300 * battle_config.combo_delay_rate/100; + ud->attackabletime = gettick()+tick; + unit_set_walkdelay(bl, gettick(), tick, 1); + } + val3 = 0; + val4 = tick; } - val3 = 0; - val4 = tick; - } - break; - case SC_EARTHSCROLL: - val2 = 11-val1; //Chance to consume: 11-skill_lv% - break; - case SC_RUN: - val4 = gettick(); //Store time at which you started running. - tick = -1; - break; - case SC_KAAHI: - val2 = 200*val1; //HP heal - val3 = 5*val1; //SP cost - val4 = INVALID_TIMER; //Kaahi Timer. - break; - case SC_BLESSING: - if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) - val2 = val1; - else - val2 = 0; //0 -> Half stat. - break; - case SC_TRICKDEAD: - if (vd) vd->dead_sit = 1; - tick = -1; - break; - case SC_CONCENTRATE: - val2 = 2 + val1; - if (sd) { //Store the card-bonus data that should not count in the % - val3 = sd->param_bonus[1]; //Agi - val4 = sd->param_bonus[4]; //Dex - } else { - val3 = val4 = 0; - } - break; - case SC_MAXOVERTHRUST: - val2 = 20*val1; //Power increase - break; - case SC_OVERTHRUST: - //val2 holds if it was casted on self, or is bonus received from others - val3 = 5*val1; //Power increase - if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; - break; - case SC_ADRENALINE2: - case SC_ADRENALINE: - val3 = (val2) ? 300 : 200; // aspd increase - case SC_WEAPONPERFECTION: - if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) - tick += tick / 10; - break; - case SC_CONCENTRATION: - val2 = 5*val1; //Batk/Watk Increase - val3 = 10*val1; //Hit Increase - val4 = 5*val1; //Def reduction - break; - case SC_ANGELUS: - val2 = 5*val1; //def increase - break; - case SC_IMPOSITIO: - val2 = 5*val1; //watk increase - break; - case SC_MELTDOWN: - val2 = 100*val1; //Chance to break weapon - val3 = 70*val1; //Change to break armor - break; - case SC_TRUESIGHT: - val2 = 10*val1; //Critical increase - val3 = 3*val1; //Hit increase - break; - case SC_SUN_COMFORT: - val2 = (status_get_lv(bl) + status->dex + status->luk)/2; //def increase - break; - case SC_MOON_COMFORT: - val2 = (status_get_lv(bl) + status->dex + status->luk)/10; //flee increase - break; - case SC_STAR_COMFORT: - val2 = (status_get_lv(bl) + status->dex + status->luk); //Aspd increase - break; - case SC_QUAGMIRE: - val2 = (sd?5:10)*val1; //Agi/Dex decrease. - break; + break; + case SC_EARTHSCROLL: + val2 = 11-val1; //Chance to consume: 11-skill_lv% + break; + case SC_RUN: + val4 = gettick(); //Store time at which you started running. + tick = -1; + break; + case SC_KAAHI: + val2 = 200*val1; //HP heal + val3 = 5*val1; //SP cost + val4 = INVALID_TIMER; //Kaahi Timer. + break; + case SC_BLESSING: + if ((!undead_flag && status->race!=RC_DEMON) || bl->type == BL_PC) + val2 = val1; + else + val2 = 0; //0 -> Half stat. + break; + case SC_TRICKDEAD: + if (vd) vd->dead_sit = 1; + tick = -1; + break; + case SC_CONCENTRATE: + val2 = 2 + val1; + if (sd) { //Store the card-bonus data that should not count in the % + val3 = sd->param_bonus[1]; //Agi + val4 = sd->param_bonus[4]; //Dex + } else { + val3 = val4 = 0; + } + break; + case SC_MAXOVERTHRUST: + val2 = 20*val1; //Power increase + break; + case SC_OVERTHRUST: + //val2 holds if it was casted on self, or is bonus received from others + val3 = 5*val1; //Power increase + if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; + case SC_ADRENALINE2: + case SC_ADRENALINE: + val3 = (val2) ? 300 : 200; // aspd increase + case SC_WEAPONPERFECTION: + if(sd && pc_checkskill(sd,BS_HILTBINDING)>0) + tick += tick / 10; + break; + case SC_CONCENTRATION: + val2 = 5*val1; //Batk/Watk Increase + val3 = 10*val1; //Hit Increase + val4 = 5*val1; //Def reduction + break; + case SC_ANGELUS: + val2 = 5*val1; //def increase + break; + case SC_IMPOSITIO: + val2 = 5*val1; //watk increase + break; + case SC_MELTDOWN: + val2 = 100*val1; //Chance to break weapon + val3 = 70*val1; //Change to break armor + break; + case SC_TRUESIGHT: + val2 = 10*val1; //Critical increase + val3 = 3*val1; //Hit increase + break; + case SC_SUN_COMFORT: + val2 = (status_get_lv(bl) + status->dex + status->luk)/2; //def increase + break; + case SC_MOON_COMFORT: + val2 = (status_get_lv(bl) + status->dex + status->luk)/10; //flee increase + break; + case SC_STAR_COMFORT: + val2 = (status_get_lv(bl) + status->dex + status->luk); //Aspd increase + break; + case SC_QUAGMIRE: + val2 = (sd?5:10)*val1; //Agi/Dex decrease. + break; - // gs_something1 [Vicious] - case SC_GATLINGFEVER: - val2 = 20*val1; //Aspd increase - val3 = 20+10*val1; //Batk increase - val4 = 5*val1; //Flee decrease - break; + // gs_something1 [Vicious] + case SC_GATLINGFEVER: + val2 = 20*val1; //Aspd increase + val3 = 20+10*val1; //Batk increase + val4 = 5*val1; //Flee decrease + break; - case SC_FLING: - if (bl->type == BL_PC) - val2 = 0; //No armor reduction to players. - else - val2 = 5*val1; //Def reduction - val3 = 5*val1; //Def2 reduction - break; - case SC_PROVOKE: - //val2 signals autoprovoke. - val3 = 2+3*val1; //Atk increase - val4 = 5+5*val1; //Def reduction. - break; - case SC_AVOID: - //val2 = 10*val1; //Speed change rate. - break; - case SC_DEFENCE: - val2 = 2*val1; //Def bonus - break; - case SC_BLOODLUST: - val2 = 20+10*val1; //Atk rate change. - val3 = 3*val1; //Leech chance - val4 = 20; //Leech percent - break; - case SC_FLEET: - val2 = 30*val1; //Aspd change - val3 = 5+5*val1; //bAtk/wAtk rate change - break; - case SC_MINDBREAKER: - val2 = 20*val1; //matk increase. - val3 = 12*val1; //mdef2 reduction. - break; - case SC_SKA: - val2 = tick/1000; - val3 = rnd()%100; //Def changes randomly every second... - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_JAILED: - //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. - tick = val1>0?1000:250; - if (sd) - { - if (sd->mapindex != val2) + case SC_FLING: + if (bl->type == BL_PC) + val2 = 0; //No armor reduction to players. + else + val2 = 5*val1; //Def reduction + val3 = 5*val1; //Def2 reduction + break; + case SC_PROVOKE: + //val2 signals autoprovoke. + val3 = 2+3*val1; //Atk increase + val4 = 5+5*val1; //Def reduction. + break; + case SC_AVOID: + //val2 = 10*val1; //Speed change rate. + break; + case SC_DEFENCE: + val2 = 2*val1; //Def bonus + break; + case SC_BLOODLUST: + val2 = 20+10*val1; //Atk rate change. + val3 = 3*val1; //Leech chance + val4 = 20; //Leech percent + break; + case SC_FLEET: + val2 = 30*val1; //Aspd change + val3 = 5+5*val1; //bAtk/wAtk rate change + break; + case SC_MINDBREAKER: + val2 = 20*val1; //matk increase. + val3 = 12*val1; //mdef2 reduction. + break; + case SC_SKA: + val2 = tick/1000; + val3 = rnd()%100; //Def changes randomly every second... + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_JAILED: + //Val1 is duration in minutes. Use INT_MAX to specify 'unlimited' time. + tick = val1>0?1000:250; + if (sd) { - int pos = (bl->x&0xFFFF)|(bl->y<<16), //Current Coordinates - map = sd->mapindex; //Current Map - //1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y - pc_setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT); - //2. Set restore point (val3 -> return map, val4 return coords - val3 = map; - val4 = pos; - } else if (!val3 || val3 == sd->mapindex) { //Use save point. - val3 = sd->status.save_point.map; - val4 = (sd->status.save_point.x&0xFFFF) - |(sd->status.save_point.y<<16); + if (sd->mapindex != val2) + { + int pos = (bl->x&0xFFFF)|(bl->y<<16), //Current Coordinates + map = sd->mapindex; //Current Map + //1. Place in Jail (val2 -> Jail Map, val3 -> x, val4 -> y + pc_setpos(sd,(unsigned short)val2,val3,val4, CLR_TELEPORT); + //2. Set restore point (val3 -> return map, val4 return coords + val3 = map; + val4 = pos; + } else if (!val3 || val3 == sd->mapindex) { //Use save point. + val3 = sd->status.save_point.map; + val4 = (sd->status.save_point.x&0xFFFF) + |(sd->status.save_point.y<<16); + } } - } - break; - case SC_UTSUSEMI: - val2=(val1+1)/2; // number of hits blocked - val3=skill_get_blewcount(NJ_UTSUSEMI, val1); //knockback value. - break; - case SC_BUNSINJYUTSU: - val2=(val1+1)/2; // number of hits blocked - break; - case SC_CHANGE: - val2= 30*val1; //Vit increase - val3= 20*val1; //Int increase - break; - case SC_SWOO: - if(status->mode&MD_BOSS) - tick /= 5; //TODO: Reduce skill's duration. But for how long? - break; - case SC_SPIDERWEB: - if( bl->type == BL_PC ) - tick /= 2; - break; - case SC_ARMOR: - //NPC_DEFENDER: - val2 = 80; //Damage reduction - //Attack requirements to be blocked: - val3 = BF_LONG; //Range - val4 = BF_WEAPON|BF_MISC; //Type - break; - case SC_ENCHANTARMS: - //end previous enchants - skill_enchant_elemental_end(bl,type); - //Make sure the received element is valid. - if (val2 >= ELE_MAX) - val2 = val2%ELE_MAX; - else if (val2 < 0) - val2 = rnd()%ELE_MAX; - break; - case SC_CRITICALWOUND: - val2 = 20*val1; //Heal effectiveness decrease - break; - case SC_MAGICMIRROR: - case SC_SLOWCAST: - val2 = 20*val1; //Magic reflection/cast rate - break; + break; + case SC_UTSUSEMI: + val2=(val1+1)/2; // number of hits blocked + val3=skill->get_blewcount(NJ_UTSUSEMI, val1); //knockback value. + break; + case SC_BUNSINJYUTSU: + val2=(val1+1)/2; // number of hits blocked + break; + case SC_CHANGE: + val2= 30*val1; //Vit increase + val3= 20*val1; //Int increase + break; + case SC_SWOO: + if(status->mode&MD_BOSS) + tick /= 5; //TODO: Reduce skill's duration. But for how long? + break; + case SC_SPIDERWEB: + if( bl->type == BL_PC ) + tick /= 2; + break; + case SC_ARMOR: + //NPC_DEFENDER: + val2 = 80; //Damage reduction + //Attack requirements to be blocked: + val3 = BF_LONG; //Range + val4 = BF_WEAPON|BF_MISC; //Type + break; + case SC_ENCHANTARMS: + //end previous enchants + skill->enchant_elemental_end(bl,type); + //Make sure the received element is valid. + if (val2 >= ELE_MAX) + val2 = val2%ELE_MAX; + else if (val2 < 0) + val2 = rnd()%ELE_MAX; + break; + case SC_CRITICALWOUND: + val2 = 20*val1; //Heal effectiveness decrease + break; + case SC_MAGICMIRROR: + case SC_SLOWCAST: + val2 = 20*val1; //Magic reflection/cast rate + break; - case SC_ARMORCHANGE: - if (val2 == NPC_ANTIMAGIC) - { //Boost mdef - val2 =-20; - val3 = 20; - } else { //Boost def - val2 = 20; - val3 =-20; - } - val2*=val1; //20% per level - val3*=val1; - break; - case SC_EXPBOOST: - case SC_JEXPBOOST: - if (val1 < 0) - val1 = 0; - break; - case SC_INCFLEE2: - case SC_INCCRI: - val2 = val1*10; //Actual boost (since 100% = 1000) - break; - case SC_SUFFRAGIUM: - val2 = 15 * val1; //Speed cast decrease - break; - case SC_INCHEALRATE: - if (val1 < 1) - val1 = 1; - break; - case SC_HALLUCINATION: - val2 = 5+val1; //Factor by which displayed damage is increased by - break; - case SC_DOUBLECAST: - val2 = 30+10*val1; //Trigger rate - break; - case SC_KAIZEL: - val2 = 10*val1; //% of life to be revived with - break; - // case SC_ARMOR_ELEMENT: - // case SC_ARMOR_RESIST: - // Mod your resistance against elements: - // val1 = water | val2 = earth | val3 = fire | val4 = wind - // break; - //case ????: - //Place here SCs that have no SCB_* data, no skill associated, no ICON - //associated, and yet are not wrong/unknown. [Skotlex] - //break; + case SC_ARMORCHANGE: + if (val2 == NPC_ANTIMAGIC) + { //Boost mdef + val2 =-20; + val3 = 20; + } else { //Boost def + val2 = 20; + val3 =-20; + } + val2*=val1; //20% per level + val3*=val1; + break; + case SC_EXPBOOST: + case SC_JEXPBOOST: + if (val1 < 0) + val1 = 0; + break; + case SC_INCFLEE2: + case SC_INCCRI: + val2 = val1*10; //Actual boost (since 100% = 1000) + break; + case SC_SUFFRAGIUM: + val2 = 15 * val1; //Speed cast decrease + break; + case SC_INCHEALRATE: + if (val1 < 1) + val1 = 1; + break; + case SC_HALLUCINATION: + val2 = 5+val1; //Factor by which displayed damage is increased by + break; + case SC_DOUBLECAST: + val2 = 30+10*val1; //Trigger rate + break; + case SC_KAIZEL: + val2 = 10*val1; //% of life to be revived with + break; + // case SC_ARMOR_ELEMENT: + // case SC_ARMOR_RESIST: + // Mod your resistance against elements: + // val1 = water | val2 = earth | val3 = fire | val4 = wind + // break; + //case ????: + //Place here SCs that have no SCB_* data, no skill associated, no ICON + //associated, and yet are not wrong/unknown. [Skotlex] + //break; - case SC_MERC_FLEEUP: - case SC_MERC_ATKUP: - case SC_MERC_HITUP: - val2 = 15 * val1; - break; - case SC_MERC_HPUP: - case SC_MERC_SPUP: - val2 = 5 * val1; - break; - case SC_REBIRTH: - val2 = 20*val1; //% of life to be revived with - break; + case SC_MERC_FLEEUP: + case SC_MERC_ATKUP: + case SC_MERC_HITUP: + val2 = 15 * val1; + break; + case SC_MERC_HPUP: + case SC_MERC_SPUP: + val2 = 5 * val1; + break; + case SC_REBIRTH: + val2 = 20*val1; //% of life to be revived with + break; - case SC_MANU_DEF: - case SC_MANU_ATK: - case SC_MANU_MATK: - val2 = 1; // Manuk group - break; - case SC_SPL_DEF: - case SC_SPL_ATK: - case SC_SPL_MATK: - val2 = 2; // Splendide group - break; - /** - * General - **/ - case SC_FEAR: - val2 = 2; - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_BURNING: - val4 = tick / 2000; // Total Ticks to Burn!! - tick_time = 2000; // [GodLesZ] tick time - break; - /** - * Rune Knight - **/ - case SC_DEATHBOUND: - val2 = 500 + 100 * val1; - break; - case SC_FIGHTINGSPIRIT: - val_flag |= 1|2; - break; - case SC_ABUNDANCE: - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_GIANTGROWTH: - val2 = 10; // Triple damage success rate. - break; - /** - * Arch Bishop - **/ - case SC_RENOVATIO: - val4 = tick / 5000; - tick_time = 5000; - break; - case SC_SECRAMENT: - val2 = 10 * val1; - break; - case SC_VENOMIMPRESS: - val2 = 10 * val1; - val_flag |= 1|2; - break; - case SC_POISONINGWEAPON: - val_flag |= 1|2|4; - break; - case SC_WEAPONBLOCKING: - val2 = 10 + 2 * val1; // Chance - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - val_flag |= 1|2; - break; - case SC_TOXIN: - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_MAGICMUSHROOM: - val4 = tick / 4000; - tick_time = 4000; // [GodLesZ] tick time - break; - case SC_PYREXIA: - status_change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_LEECHESEND: - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_OBLIVIONCURSE: - val4 = tick / 3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_ROLLINGCUTTER: - val_flag |= 1; - break; - case SC_CLOAKINGEXCEED: - val2 = ( val1 + 1 ) / 2; // Hits - val3 = 90 + val1 * 10; // Walk speed - val_flag |= 1|2|4; - if (bl->type == BL_PC) - val4 |= battle_config.pc_cloak_check_type&7; - else - val4 |= battle_config.monster_cloak_check_type&7; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_HALLUCINATIONWALK: - val2 = 50 * val1; // Evasion rate of physical attacks. Flee - val3 = 10 * val1; // Evasion rate of magical attacks. - val_flag |= 1|2|4; - break; - case SC_WHITEIMPRISON: - status_change_end(bl, SC_BURNING, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_STONE, INVALID_TIMER); - break; - case SC_FREEZING: - status_change_end(bl, SC_BURNING, INVALID_TIMER); - break; - case SC_READING_SB: - // val2 = sp reduction per second - tick_time = 5000; // [GodLesZ] tick time - break; - case SC_SPHERE_1: - case SC_SPHERE_2: - case SC_SPHERE_3: - case SC_SPHERE_4: - case SC_SPHERE_5: - if( !sd ) - return 0; // Should only work on players. - val4 = tick / 1000; - if( val4 < 1 ) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time - val_flag |= 1; - break; - case SC_SHAPESHIFT: - switch( val1 ) - { - case 1: val2 = ELE_FIRE; break; - case 2: val2 = ELE_EARTH; break; - case 3: val2 = ELE_WIND; break; - case 4: val2 = ELE_WATER; break; - } - break; - case SC_ELECTRICSHOCKER: - case SC_CRYSTALIZE: - case SC_MEIKYOUSISUI: - val4 = tick / 1000; - if( val4 < 1 ) - val4 = 1; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_CAMOUFLAGE: - val4 = tick/1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_WUGDASH: - val4 = gettick(); //Store time at which you started running. - tick = -1; - break; - case SC__SHADOWFORM: { - struct map_session_data * s_sd = map_id2sd(val2); - if( s_sd ) - s_sd->shadowform_id = bl->id; + case SC_MANU_DEF: + case SC_MANU_ATK: + case SC_MANU_MATK: + val2 = 1; // Manuk group + break; + case SC_SPL_DEF: + case SC_SPL_ATK: + case SC_SPL_MATK: + val2 = 2; // Splendide group + break; + /** + * General + **/ + case SC_FEAR: + val2 = 2; val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_BURNING: + val4 = tick / 2000; // Total Ticks to Burn!! + tick_time = 2000; // [GodLesZ] tick time + break; + /** + * Rune Knight + **/ + case SC_DEATHBOUND: + val2 = 500 + 100 * val1; + break; + case SC_STONEHARDSKIN: + if( sd ) + val1 = sd->status.job_level * pc_checkskill(sd, RK_RUNEMASTERY) / 4; //DEF/MDEF Increase + break; + case SC_FIGHTINGSPIRIT: + val_flag |= 1|2; + break; + case SC_ABUNDANCE: + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_GIANTGROWTH: + val2 = 10; // Triple damage success rate. + break; + /** + * Arch Bishop + **/ + case SC_RENOVATIO: + val4 = tick / 5000; + tick_time = 5000; + break; + case SC_SECRAMENT: + val2 = 10 * val1; + break; + case SC_VENOMIMPRESS: + val2 = 10 * val1; + val_flag |= 1|2; + break; + case SC_POISONINGWEAPON: val_flag |= 1|2|4; + break; + case SC_WEAPONBLOCKING: + val2 = 10 + 2 * val1; // Chance + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + val_flag |= 1|2; + break; + case SC_TOXIN: + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_MAGICMUSHROOM: + val4 = tick / 4000; + tick_time = 4000; // [GodLesZ] tick time + break; + case SC_PYREXIA: + status_change_start(bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_LEECHESEND: + val4 = tick / 1000; tick_time = 1000; // [GodLesZ] tick time - } - break; - case SC__STRIPACCESSORY: - if (!sd) + break; + case SC_OBLIVIONCURSE: + val4 = tick / 3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_ROLLINGCUTTER: + val_flag |= 1; + break; + case SC_CLOAKINGEXCEED: + val2 = ( val1 + 1 ) / 2; // Hits + val3 = 90 + val1 * 10; // Walk speed + val_flag |= 1|2|4; + if (bl->type == BL_PC) + val4 |= battle_config.pc_cloak_check_type&7; + else + val4 |= battle_config.monster_cloak_check_type&7; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_HALLUCINATIONWALK: + val2 = 50 * val1; // Evasion rate of physical attacks. Flee + val3 = 10 * val1; // Evasion rate of magical attacks. + val_flag |= 1|2|4; + break; + case SC_WHITEIMPRISON: + status_change_end(bl, SC_BURNING, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_STONE, INVALID_TIMER); + break; + case SC_FREEZING: + status_change_end(bl, SC_BURNING, INVALID_TIMER); + break; + case SC_READING_SB: + // val2 = sp reduction per second + tick_time = 5000; // [GodLesZ] tick time + break; + case SC_SPHERE_1: + case SC_SPHERE_2: + case SC_SPHERE_3: + case SC_SPHERE_4: + case SC_SPHERE_5: + if( !sd ) + return 0; // Should only work on players. + val4 = tick / 1000; + if( val4 < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + val_flag |= 1; + break; + case SC_SHAPESHIFT: + switch( val1 ) + { + case 1: val2 = ELE_FIRE; break; + case 2: val2 = ELE_EARTH; break; + case 3: val2 = ELE_WIND; break; + case 4: val2 = ELE_WATER; break; + } + break; + case SC_ELECTRICSHOCKER: + case SC_CRYSTALIZE: + case SC_MEIKYOUSISUI: + val4 = tick / 1000; + if( val4 < 1 ) + val4 = 1; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_CAMOUFLAGE: + val4 = tick/1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_WUGDASH: + val4 = gettick(); //Store time at which you started running. + tick = -1; + break; + case SC__SHADOWFORM: { + struct map_session_data * s_sd = map_id2sd(val2); + if( s_sd ) + s_sd->shadowform_id = bl->id; + val4 = tick / 1000; + val_flag |= 1|2|4; + tick_time = 1000; // [GodLesZ] tick time + } + break; + case SC__STRIPACCESSORY: + if (!sd) + val2 = 20; + break; + case SC__INVISIBILITY: + val2 = 50 - 10 * val1; // ASPD + val3 = 20 * val1; // CRITICAL + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + val_flag |= 1|2; + break; + case SC__ENERVATION: + val2 = 20 + 10 * val1; // ATK Reduction + val_flag |= 1|2; + if( sd ) pc_delspiritball(sd,sd->spiritball,0); + break; + case SC__GROOMY: + val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie] + val3 = 20 * val1; //HIT + val_flag |= 1|2|4; + if( sd ) { // Removes Animals + if( pc_isriding(sd) ) pc_setriding(sd, 0); + if( pc_isridingdragon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); + if( pc_iswug(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_WUG); + if( pc_isridingwug(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_WUGRIDER); + if( pc_isfalcon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_FALCON); + if( sd->status.pet_id > 0 ) pet_menu(sd, 3); + if( homun_alive(sd->hd) ) homun->vaporize(sd,1); + if( sd->md ) merc_delete(sd->md,3); + } + break; + case SC__LAZINESS: + val2 = 10 + 10 * val1; // Cast reduction + val3 = 10 * val1; // Flee Reduction + val_flag |= 1|2|4; + break; + case SC__UNLUCKY: + val2 = 10 * val1; // Crit and Flee2 Reduction + val_flag |= 1|2|4; + break; + case SC__WEAKNESS: + val2 = 10 * val1; + val_flag |= 1|2; + // bypasses coating protection and MADO + sc_start(bl,SC_STRIPWEAPON,100,val1,tick); + sc_start(bl,SC_STRIPSHIELD,100,val1,tick); + break; + break; + case SC_GN_CARTBOOST: + if( val1 < 3 ) + val2 = 50; + else if( val1 < 5 ) + val2 = 75; + else + val2 = 100; + break; + case SC_PROPERTYWALK: + val_flag |= 1|2; + val3 = 0; + break; + case SC_WARMER: + status_change_end(bl, SC_FREEZE, INVALID_TIMER); + status_change_end(bl, SC_FREEZING, INVALID_TIMER); + status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); + break; + case SC_STRIKING: + val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1) + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_BLOODSUCKER: + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_VACUUM_EXTREME: + tick -= (status->str / 20) * 1000; + val4 = val3 = tick / 100; + tick_time = 100; // [GodLesZ] tick time + break; + case SC_SWINGDANCE: + val2 = 4 * val1; // Walk speed and aspd reduction. + break; + case SC_SYMPHONYOFLOVER: + case SC_RUSHWINDMILL: + case SC_ECHOSONG: + val2 = 6 * val1; + val2 += val3; //Adding 1% * Lesson Bonus + val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel + break; + case SC_MOONLITSERENADE: + val2 = 10 * val1; + break; + case SC_HARMONIZE: + val2 = 5 + 5 * val1; + break; + case SC_VOICEOFSIREN: + val4 = tick / 2000; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_DEEPSLEEP: + val4 = tick / 2000; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_SIRCLEOFNATURE: + val2 = 1 + val1; //SP consume + val3 = 40 * val1; //HP recovery + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_SONGOFMANA: + val3 = 10 + (2 * val2); + val4 = tick/3000; + tick_time = 3000; // [GodLesZ] tick time + break; + case SC_SATURDAYNIGHTFEVER: + if (!val4) val4 = skill->get_time2(status_sc2skill(type),val1); + if (!val4) val4 = 3000; + val3 = tick/val4; + tick_time = val4; // [GodLesZ] tick time + break; + case SC_GLOOMYDAY: + val2 = 20 + 5 * val1; // Flee reduction. + val3 = 15 + 5 * val1; // ASPD reduction. + if( sd && rand()%100 < val1 ){ // (Skill Lv) % + val4 = 1; // reduce walk speed by half. + if( pc_isriding(sd) ) pc_setriding(sd, 0); + if( pc_isridingdragon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); + } + break; + case SC_GLOOMYDAY_SK: + // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %. + val2 = 15 + rand()%( (sd?pc_checkskill(sd, WM_LESSON)*5:0) + val1*10 ); + break; + case SC_SITDOWN_FORCE: + case SC_BANANA_BOMB_SITDOWN: + if( sd && !pc_issit(sd) ) + { + pc_setsit(sd); + skill->sit(sd,1); + clif->sitting(bl); + } + break; + case SC_DANCEWITHWUG: + val3 = (5 * val1) + (1 * val2); //Still need official value. + break; + case SC_LERADSDEW: + val3 = (5 * val1) + (1 * val2); + break; + case SC_MELODYOFSINK: + val3 = (5 * val1) + (1 * val2); + break; + case SC_BEYONDOFWARCRY: + val3 = (5 * val1) + (1 * val2); + break; + case SC_UNLIMITEDHUMMINGVOICE: + { + struct unit_data *ud = unit_bl2ud(bl); + if( ud == NULL ) return 0; + ud->state.skillcastcancel = 0; + val3 = 15 - (2 * val2); + } + break; + case SC_REFLECTDAMAGE: + val2 = 15 + 5 * val1; + val3 = (val1==5)?20:(val1+4)*2; // SP consumption + val4 = tick/10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_FORCEOFVANGUARD: // This is not the official way to handle it but I think we should use it. [pakpil] + val2 = 20 + 12 * (val1 - 1); // Chance + val3 = 5 + (2 * val1); // Max rage counters + tick = -1; //endless duration in the client + tick_time = 6000; // [GodLesZ] tick time + val_flag |= 1|2|4; + 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] + break; + case SC_PRESTIGE: // Bassed on suggested formula in iRO Wiki and some test, still need more test. [pakpil] + val2 = ((status->int_ + status->luk) / 6) + 5; // Chance to evade magic damage. + val1 *= 15; // Defence added + if( sd ) + val1 += 10 * pc_checkskill(sd,CR_DEFENDER); + val_flag |= 1|2; + break; + case SC_BANDING: + tick_time = 5000; // [GodLesZ] tick time + val_flag |= 1; + break; + case SC_SHIELDSPELL_DEF: + case SC_SHIELDSPELL_MDEF: + case SC_SHIELDSPELL_REF: + val_flag |= 1|2; + break; + case SC_MAGNETICFIELD: + val3 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + break; + case SC_INSPIRATION: + if( sd ) + { + val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus + val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus + } + val4 = tick / 1000; + tick_time = 1000; // [GodLesZ] tick time + status_change_clear_buffs(bl,3); //Remove buffs/debuffs + break; + case SC_SPELLFIST: + case SC_CURSEDCIRCLE_ATKER: + val_flag |= 1|2|4; + break; + case SC_CRESCENTELBOW: + val2 = 94 + val1; + val_flag |= 1|2; + break; + case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] % + val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1; + val_flag |= 1; + break; + case SC_RAISINGDRAGON: + val3 = tick / 5000; + tick_time = 5000; // [GodLesZ] tick time + break; + case SC_GT_CHANGE: + {// take note there is no def increase as skill desc says. [malufett] + struct block_list * src; + val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % + if( (src = map_id2bl(val2)) ) + val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] + } + break; + case SC_GT_REVITALIZE: + {// take note there is no vit,aspd,speed increase as skill desc says. [malufett] + struct block_list * src; + val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % + if( (src = map_id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently + val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] + } + break; + case SC_PYROTECHNIC_OPTION: + val_flag |= 1|2|4; + break; + case SC_HEATER_OPTION: + val2 = 120; // Watk. TODO: Renewal (Atk2) + val3 = 33; // % Increase effects. + val4 = 3; // Change into fire element. + val_flag |= 1|2|4; + break; + case SC_TROPIC_OPTION: + val2 = 180; // Watk. TODO: Renewal (Atk2) + val3 = MG_FIREBOLT; + break; + case SC_AQUAPLAY_OPTION: + val2 = 40; + val_flag |= 1|2|4; + break; + case SC_COOLER_OPTION: + val2 = 80; // % Freezing chance + val3 = 33; // % increased damage + val4 = 1; // Change into water elemet + val_flag |= 1|2|4; + break; + case SC_CHILLY_AIR_OPTION: + val2 = 120; // Matk. TODO: Renewal (Matk1) + val3 = MG_COLDBOLT; + val_flag |= 1|2; + break; + case SC_GUST_OPTION: + val_flag |= 1|2; + break; + case SC_WIND_STEP_OPTION: + val2 = 50; // % Increase speed and flee. + break; + case SC_BLAST_OPTION: val2 = 20; - break; - case SC__INVISIBILITY: - val2 = 50 - 10 * val1; // ASPD - val3 = 20 * val1; // CRITICAL - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - val_flag |= 1|2; - break; - case SC__ENERVATION: - val2 = 20 + 10 * val1; // ATK Reduction - val_flag |= 1|2; - if( sd ) pc_delspiritball(sd,sd->spiritball,0); - break; - case SC__GROOMY: - val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie] - val3 = 20 * val1; //HIT - val_flag |= 1|2|4; - if( sd ) - { // Removes Animals - if( pc_isriding(sd) ) pc_setriding(sd, 0); - if( pc_isridingdragon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); - if( pc_iswug(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_WUG); - if( pc_isridingwug(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_WUGRIDER); - if( pc_isfalcon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_FALCON); - if( sd->status.pet_id > 0 ) pet_menu(sd, 3); - if( merc_is_hom_active(sd->hd) ) merc_hom_vaporize(sd,1); - if( sd->md ) merc_delete(sd->md,3); - } - break; - case SC__LAZINESS: - val2 = 10 + 10 * val1; // Cast reduction - val3 = 10 * val1; // Flee Reduction - val_flag |= 1|2|4; - break; - case SC__UNLUCKY: - val2 = 10 * val1; // Crit and Flee2 Reduction - val_flag |= 1|2|4; - break; - case SC__WEAKNESS: - val2 = 10 * val1; - val_flag |= 1|2; - // bypasses coating protection and MADO - sc_start(bl,SC_STRIPWEAPON,100,val1,tick); - sc_start(bl,SC_STRIPSHIELD,100,val1,tick); - break; - break; - case SC_GN_CARTBOOST: - if( val1 < 3 ) - val2 = 50; - else if( val1 < 5 ) - val2 = 75; - else - val2 = 100; - break; - case SC_PROPERTYWALK: - val_flag |= 1|2; - val3 = 0; - break; - case SC_WARMER: - status_change_end(bl, SC_FREEZE, INVALID_TIMER); - status_change_end(bl, SC_FREEZING, INVALID_TIMER); - status_change_end(bl, SC_CRYSTALIZE, INVALID_TIMER); - break; - case SC_STRIKING: - val1 = 6 - val1;//spcost = 6 - level (lvl1:5 ... lvl 5: 1) - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_BLOODSUCKER: - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_VACUUM_EXTREME: - tick -= (status->str / 20) * 1000; - val4 = val3 = tick / 100; - tick_time = 100; // [GodLesZ] tick time - break; - case SC_SWINGDANCE: - val2 = 4 * val1; // Walk speed and aspd reduction. - break; - case SC_SYMPHONYOFLOVER: - case SC_RUSHWINDMILL: - case SC_ECHOSONG: - val2 = 6 * val1; - val2 += val3; //Adding 1% * Lesson Bonus - val2 += (int)(val4*2/10); //Adding 0.2% per JobLevel - break; - case SC_MOONLITSERENADE: - val2 = 10 * val1; - break; - case SC_HARMONIZE: - val2 = 5 + 5 * val1; - break; - case SC_VOICEOFSIREN: - val4 = tick / 2000; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_DEEPSLEEP: - val4 = tick / 2000; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_SIRCLEOFNATURE: - val2 = 1 + val1; //SP consume - val3 = 40 * val1; //HP recovery - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_SONGOFMANA: - val3 = 10 + (2 * val2); - val4 = tick/3000; - tick_time = 3000; // [GodLesZ] tick time - break; - case SC_SATURDAYNIGHTFEVER: - if (!val4) val4 = skill_get_time2(status_sc2skill(type),val1); - if (!val4) val4 = 3000; - val3 = tick/val4; - tick_time = val4; // [GodLesZ] tick time - break; - case SC_GLOOMYDAY: - val2 = 20 + 5 * val1; // Flee reduction. - val3 = 15 + 5 * val1; // ASPD reduction. - if( sd && rand()%100 < val1 ){ // (Skill Lv) % - val4 = 1; // reduce walk speed by half. - if( pc_isriding(sd) ) pc_setriding(sd, 0); - if( pc_isridingdragon(sd) ) pc_setoption(sd, sd->sc.option&~OPTION_DRAGON); - } - break; - case SC_GLOOMYDAY_SK: - // Random number between [15 ~ (Voice Lesson Skill Level x 5) + (Skill Level x 10)] %. - val2 = 15 + rand()%( (sd?pc_checkskill(sd, WM_LESSON)*5:0) + val1*10 ); - break; - case SC_SITDOWN_FORCE: - case SC_BANANA_BOMB_SITDOWN: - if( sd && !pc_issit(sd) ) - { - pc_setsit(sd); - skill_sit(sd,1); - clif_sitting(bl); - } - break; - case SC_DANCEWITHWUG: - val3 = (5 * val1) + (1 * val2); //Still need official value. - break; - case SC_LERADSDEW: - val3 = (5 * val1) + (1 * val2); - break; - case SC_MELODYOFSINK: - val3 = (5 * val1) + (1 * val2); - break; - case SC_BEYONDOFWARCRY: - val3 = (5 * val1) + (1 * val2); - break; - case SC_UNLIMITEDHUMMINGVOICE: - { - struct unit_data *ud = unit_bl2ud(bl); - if( ud == NULL ) return 0; - ud->state.skillcastcancel = 0; - val3 = 15 - (2 * val2); - } - break; - case SC_REFLECTDAMAGE: - val2 = 15 + 5 * val1; - val3 = (val1==5)?20:(val1+4)*2; // SP consumption - val4 = tick/10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_FORCEOFVANGUARD: // This is not the official way to handle it but I think we should use it. [pakpil] - val2 = 20 + 12 * (val1 - 1); // Chance - val3 = 5 + (2 * val1); // Max rage counters - tick = -1; //endless duration in the client - tick_time = 6000; // [GodLesZ] tick time - val_flag |= 1|2|4; - 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] - break; - case SC_PRESTIGE: // Bassed on suggested formula in iRO Wiki and some test, still need more test. [pakpil] - val2 = ((status->int_ + status->luk) / 6) + 5; // Chance to evade magic damage. - val1 *= 15; // Defence added - if( sd ) - val1 += 10 * pc_checkskill(sd,CR_DEFENDER); - val_flag |= 1|2; - break; - case SC_BANDING: - tick_time = 5000; // [GodLesZ] tick time - val_flag |= 1; - break; - case SC_SHIELDSPELL_DEF: - case SC_SHIELDSPELL_MDEF: - case SC_SHIELDSPELL_REF: - val_flag |= 1|2; - break; - case SC_MAGNETICFIELD: - val3 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - break; - case SC_INSPIRATION: - if( sd ) - { - val2 = (40 * val1) + (3 * sd->status.job_level); // ATK bonus - val3 = (sd->status.job_level / 10) * 2 + 12; // All stat bonus - } - val4 = tick / 1000; - tick_time = 1000; // [GodLesZ] tick time - status_change_clear_buffs(bl,3); //Remove buffs/debuffs - break; - case SC_SPELLFIST: - case SC_CURSEDCIRCLE_ATKER: - val_flag |= 1|2|4; - break; - case SC_CRESCENTELBOW: - val2 = 94 + val1; - val_flag |= 1|2; - break; - case SC_LIGHTNINGWALK: // [(Job Level / 2) + (40 + 5 * Skill Level)] % - val1 = (sd?sd->status.job_level:2)/2 + 40 + 5 * val1; - val_flag |= 1; - break; - case SC_RAISINGDRAGON: - val3 = tick / 5000; - tick_time = 5000; // [GodLesZ] tick time - break; - case SC_GT_CHANGE: - {// take note there is no def increase as skill desc says. [malufett] - struct block_list * src; - val3 = status->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] % - if( (src = map_id2bl(val2)) ) - val4 = ( 200/status_get_int(src) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level] - } - break; - case SC_GT_REVITALIZE: - {// take note there is no vit,aspd,speed increase as skill desc says. [malufett] - struct block_list * src; - val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] % - if( (src = map_id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently - val4 = ( status_get_vit(src)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level] - } - break; - case SC_PYROTECHNIC_OPTION: - val_flag |= 1|2|4; - break; - case SC_HEATER_OPTION: - val2 = 120; // Watk. TODO: Renewal (Atk2) - val3 = 33; // % Increase effects. - val4 = 3; // Change into fire element. - val_flag |= 1|2|4; - break; - case SC_TROPIC_OPTION: - val2 = 180; // Watk. TODO: Renewal (Atk2) - val3 = MG_FIREBOLT; - break; - case SC_AQUAPLAY_OPTION: - val2 = 40; - val_flag |= 1|2|4; - break; - case SC_COOLER_OPTION: - val2 = 80; // % Freezing chance - val3 = 33; // % increased damage - val4 = 1; // Change into water elemet - val_flag |= 1|2|4; - break; - case SC_CHILLY_AIR_OPTION: - val2 = 120; // Matk. TODO: Renewal (Matk1) - val3 = MG_COLDBOLT; - val_flag |= 1|2; - break; - case SC_GUST_OPTION: - val_flag |= 1|2; - break; - case SC_WIND_STEP_OPTION: - val2 = 50; // % Increase speed and flee. - break; - case SC_BLAST_OPTION: - val2 = 20; - val3 = ELE_WIND; - val_flag |= 1|2|4; - break; - case SC_WILD_STORM_OPTION: - val2 = MG_LIGHTNINGBOLT; - val_flag |= 1|2; - break; - case SC_PETROLOGY_OPTION: - val2 = 5; - val3 = 50; - val_flag |= 1|2|4; - break; - case SC_CURSED_SOIL_OPTION: - val2 = 10; - val3 = 33; - val4 = 2; - val_flag |= 1|2|4; - break; - case SC_UPHEAVAL_OPTION: - val2 = WZ_EARTHSPIKE; - val_flag |= 1|2; - break; - case SC_CIRCLE_OF_FIRE_OPTION: - val2 = 300; - val_flag |= 1|2; - break; - case SC_FIRE_CLOAK_OPTION: - case SC_WATER_DROP_OPTION: - case SC_WIND_CURTAIN_OPTION: - case SC_STONE_SHIELD_OPTION: - val2 = 20; // Elemental modifier. Not confirmed. - break; - case SC_CIRCLE_OF_FIRE: - case SC_FIRE_CLOAK: - case SC_WATER_DROP: - case SC_WATER_SCREEN: - case SC_WIND_CURTAIN: - case SC_WIND_STEP: - case SC_STONE_SHIELD: - case SC_SOLID_SKIN: - val2 = 10; - tick_time = 2000; // [GodLesZ] tick time - break; - case SC_WATER_BARRIER: - val2 = 40; // Increasement. Mdef1 ??? - val3 = 20; // Reductions. Atk2, Flee1, Matk1 ???? - val_flag |= 1|2|4; - break; - case SC_ZEPHYR: - val2 = 22; // Flee. - break; - case SC_TIDAL_WEAPON: - val2 = 20; // Increase Elemental's attack. - break; - case SC_ROCK_CRUSHER: - case SC_ROCK_CRUSHER_ATK: - case SC_POWER_OF_GAIA: - val2 = 33; - break; - case SC_MELON_BOMB: - case SC_BANANA_BOMB: - val1 = 15; - break; - case SC_STOMACHACHE: - val2 = 8; // SP consume. - val4 = tick / 10000; - tick_time = 10000; // [GodLesZ] tick time - break; - case SC_KYOUGAKU: - val2 = 2*val1 + rand()%val1; - clif_status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); - break; - case SC_KAGEMUSYA: - val3 = val1 * 2; - case SC_IZAYOI: - val2 = tick/1000; - tick_time = 1000; - break; - case SC_ZANGETSU: - if( (status_get_hp(bl)+status_get_sp(bl)) % 2 == 0) - val2 = status_get_lv(bl) / 2 + 50; - else - val2 -= 50; - break; - case SC_GENSOU: - { - int hp = status_get_hp(bl), lv = 5; - short per = 100 / (status_get_max_hp(bl) / hp); - - if( per <= 15 ) - lv = 1; - else if( per <= 30 ) - lv = 2; - else if( per <= 50 ) - lv = 3; - else if( per <= 75 ) - lv = 4; - if( hp % 2 == 0) - status_heal(bl, hp * (6-lv) * 4 / 100, status_get_sp(bl) * (6-lv) * 3 / 100, 1); + val3 = ELE_WIND; + val_flag |= 1|2|4; + break; + case SC_WILD_STORM_OPTION: + val2 = MG_LIGHTNINGBOLT; + val_flag |= 1|2; + break; + case SC_PETROLOGY_OPTION: + val2 = 5; + val3 = 50; + val_flag |= 1|2|4; + break; + case SC_CURSED_SOIL_OPTION: + val2 = 10; + val3 = 33; + val4 = 2; + val_flag |= 1|2|4; + break; + case SC_UPHEAVAL_OPTION: + val2 = WZ_EARTHSPIKE; + val_flag |= 1|2; + break; + case SC_CIRCLE_OF_FIRE_OPTION: + val2 = 300; + val_flag |= 1|2; + break; + case SC_FIRE_CLOAK_OPTION: + case SC_WATER_DROP_OPTION: + case SC_WIND_CURTAIN_OPTION: + case SC_STONE_SHIELD_OPTION: + val2 = 20; // Elemental modifier. Not confirmed. + break; + case SC_CIRCLE_OF_FIRE: + case SC_FIRE_CLOAK: + case SC_WATER_DROP: + case SC_WATER_SCREEN: + case SC_WIND_CURTAIN: + case SC_WIND_STEP: + case SC_STONE_SHIELD: + case SC_SOLID_SKIN: + val2 = 10; + tick_time = 2000; // [GodLesZ] tick time + break; + case SC_WATER_BARRIER: + val2 = 40; // Increasement. Mdef1 ??? + val3 = 20; // Reductions. Atk2, Flee1, Matk1 ???? + val_flag |= 1|2|4; + break; + case SC_ZEPHYR: + val2 = 22; // Flee. + break; + case SC_TIDAL_WEAPON: + val2 = 20; // Increase Elemental's attack. + break; + case SC_ROCK_CRUSHER: + case SC_ROCK_CRUSHER_ATK: + case SC_POWER_OF_GAIA: + val2 = 33; + break; + case SC_MELON_BOMB: + case SC_BANANA_BOMB: + val1 = 15; + break; + case SC_STOMACHACHE: + val2 = 8; // SP consume. + val4 = tick / 10000; + tick_time = 10000; // [GodLesZ] tick time + break; + case SC_KYOUGAKU: + val2 = 2*val1 + rand()%val1; + clif->status_change(bl,SI_ACTIVE_MONSTER_TRANSFORM,1,0,1002,0,0); + break; + case SC_KAGEMUSYA: + val3 = val1 * 2; + case SC_IZAYOI: + val2 = tick/1000; + tick_time = 1000; + break; + case SC_ZANGETSU: + if( (status_get_hp(bl)+status_get_sp(bl)) % 2 == 0) + val2 = status_get_lv(bl) / 2 + 50; else - status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100); - } - break; - case SC_ANGRIFFS_MODUS: - val2 = 50 + 20 * val1; //atk bonus - val3 = 40 + 20 * val1; // Flee reduction. - val4 = tick/1000; // hp/sp reduction timer - tick_time = 1000; - break; - case SC_GOLDENE_FERSE: - val2 = 10 + 10*val1; //max hp bonus - val3 = 6 + 4 * val1; // Aspd Bonus - val4 = 2 + 2 * val1; // Chance of holy attack - break; - case SC_OVERED_BOOST: - val2 = 300 + 40*val1; //flee bonus - val3 = 179 + 2*val1; //aspd bonus - break; - case SC_GRANITIC_ARMOR: - val2 = 2*val1; //dmg reduction - val3 = 6*val1; //dmg on status end - break; - case SC_MAGMA_FLOW: - val2 = 3*val1; //activation chance - break; - case SC_PYROCLASTIC: - val2 += 10*val1; //atk bonus - break; - case SC_PARALYSIS: //[Lighta] need real info - val2 = 2*val1; //def reduction - val3 = 500*val1; //varcast augmentation - break; - case SC_PAIN_KILLER: //[Lighta] need real info - val2 = 2*val1; //aspd reduction % - val3 = 2*val1; //dmg reduction % - if(sc->data[SC_PARALYSIS]) - sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration - break; - case SC_STYLE_CHANGE: //[Lighta] need real info - tick = -1; - if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; - else val2 = MH_MD_FIGHTING; - break; - default: - if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) - { //Status change with no calc, no icon, and no skill associated...? - ShowError("UnknownStatusChange [%d]\n", type); - return 0; - } + val2 -= 50; + break; + case SC_GENSOU: + { + int hp = status_get_hp(bl), lv = 5; + short per = 100 / (status_get_max_hp(bl) / hp); + + if( per <= 15 ) + lv = 1; + else if( per <= 30 ) + lv = 2; + else if( per <= 50 ) + lv = 3; + else if( per <= 75 ) + lv = 4; + if( hp % 2 == 0) + status_heal(bl, hp * (6-lv) * 4 / 100, status_get_sp(bl) * (6-lv) * 3 / 100, 1); + else + status_zap(bl, hp * (lv*4) / 100, status_get_sp(bl) * (lv*3) / 100); + } + break; + case SC_ANGRIFFS_MODUS: + val2 = 50 + 20 * val1; //atk bonus + val3 = 40 + 20 * val1; // Flee reduction. + val4 = tick/1000; // hp/sp reduction timer + tick_time = 1000; + break; + case SC_NEUTRALBARRIER: + tick_time = tick; + tick = -1; + break; + case SC_GOLDENE_FERSE: + val2 = 10 + 10*val1; //max hp bonus + val3 = 6 + 4 * val1; // Aspd Bonus + val4 = 2 + 2 * val1; // Chance of holy attack + break; + case SC_OVERED_BOOST: + val2 = 300 + 40*val1; //flee bonus + val3 = 179 + 2*val1; //aspd bonus + break; + case SC_GRANITIC_ARMOR: + val2 = 2*val1; //dmg reduction + val3 = 6*val1; //dmg on status end + break; + case SC_MAGMA_FLOW: + val2 = 3*val1; //activation chance + break; + case SC_PYROCLASTIC: + val2 += 10*val1; //atk bonus + break; + case SC_PARALYSIS: //[Lighta] need real info + val2 = 2*val1; //def reduction + val3 = 500*val1; //varcast augmentation + break; + case SC_PAIN_KILLER: //[Lighta] need real info + val2 = 2*val1; //aspd reduction % + val3 = 2*val1; //dmg reduction % + if(sc->data[SC_PARALYSIS]) + sc_start(bl, SC_ENDURE, 100, val1, tick); //start endure for same duration + break; + case SC_STYLE_CHANGE: //[Lighta] need real info + tick = -1; + if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; + else val2 = MH_MD_FIGHTING; + break; + default: + if( calc_flag == SCB_NONE && StatusSkillChangeTable[type] == 0 && StatusIconChangeTable[type] == 0 ) + { //Status change with no calc, no icon, and no skill associated...? + ShowError("UnknownStatusChange [%d]\n", type); + return 0; + } + } + } else { //Special considerations when loading SC data. + switch( type ) { + case SC_WEDDING: + case SC_XMAS: + case SC_SUMMER: + case SC_HANBOK: + if( !vd ) break; + clif->changelook(bl,LOOK_BASE,vd->class_); + clif->changelook(bl,LOOK_WEAPON,0); + clif->changelook(bl,LOOK_SHIELD,0); + clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + break; + case SC_KAAHI: + val4 = INVALID_TIMER; + break; + } } - else //Special considerations when loading SC data. - switch( type ) - { - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - clif_changelook(bl,LOOK_WEAPON,0); - clif_changelook(bl,LOOK_SHIELD,0); - clif_changelook(bl,LOOK_BASE,type==SC_WEDDING?JOB_WEDDING:type==SC_XMAS?JOB_XMAS:JOB_SUMMER); - clif_changelook(bl,LOOK_CLOTHES_COLOR,val4); - break; - case SC_KAAHI: - val4 = INVALID_TIMER; - break; + + /* [Ind/Hercules] */ + if( sd && StatusDisplayType[type] ) { + int dval1 = 0, dval2 = 0, dval3 = 0; + switch( type ) { + case SC_ALL_RIDING: + dval1 = 1; + break; + default: /* all others: just copy val1 */ + dval1 = val1; + break; + } + status_display_add(sd,type,dval1,dval2,dval3); } //Those that make you stop attacking/walking.... @@ -8631,7 +8654,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_CONFUSION: case SC_CLOSECONFINE: case SC_CLOSECONFINE2: - case SC_ANKLE: case SC_SPIDERWEB: case SC_ELECTRICSHOCKER: case SC_BITE: @@ -8647,6 +8669,10 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_PARALYSIS: unit_stop_walking(bl,1); break; + case SC_ANKLE: + if( battle_config.skill_trap_type || !map_flag_gvg(bl->m) ) + unit_stop_walking(bl,1); + break; case SC_HIDING: case SC_CLOAKING: case SC_CLOAKINGEXCEED: @@ -8664,8 +8690,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val // Set option as needed. opt_flag = 1; - switch(type) - { + switch(type) { //OPT1 case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break; case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break; @@ -8801,12 +8826,19 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val break; case SC_WEDDING: sc->option |= OPTION_WEDDING; + opt_flag |= 0x4; break; case SC_XMAS: sc->option |= OPTION_XMAS; + opt_flag |= 0x4; break; case SC_SUMMER: sc->option |= OPTION_SUMMER; + opt_flag |= 0x4; + break; + case SC_HANBOK: + sc->option |= OPTION_HANBOK; + opt_flag |= 0x4; break; case SC_ORCISH: sc->option |= OPTION_ORCISH; @@ -8819,20 +8851,25 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } //On Aegis, when turning on a status change, first goes the option packet, then the sc packet. - if(opt_flag) - clif_changeoption(bl); - - if (calc_flag&SCB_DYE) - { //Reset DYE color - if (vd && vd->cloth_color) - { + if(opt_flag) { + clif->changeoption(bl); + if( sd && opt_flag&0x4 ) { + clif->changelook(bl,LOOK_BASE,vd->class_); + clif->changelook(bl,LOOK_WEAPON,0); + clif->changelook(bl,LOOK_SHIELD,0); + clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); + } + } + if (calc_flag&SCB_DYE) { //Reset DYE color + if (vd && vd->cloth_color) { val4 = vd->cloth_color; - clif_changelook(bl,LOOK_CLOTHES_COLOR,0); + clif->changelook(bl,LOOK_CLOTHES_COLOR,0); } calc_flag&=~SCB_DYE; } - clif_status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); + if( !(flag&4 && StatusDisplayType[type]) ) + clif->status_change(bl,StatusIconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0); /** * used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first. @@ -8844,7 +8881,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if((sce=sc->data[type])) {// reuse old sc if( sce->timer != INVALID_TIMER ) delete_timer(sce->timer, status_change_timer); - sc_isnew = false; } else {// new sc ++(sc->count); sce = sc->data[type] = ers_alloc(sc_data_ers, struct status_change_entry); @@ -8861,10 +8897,6 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val if (calc_flag) status_calc_bl(bl,calc_flag); - if ( sc_isnew && StatusChangeStateTable[type] ) /* non-zero */ - status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],true); - - if(sd && sd->pd) pet_sc_check(sd, type); //Skotlex: Pet Status Effect Healing @@ -8888,7 +8920,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val } break; case SC_BOSSMAPINFO: - clif_bossmapinfo(sd->fd, map_id2boss(sce->val1), 0); // First Message + clif->bossmapinfo(sd->fd, map_id2boss(sce->val1), 0); // First Message break; case SC_MERC_HPUP: status_percent_heal(bl, 100, 0); // Recover Full HP @@ -8909,35 +8941,35 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val case SC_COMBO: switch (sce->val1) { case TK_STORMKICK: - clif_skill_nodamage(bl,bl,TK_READYSTORM,1,1); + clif->skill_nodamage(bl,bl,TK_READYSTORM,1,1); break; case TK_DOWNKICK: - clif_skill_nodamage(bl,bl,TK_READYDOWN,1,1); + clif->skill_nodamage(bl,bl,TK_READYDOWN,1,1); break; case TK_TURNKICK: - clif_skill_nodamage(bl,bl,TK_READYTURN,1,1); + clif->skill_nodamage(bl,bl,TK_READYTURN,1,1); break; case TK_COUNTER: - clif_skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); + clif->skill_nodamage(bl,bl,TK_READYCOUNTER,1,1); break; case MO_COMBOFINISH: case CH_TIGERFIST: case CH_CHAINCRUSH: if (sd) - clif_skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); + clif->skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL); break; case TK_JUMPKICK: if (sd) - clif_skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); + clif->skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL); break; case MO_TRIPLEATTACK: if (sd && pc_checkskill(sd, SR_DRAGONCOMBO) > 0) - clif_skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); + clif->skillinfo(sd,SR_DRAGONCOMBO, INF_SELF_SKILL); break; case SR_FALLENEMPIRE: if (sd){ - clif_skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); - clif_skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); + clif->skillinfo(sd,SR_GATEOFHELL, INF_SELF_SKILL); + clif->skillinfo(sd,SR_TIGERCANNON, INF_SELF_SKILL); } break; } @@ -8962,8 +8994,7 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val * 2 - Do clif * 3 - Do not remove some permanent/time-independent effects *------------------------------------------*/ -int status_change_clear(struct block_list* bl, int type) -{ +int status_change_clear(struct block_list* bl, int type) { struct status_change* sc; int i; @@ -8972,81 +9003,80 @@ int status_change_clear(struct block_list* bl, int type) if (!sc || !sc->count) return 0; - for(i = 0; i < SC_MAX; i++) - { + for(i = 0; i < SC_MAX; i++) { if(!sc->data[i]) continue; - if(type == 0) - switch (i) - { //Type 0: PC killed -> Place here statuses that do not dispel on death. - case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death - if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK ) - break; - case SC_WEIGHT50: - case SC_WEIGHT90: - case SC_EDP: - case SC_MELTDOWN: - case SC_XMAS: - case SC_SUMMER: - case SC_NOCHAT: - case SC_FUSION: - case SC_EARTHSCROLL: - case SC_READYSTORM: - case SC_READYDOWN: - case SC_READYCOUNTER: - case SC_READYTURN: - case SC_DODGE: - case SC_JAILED: - case SC_EXPBOOST: - case SC_ITEMBOOST: - case SC_HELLPOWER: - case SC_JEXPBOOST: - case SC_AUTOTRADE: - case SC_WHISTLE: - case SC_ASSNCROS: - case SC_POEMBRAGI: - case SC_APPLEIDUN: - case SC_HUMMING: - case SC_DONTFORGETME: - case SC_FORTUNE: - case SC_SERVICE4U: - case SC_FOOD_STR_CASH: - case SC_FOOD_AGI_CASH: - case SC_FOOD_VIT_CASH: - case SC_FOOD_DEX_CASH: - case SC_FOOD_INT_CASH: - case SC_FOOD_LUK_CASH: - case SC_DEF_RATE: - case SC_MDEF_RATE: - case SC_INCHEALRATE: - case SC_INCFLEE2: - case SC_INCHIT: - case SC_ATKPOTION: - case SC_MATKPOTION: - case SC_S_LIFEPOTION: - case SC_L_LIFEPOTION: - case SC_PUSH_CART: - continue; - + if(type == 0) { + switch (i) { //Type 0: PC killed -> Place here statuses that do not dispel on death. + case SC_ELEMENTALCHANGE://Only when its Holy or Dark that it doesn't dispell on death + if( sc->data[i]->val2 != ELE_HOLY && sc->data[i]->val2 != ELE_DARK ) + break; + case SC_WEIGHT50: + case SC_WEIGHT90: + case SC_EDP: + case SC_MELTDOWN: + case SC_XMAS: + case SC_SUMMER: + case SC_HANBOK: + case SC_NOCHAT: + case SC_FUSION: + case SC_EARTHSCROLL: + case SC_READYSTORM: + case SC_READYDOWN: + case SC_READYCOUNTER: + case SC_READYTURN: + case SC_DODGE: + case SC_JAILED: + case SC_EXPBOOST: + case SC_ITEMBOOST: + case SC_HELLPOWER: + case SC_JEXPBOOST: + case SC_AUTOTRADE: + case SC_WHISTLE: + case SC_ASSNCROS: + case SC_POEMBRAGI: + case SC_APPLEIDUN: + case SC_HUMMING: + case SC_DONTFORGETME: + case SC_FORTUNE: + case SC_SERVICE4U: + case SC_FOOD_STR_CASH: + case SC_FOOD_AGI_CASH: + case SC_FOOD_VIT_CASH: + case SC_FOOD_DEX_CASH: + case SC_FOOD_INT_CASH: + case SC_FOOD_LUK_CASH: + case SC_DEF_RATE: + case SC_MDEF_RATE: + case SC_INCHEALRATE: + case SC_INCFLEE2: + case SC_INCHIT: + case SC_ATKPOTION: + case SC_MATKPOTION: + case SC_S_LIFEPOTION: + case SC_L_LIFEPOTION: + case SC_PUSH_CART: + case SC_ALL_RIDING: + continue; + } } - if( type == 3 ) - { - switch (i) - {// TODO: This list may be incomplete + if( type == 3 ) { + switch (i) {// TODO: This list may be incomplete case SC_WEIGHT50: case SC_WEIGHT90: case SC_NOCHAT: case SC_PUSH_CART: + case SC_ALL_RIDING: continue; } } status_change_end(bl, (sc_type)i, INVALID_TIMER); - if( type == 1 && sc->data[i] ) - { //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex] + if( type == 1 && sc->data[i] ) { + //If for some reason status_change_end decides to still keep the status when quitting. [Skotlex] (sc->count)--; if (sc->data[i]->timer != INVALID_TIMER) delete_timer(sc->data[i]->timer, status_change_timer); @@ -9058,10 +9088,12 @@ int status_change_clear(struct block_list* bl, int type) sc->opt1 = 0; sc->opt2 = 0; sc->opt3 = 0; - sc->option &= OPTION_MASK; - + sc->bs_counter = 0; +#ifndef RENEWAL + sc->sg_counter = 0; +#endif if( type == 0 || type == 2 ) - clif_changeoption(bl); + clif->changeoption(bl); return 1; } @@ -9069,8 +9101,7 @@ int status_change_clear(struct block_list* bl, int type) /*========================================== * Special condition we want to effectuate, check before ending a status. *------------------------------------------*/ -int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) -{ +int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const char* file, int line) { struct map_session_data *sd; struct status_change *sc; struct status_change_entry *sce; @@ -9120,11 +9151,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const (sc->count)--; - if ( StatusChangeStateTable[type] ) - status_calc_state(bl,sc,( enum scs_flag ) StatusChangeStateTable[type],false); - sc->data[type] = NULL; + if( sd && StatusDisplayType[type] ) { + status_display_remove(sd,type); + } + vd = status_get_viewdata(bl); calc_flag = StatusChangeFlagTable[type]; switch(type){ @@ -9137,30 +9169,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } case SC_PYROCLASTIC: if(bl->type == BL_PC) - skill_break_equip(bl,EQP_WEAPON,10000,BCT_SELF); + skill->break_equip(bl,EQP_WEAPON,10000,BCT_SELF); break; - case SC_WEDDING: - case SC_XMAS: - case SC_SUMMER: - if (!vd) break; - if (sd) - { //Load data from sd->status.* as the stored values could have changed. - //Must remove OPTION to prevent class being rechanged. - sc->option &= type==SC_WEDDING?~OPTION_WEDDING:type==SC_XMAS?~OPTION_XMAS:~OPTION_SUMMER; - clif_changeoption(&sd->bl); - status_set_viewdata(bl, sd->status.class_); - } else { - vd->class_ = sce->val1; - vd->weapon = sce->val2; - vd->shield = sce->val3; - vd->cloth_color = sce->val4; - } - clif_changelook(bl,LOOK_BASE,vd->class_); - clif_changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color); - clif_changelook(bl,LOOK_WEAPON,vd->weapon); - clif_changelook(bl,LOOK_SHIELD,vd->shield); - if(sd) clif_skillinfoblock(sd); - break; case SC_RUN: { struct unit_data *ud = unit_bl2ud(bl); @@ -9176,7 +9186,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const DIFF_TICK(gettick(), sce->val4) <= 1000 && (!sd || (sd->weapontype1 == 0 && sd->weapontype2 == 0)) ) - sc_start(bl,SC_SPURT,100,sce->val1,skill_get_time2(status_sc2skill(type), sce->val1)); + sc_start(bl,SC_SPURT,100,sce->val1,skill->get_time2(status_sc2skill(type), sce->val1)); } break; case SC_AUTOBERSERK: @@ -9216,7 +9226,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const ((TBL_PC*)d_bl)->devotion[sce->val2] = 0; else if( d_bl->type == BL_MER ) ((TBL_MER*)d_bl)->devotion_flag = 0; - clif_devotion(d_bl, NULL); + clif->devotion(d_bl, NULL); } status_change_end(bl, SC_AUTOGUARD, INVALID_TIMER); @@ -9238,7 +9248,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const tsc->data[SC_BLADESTOP]->val4 = 0; status_change_end(tbl, SC_BLADESTOP, INVALID_TIMER); } - clif_bladestop(bl, tid, 0); + clif->bladestop(bl, tid, 0); } break; case SC_DANCING: @@ -9278,7 +9288,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if(sce->val2) {// erase associated land skill - group = skill_id2group(sce->val2); + group = skill->id2group(sce->val2); if( group == NULL ) { @@ -9291,11 +9301,11 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } sce->val2 = 0; - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); } if((sce->val1&0xFFFF) == CG_MOONLIT) - clif_status_change(bl,SI_MOONLIT,0,0,0,0,0); + clif->sc_end(bl,bl->id,AREA,SI_MOONLIT); status_change_end(bl, SC_LONGING, INVALID_TIMER); } @@ -9305,15 +9315,15 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const sd->status.manner = 0; if (sd && tid == INVALID_TIMER) { - clif_changestatus(sd,SP_MANNER,sd->status.manner); - clif_updatestatus(sd,SP_MANNER); + clif->changestatus(sd,SP_MANNER,sd->status.manner); + clif->updatestatus(sd,SP_MANNER); } break; case SC_SPLASHER: { struct block_list *src=map_id2bl(sce->val3); if(src && tid != INVALID_TIMER) - skill_castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL ); + skill->castend_damage_id(src, bl, sce->val2, sce->val1, gettick(), SD_LEVEL ); } break; case SC_CLOSECONFINE2: @@ -9331,8 +9341,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (sce->val2 > 0) { //Caster has been unlocked... nearby chars need to be unlocked. int range = 1 - +skill_get_range2(bl, status_sc2skill(type), sce->val1) - +skill_get_range2(bl, TF_BACKSLIDING, 1); //Since most people use this to escape the hold.... + +skill->get_range2(bl, status_sc2skill(type), sce->val1) + +skill->get_range2(bl, TF_BACKSLIDING, 1); //Since most people use this to escape the hold.... map_foreachinarea(status_change_timer_sub, bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,gettick()); } @@ -9343,18 +9353,18 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const case MO_COMBOFINISH: case CH_TIGERFIST: case CH_CHAINCRUSH: - clif_skillinfo(sd, MO_EXTREMITYFIST, 0); + clif->skillinfo(sd, MO_EXTREMITYFIST, 0); break; case TK_JUMPKICK: - clif_skillinfo(sd, TK_JUMPKICK, 0); + clif->skillinfo(sd, TK_JUMPKICK, 0); break; case MO_TRIPLEATTACK: if (pc_checkskill(sd, SR_DRAGONCOMBO) > 0) - clif_skillinfo(sd, SR_DRAGONCOMBO, 0); + clif->skillinfo(sd, SR_DRAGONCOMBO, 0); break; case SR_FALLENEMPIRE: - clif_skillinfo(sd, SR_GATEOFHELL, 0); - clif_skillinfo(sd, SR_TIGERCANNON, 0); + clif->skillinfo(sd, SR_GATEOFHELL, 0); + clif->skillinfo(sd, SR_TIGERCANNON, 0); break; } break; @@ -9386,23 +9396,23 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const status_change_end(bl, SC_ENDURE, INVALID_TIMER); } case SC__BLOODYLUST: - sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill_get_time(LK_BERSERK, sce->val1)); + sc_start4(bl, SC_REGENERATION, 100, 10,0,0,(RGN_HP|RGN_SP), skill->get_time(LK_BERSERK, sce->val1)); if( type == SC_SATURDAYNIGHTFEVER ) //Sit down force of Saturday Night Fever has the duration of only 3 seconds. - sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill_get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); + sc_start(bl,SC_SITDOWN_FORCE,100,sce->val1,skill->get_time2(WM_SATURDAY_NIGHT_FEVER,sce->val1)); break; case SC_GOSPEL: if (sce->val3) { //Clear the group. - struct skill_unit_group* group = skill_id2group(sce->val3); + struct skill_unit_group* group = skill->id2group(sce->val3); sce->val3 = 0; - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); } break; case SC_HERMODE: if(sce->val3 == BCT_SELF) - skill_clear_unitgroup(bl); + skill->clear_unitgroup(bl); break; case SC_BASILICA: //Clear the skill area. [Skotlex] - skill_clear_unitgroup(bl); + skill->clear_unitgroup(bl); break; case SC_TRICKDEAD: if (vd) vd->dead_sit = 0; @@ -9410,10 +9420,10 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const case SC_WARM: case SC__MANHOLE: if (sce->val4) { //Clear the group. - struct skill_unit_group* group = skill_id2group(sce->val4); + struct skill_unit_group* group = skill->id2group(sce->val4); sce->val4 = 0; if( group ) /* might have been cleared before status ended, e.g. land protector */ - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); } break; case SC_KAAHI: @@ -9458,17 +9468,17 @@ 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(sd,0); break; case SC_HALLUCINATIONWALK: - sc_start(bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill_get_time2(GC_HALLUCINATIONWALK,sce->val1)); + sc_start(bl,SC_HALLUCINATIONWALK_POSTDELAY,100,sce->val1,skill->get_time2(GC_HALLUCINATIONWALK,sce->val1)); break; case SC_WHITEIMPRISON: { struct block_list* src = map_id2bl(sce->val2); if( tid == -1 || !src) break; // Terminated by Damage - status_fix_damage(src,bl,400*sce->val1,clif_damage(bl,bl,gettick(),0,0,400*sce->val1,0,0,0)); + status_fix_damage(src,bl,400*sce->val1,clif->damage(bl,bl,gettick(),0,0,400*sce->val1,0,0,0)); } break; case SC_WUGDASH: @@ -9494,24 +9504,24 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const case SC_SITDOWN_FORCE: if( sd && pc_issit(sd) ) { pc_setstand(sd); - clif_standing(bl); + clif->standing(bl); } break; case SC_NEUTRALBARRIER_MASTER: case SC_STEALTHFIELD_MASTER: if( sce->val2 ) { - struct skill_unit_group* group = skill_id2group(sce->val2); + struct skill_unit_group* group = skill->id2group(sce->val2); sce->val2 = 0; if( group ) /* might have been cleared before status ended, e.g. land protector */ - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); } break; case SC_BANDING: if(sce->val4) { - struct skill_unit_group *group = skill_id2group(sce->val4); + struct skill_unit_group *group = skill->id2group(sce->val4); sce->val4 = 0; if( group ) /* might have been cleared before status ended, e.g. land protector */ - skill_delunitgroup(group); + skill->del_unitgroup(group,ALC_MARK); } break; case SC_CURSEDCIRCLE_ATKER: @@ -9525,7 +9535,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const pc_delspiritball(sd, sd->spiritball, 0); status_change_end(bl, SC_EXPLOSIONSPIRITS, INVALID_TIMER); while( i > 0 ) { - pc_addspiritball(sd, skill_get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), 5); + pc_addspiritball(sd, skill->get_time(MO_CALLSPIRITS, pc_checkskill(sd,MO_CALLSPIRITS)), 5); --i; } } @@ -9536,7 +9546,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct status_change *sc = status_get_sc(src); if( sc && sc->data[SC_CURSEDCIRCLE_ATKER] && --(sc->data[SC_CURSEDCIRCLE_ATKER]->val2) == 0 ){ status_change_end(src, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); - clif_bladestop(bl, sce->val2, 0); + clif->bladestop(bl, sce->val2, 0); } } break; @@ -9549,197 +9559,208 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } } break; - case SC_VACUUM_EXTREME: - if(sc && sc->cant.move > 0) sc->cant.move--; - break; case SC_KYOUGAKU: - clif_status_load(bl, SI_KYOUGAKU, 0); // Avoid client crash - clif_status_load(bl, SI_ACTIVE_MONSTER_TRANSFORM, 0); + clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_KYOUGAKU); + clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_ACTIVE_MONSTER_TRANSFORM); break; case SC_INTRAVISION: calc_flag = SCB_ALL;/* required for overlapping */ break; - } + } opt_flag = 1; switch(type){ - case SC_STONE: - case SC_FREEZE: - case SC_STUN: - case SC_SLEEP: - case SC_DEEPSLEEP: - case SC_BURNING: - case SC_WHITEIMPRISON: - case SC_CRYSTALIZE: - sc->opt1 = 0; - break; + case SC_STONE: + case SC_FREEZE: + case SC_STUN: + case SC_SLEEP: + case SC_DEEPSLEEP: + case SC_BURNING: + case SC_WHITEIMPRISON: + case SC_CRYSTALIZE: + sc->opt1 = 0; + break; - case SC_POISON: - case SC_CURSE: - case SC_SILENCE: - case SC_BLIND: - sc->opt2 &= ~(1<<(type-SC_POISON)); - break; - case SC_DPOISON: - sc->opt2 &= ~OPT2_DPOISON; - break; - case SC_SIGNUMCRUCIS: - sc->opt2 &= ~OPT2_SIGNUMCRUCIS; - break; + case SC_POISON: + case SC_CURSE: + case SC_SILENCE: + case SC_BLIND: + sc->opt2 &= ~(1<<(type-SC_POISON)); + break; + case SC_DPOISON: + sc->opt2 &= ~OPT2_DPOISON; + break; + case SC_SIGNUMCRUCIS: + sc->opt2 &= ~OPT2_SIGNUMCRUCIS; + break; - case SC_HIDING: - sc->option &= ~OPTION_HIDE; - opt_flag|= 2|4; //Check for warp trigger + AoE trigger - break; - case SC_CLOAKING: - case SC_CLOAKINGEXCEED: - case SC__INVISIBILITY: - sc->option &= ~OPTION_CLOAK; - case SC_CAMOUFLAGE: - opt_flag|= 2; - break; - case SC_CHASEWALK: - sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK); - opt_flag|= 2; - break; - case SC_SIGHT: - sc->option &= ~OPTION_SIGHT; - break; - case SC_WEDDING: - sc->option &= ~OPTION_WEDDING; - break; - case SC_XMAS: - sc->option &= ~OPTION_XMAS; - break; - case SC_SUMMER: - sc->option &= ~OPTION_SUMMER; - break; - case SC_ORCISH: - sc->option &= ~OPTION_ORCISH; - break; - case SC_RUWACH: - sc->option &= ~OPTION_RUWACH; - break; - case SC_FUSION: - sc->option &= ~OPTION_FLYING; - break; - //opt3 - case SC_TWOHANDQUICKEN: - case SC_ONEHAND: - case SC_SPEARQUICKEN: - case SC_CONCENTRATION: - case SC_MERC_QUICKEN: - sc->opt3 &= ~OPT3_QUICKEN; - opt_flag = 0; - break; - case SC_OVERTHRUST: - case SC_MAXOVERTHRUST: - case SC_SWOO: - sc->opt3 &= ~OPT3_OVERTHRUST; - if( type == SC_SWOO ) - opt_flag = 8; - else + case SC_HIDING: + sc->option &= ~OPTION_HIDE; + opt_flag|= 2|4; //Check for warp trigger + AoE trigger + break; + case SC_CLOAKING: + case SC_CLOAKINGEXCEED: + case SC__INVISIBILITY: + sc->option &= ~OPTION_CLOAK; + case SC_CAMOUFLAGE: + opt_flag|= 2; + break; + case SC_CHASEWALK: + sc->option &= ~(OPTION_CHASEWALK|OPTION_CLOAK); + opt_flag|= 2; + break; + case SC_SIGHT: + sc->option &= ~OPTION_SIGHT; + break; + case SC_WEDDING: + sc->option &= ~OPTION_WEDDING; + opt_flag |= 0x4; + break; + case SC_XMAS: + sc->option &= ~OPTION_XMAS; + opt_flag |= 0x4; + break; + case SC_SUMMER: + sc->option &= ~OPTION_SUMMER; + opt_flag |= 0x4; + break; + case SC_HANBOK: + sc->option &= ~OPTION_HANBOK; + opt_flag |= 0x4; + break; + case SC_ORCISH: + sc->option &= ~OPTION_ORCISH; + break; + case SC_RUWACH: + sc->option &= ~OPTION_RUWACH; + break; + case SC_FUSION: + sc->option &= ~OPTION_FLYING; + break; + //opt3 + case SC_TWOHANDQUICKEN: + case SC_ONEHAND: + case SC_SPEARQUICKEN: + case SC_CONCENTRATION: + case SC_MERC_QUICKEN: + sc->opt3 &= ~OPT3_QUICKEN; opt_flag = 0; - break; - case SC_ENERGYCOAT: - case SC_SKE: - sc->opt3 &= ~OPT3_ENERGYCOAT; - opt_flag = 0; - break; - case SC_INCATKRATE: //Simulated Explosion spirits effect. - if (bl->type != BL_MOB) - { + break; + case SC_OVERTHRUST: + case SC_MAXOVERTHRUST: + case SC_SWOO: + sc->opt3 &= ~OPT3_OVERTHRUST; + if( type == SC_SWOO ) + opt_flag = 8; + else + opt_flag = 0; + break; + case SC_ENERGYCOAT: + case SC_SKE: + sc->opt3 &= ~OPT3_ENERGYCOAT; opt_flag = 0; break; - } - case SC_EXPLOSIONSPIRITS: - sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; - opt_flag = 0; - break; - case SC_STEELBODY: - case SC_SKA: - sc->opt3 &= ~OPT3_STEELBODY; - opt_flag = 0; - break; - case SC_BLADESTOP: - sc->opt3 &= ~OPT3_BLADESTOP; - opt_flag = 0; - break; - case SC_AURABLADE: - sc->opt3 &= ~OPT3_AURABLADE; - opt_flag = 0; - break; - case SC_BERSERK: - opt_flag = 0; -// case SC__BLOODYLUST: - sc->opt3 &= ~OPT3_BERSERK; - break; -// case ???: // doesn't seem to do anything -// sc->opt3 &= ~OPT3_LIGHTBLADE; -// opt_flag = 0; -// break; - case SC_DANCING: - if ((sce->val1&0xFFFF) == CG_MOONLIT) - sc->opt3 &= ~OPT3_MOONLIT; - opt_flag = 0; - break; - case SC_MARIONETTE: - case SC_MARIONETTE2: - sc->opt3 &= ~OPT3_MARIONETTE; - opt_flag = 0; - break; - case SC_ASSUMPTIO: - sc->opt3 &= ~OPT3_ASSUMPTIO; - opt_flag = 0; - break; - case SC_WARM: //SG skills [Komurka] - sc->opt3 &= ~OPT3_WARM; - opt_flag = 0; - break; - case SC_KAITE: - sc->opt3 &= ~OPT3_KAITE; - opt_flag = 0; - break; - case SC_BUNSINJYUTSU: - sc->opt3 &= ~OPT3_BUNSIN; - opt_flag = 0; - break; - case SC_SPIRIT: - sc->opt3 &= ~OPT3_SOULLINK; - opt_flag = 0; - break; - case SC_CHANGEUNDEAD: - sc->opt3 &= ~OPT3_UNDEAD; - opt_flag = 0; - break; -// case ???: // from DA_CONTRACT (looks like biolab mobs aura) -// sc->opt3 &= ~OPT3_CONTRACT; -// opt_flag = 0; -// break; - default: - opt_flag = 0; + case SC_INCATKRATE: //Simulated Explosion spirits effect. + if (bl->type != BL_MOB) + { + opt_flag = 0; + break; + } + case SC_EXPLOSIONSPIRITS: + sc->opt3 &= ~OPT3_EXPLOSIONSPIRITS; + opt_flag = 0; + break; + case SC_STEELBODY: + case SC_SKA: + sc->opt3 &= ~OPT3_STEELBODY; + opt_flag = 0; + break; + case SC_BLADESTOP: + sc->opt3 &= ~OPT3_BLADESTOP; + opt_flag = 0; + break; + case SC_AURABLADE: + sc->opt3 &= ~OPT3_AURABLADE; + opt_flag = 0; + break; + case SC_BERSERK: + opt_flag = 0; + // case SC__BLOODYLUST: + sc->opt3 &= ~OPT3_BERSERK; + break; + // case ???: // doesn't seem to do anything + // sc->opt3 &= ~OPT3_LIGHTBLADE; + // opt_flag = 0; + // break; + case SC_DANCING: + if ((sce->val1&0xFFFF) == CG_MOONLIT) + sc->opt3 &= ~OPT3_MOONLIT; + opt_flag = 0; + break; + case SC_MARIONETTE: + case SC_MARIONETTE2: + sc->opt3 &= ~OPT3_MARIONETTE; + opt_flag = 0; + break; + case SC_ASSUMPTIO: + sc->opt3 &= ~OPT3_ASSUMPTIO; + opt_flag = 0; + break; + case SC_WARM: //SG skills [Komurka] + sc->opt3 &= ~OPT3_WARM; + opt_flag = 0; + break; + case SC_KAITE: + sc->opt3 &= ~OPT3_KAITE; + opt_flag = 0; + break; + case SC_BUNSINJYUTSU: + sc->opt3 &= ~OPT3_BUNSIN; + opt_flag = 0; + break; + case SC_SPIRIT: + sc->opt3 &= ~OPT3_SOULLINK; + opt_flag = 0; + break; + case SC_CHANGEUNDEAD: + sc->opt3 &= ~OPT3_UNDEAD; + opt_flag = 0; + break; + // case ???: // from DA_CONTRACT (looks like biolab mobs aura) + // sc->opt3 &= ~OPT3_CONTRACT; + // opt_flag = 0; + // break; + default: + opt_flag = 0; } - if (calc_flag&SCB_DYE) - { //Restore DYE color + if (calc_flag&SCB_DYE) { //Restore DYE color if (vd && !vd->cloth_color && sce->val4) - clif_changelook(bl,LOOK_CLOTHES_COLOR,sce->val4); + clif->changelook(bl,LOOK_CLOTHES_COLOR,sce->val4); calc_flag&=~SCB_DYE; } //On Aegis, when turning off a status change, first goes the sc packet, then the option packet. - clif_status_change(bl,StatusIconChangeTable[type],0,0,0,0,0); + clif->sc_end(bl,bl->id,AREA,StatusIconChangeTable[type]); if( opt_flag&8 ) //bugreport:681 - clif_changeoption2(bl); - else if(opt_flag) - clif_changeoption(bl); + clif->changeoption2(bl); + else if(opt_flag) { + clif->changeoption(bl); + if( sd && opt_flag&0x4 ) { + clif->changelook(bl,LOOK_BASE,vd->class_); + clif->get_weapon_view(sd, &sd->vd.weapon, &sd->vd.shield); + clif->changelook(bl,LOOK_WEAPON,sd->vd.weapon); + clif->changelook(bl,LOOK_SHIELD,sd->vd.shield); + clif->changelook(bl,LOOK_CLOTHES_COLOR,cap_value(sd->status.clothes_color,0,battle_config.max_cloth_color)); + } + } if (calc_flag) status_calc_bl(bl,calc_flag); if(opt_flag&4) //Out of hiding, invoke on place. - skill_unit_move(bl,gettick(),1); + skill->unit_move(bl,gettick(),1); if(opt_flag&2 && sd && map_getcell(bl->m,bl->x,bl->y,CELL_CHKNPC)) npc_touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event. @@ -9841,7 +9862,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) if (!sc->data[SC_INCSTR]) { sc_start(bl, SC_INCSTR,100,1<<(sce->val1-1), (sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration - *skill_get_time2(status_sc2skill(type),sce->val1)); + *skill->get_time2(status_sc2skill(type),sce->val1)); } sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data); return 0; @@ -9894,7 +9915,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) unit_stop_walking(bl,1); unit_stop_attack(bl); sc->opt1 = OPT1_STONE; - clif_changeoption(bl); + clif->changeoption(bl); sc_timer_next(1000+tick,status_change_timer, bl->id, data ); status_calc_bl(bl, StatusChangeFlagTable[type]); return 0; @@ -9951,6 +9972,9 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) if (--(sce->val4) >= 0) { int hp = rnd()%600 + 200; struct block_list* src = map_id2bl(sce->val2); + if( src && bl && bl->type == BL_MOB ) { + mob_log_damage((TBL_MOB*)bl,src,sd||hp<status->hp?hp:status->hp-1); + } map_freeblock_lock(); status_fix_damage(src, bl, sd||hp<status->hp?hp:status->hp-1, 1); if( sc->data[type] ) { @@ -9985,7 +10009,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) struct mob_data *boss_md = map_id2boss(sce->val1); if( boss_md && sd->bl.m == boss_md->bl.m ) { - clif_bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap + clif->bossmapinfo(sd->fd, boss_md, 1); // Update X - Y on minimap if (boss_md->bl.prev != NULL) { sc_timer_next(5000 + tick, status_change_timer, bl->id, data); return 0; @@ -10063,8 +10087,8 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_NOCHAT: if(sd){ sd->status.manner++; - clif_changestatus(sd,SP_MANNER,sd->status.manner); - clif_updatestatus(sd,SP_MANNER); + clif->changestatus(sd,SP_MANNER,sd->status.manner); + clif->updatestatus(sd,SP_MANNER); if (sd->status.manner < 0) { //Every 60 seconds your manner goes up by 1 until it gets back to 0. sc_timer_next(60000+tick, status_change_timer, bl->id, data); @@ -10078,7 +10102,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) //if (sce->val4 % 1000 == 0) { // char timer[10]; // snprintf (timer, 10, "%d", sce->val4/1000); - // clif_message(bl, timer); + // clif->message(bl, timer); //} if((sce->val4 -= 500) > 0) { sc_timer_next(500 + tick, status_change_timer, bl->id, data); @@ -10136,7 +10160,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_PYREXIA: if( --(sce->val4) >= 0 ) { map_freeblock_lock(); - clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0); + clif->damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,100,0,0,0); status_fix_damage(NULL,bl,100,0); if( sc->data[type] ) { sc_timer_next(3000+tick,status_change_timer,bl->id,data); @@ -10152,7 +10176,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) damage += status->vit * (sce->val1 - 3); unit_skillcastcancel(bl,2); map_freeblock_lock(); - status_damage(bl, bl, damage, 0, clif_damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1); + status_damage(bl, bl, damage, 0, clif->damage(bl,bl,tick,status_get_amotion(bl),status_get_dmotion(bl)+500,damage,1,0,0), 1); if( sc->data[type] ) { sc_timer_next(1000 + tick, status_change_timer, bl->id, data ); } @@ -10186,20 +10210,20 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) } while( mushroom_skill_id == 0 ); - switch( skill_get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage + switch( skill->get_casttype(mushroom_skill_id) ) { // Magic Mushroom skills are buffs or area damage case CAST_GROUND: - skill_castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0); + skill->castend_pos2(bl,bl->x,bl->y,mushroom_skill_id,1,tick,0); break; case CAST_NODAMAGE: - skill_castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0); + skill->castend_nodamage_id(bl,bl,mushroom_skill_id,1,tick,0); break; case CAST_DAMAGE: - skill_castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0); + skill->castend_damage_id(bl,bl,mushroom_skill_id,1,tick,0); break; } } - clif_emotion(bl,E_HEH); + clif->emotion(bl,E_HEH); sc_timer_next(4000+tick,status_change_timer,bl->id,data); } return 0; @@ -10210,7 +10234,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) if( --(sce->val4) >= 0 ) { //Damage is every 10 seconds including 3%sp drain. map_freeblock_lock(); - clif_damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0); + clif->damage(bl,bl,tick,status_get_amotion(bl),1,1,0,0,0); status_damage(NULL, bl, 1, status->max_sp * 3 / 100, 0, 0); //cancel dmg only if cancelable if( sc->data[type] ) { sc_timer_next(10000 + tick, status_change_timer, bl->id, data ); @@ -10223,7 +10247,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_OBLIVIONCURSE: if( --(sce->val4) >= 0 ) { - clif_emotion(bl,E_WHAT); + clif->emotion(bl,E_WHAT); sc_timer_next(3000 + tick, status_change_timer, bl->id, data ); return 0; } @@ -10264,7 +10288,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) int damage = 1000 + 3 * status_get_max_hp(bl) / 100; // Deals fixed (1000 + 3%*MaxHP) map_freeblock_lock(); - clif_damage(bl,bl,tick,0,0,damage,1,9,0); //damage is like endure effect with no walk delay + clif->damage(bl,bl,tick,0,0,damage,1,9,0); //damage is like endure effect with no walk delay status_damage(src, bl, damage, 0, 0, 1); if( sc->data[type]){ // Target still lives. [LimitLine] @@ -10363,10 +10387,6 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; case SC_VACUUM_EXTREME: if( --(sce->val4) >= 0 ){ - if( !unit_is_walking(bl) && !sce->val2 ){ - sc->cant.move++; - sce->val2 = 1; - } sc_timer_next(100 + tick, status_change_timer, bl->id, data); return 0; } @@ -10379,7 +10399,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) break; map_freeblock_lock(); damage = 200 + 100 * sce->val1 + status_get_int(src); - status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,0,0), 1); + status_damage(src, bl, damage, 0, clif->damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,0,0), 1); unit_skillcastcancel(bl,1); if ( sc->data[type] ) { sc_timer_next(1000 + tick, status_change_timer, bl->id, data); @@ -10393,7 +10413,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_VOICEOFSIREN: if( --(sce->val4) >= 0 ) { - clif_emotion(bl,E_LV); + clif->emotion(bl,E_LV); sc_timer_next(2000 + tick, status_change_timer, bl->id, data); return 0; } @@ -10487,7 +10507,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) int damage = status->max_hp / 100; // Suggestion 1% each second if( damage >= status->hp ) damage = status->hp - 1; // Do not kill, just keep you with 1 hp minimum map_freeblock_lock(); - status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,0,0)); + status_fix_damage(NULL,bl,damage,clif->damage(bl,bl,tick,0,0,damage,0,0,0)); if( sc->data[type] ) { sc_timer_next(1000 + tick, status_change_timer, bl->id, data); } @@ -10547,7 +10567,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) case SC_STONE_SHIELD: case SC_SOLID_SKIN: if( !status_charge(bl,0,sce->val2) ){ - struct block_list *s_bl = battle_get_master(bl); + struct block_list *s_bl = battle->get_master(bl); if( s_bl ) status_change_end(s_bl,type+1,INVALID_TIMER); status_change_end(bl,type,INVALID_TIMER); @@ -10564,7 +10584,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data) pc_stop_walking(sd,1|4); pc_stop_attack(sd); pc_setsit(sd); - clif_sitting(bl); + clif->sitting(bl); } sc_timer_next(10000 + tick, status_change_timer, bl->id, data); return 0; @@ -10644,20 +10664,21 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) status_change_end(bl, SC_CAMOUFLAGE, INVALID_TIMER); status_change_end(bl, SC_CLOAKINGEXCEED, INVALID_TIMER); status_change_end(bl, SC__INVISIBILITY, INVALID_TIMER); - if(battle_check_target( src, bl, BCT_ENEMY ) > 0) - skill_attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0); + if(battle->check_target( src, bl, BCT_ENEMY ) > 0) + skill->attack(BF_MAGIC,src,src,bl,AL_RUWACH,1,tick,0); } if( tsc && tsc->data[SC__SHADOWFORM] && (sce && sce->val4 >0 && sce->val4%2000 == 0) && // for every 2 seconds do the checking rnd()%100 < 100-tsc->data[SC__SHADOWFORM]->val1*10 ) // [100 - (Skill Level x 10)] % status_change_end(bl, SC__SHADOWFORM, INVALID_TIMER); break; case SC_SIGHTBLASTER: - if (battle_check_target( src, bl, BCT_ENEMY ) > 0 && + if (battle->check_target( src, bl, BCT_ENEMY ) > 0 && status_check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)) { - skill_attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0); - if (sce && !(bl->type&BL_SKILL)) //The hit is not counted if it's against a trap + if (sce && !(bl->type&BL_SKILL) //The hit is not counted if it's against a trap + && skill->attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,1,tick,0)){ sce->val2 = 0; //This signals it to end. + } } break; case SC_CLOSECONFINE: @@ -10669,7 +10690,7 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) break; case SC_CURSEDCIRCLE_TARGET: if( tsc && tsc->data[SC_CURSEDCIRCLE_TARGET] && tsc->data[SC_CURSEDCIRCLE_TARGET]->val2 == src->id ) { - clif_bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0); + clif->bladestop(bl, tsc->data[SC_CURSEDCIRCLE_TARGET]->val2, 0); status_change_end(bl, type, INVALID_TIMER); } break; @@ -10752,6 +10773,8 @@ int status_change_clear_buffs (struct block_list* bl, int type) case SC_ABUNDANCE: case SC_CURSEDCIRCLE_ATKER: case SC_CURSEDCIRCLE_TARGET: + case SC_PUSH_CART: + case SC_ALL_RIDING: continue; //Debuffs that can be removed. @@ -11076,12 +11099,12 @@ static int status_natural_heal(struct block_list* bl, va_list args) sd->state.doridori = 0; if ((rate = pc_checkskill(sd,TK_SPTIME))) sc_start(bl,status_skill2sc(TK_SPTIME), - 100,rate,skill_get_time(TK_SPTIME, rate)); + 100,rate,skill->get_time(TK_SPTIME, rate)); if ( (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR && rnd()%10000 < battle_config.sg_angel_skill_ratio ) { //Angel of the Sun/Moon/Star - clif_feel_hate_reset(sd); + clif->feel_hate_reset(sd); pc_resethate(sd); pc_resetfeel(sd); } @@ -11263,13 +11286,13 @@ int status_readdb(void) #ifdef RENEWAL_ASPD - sv_readdb(db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, &status_readdb_job1); + sv->readdb(db_path, "re/job_db1.txt", ',', 6+MAX_WEAPON_TYPE, 6+MAX_WEAPON_TYPE, -1, &status_readdb_job1); #else - sv_readdb(db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1); + sv->readdb(db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, &status_readdb_job1); #endif - sv_readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); - sv_readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); - sv_readdb(db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine); + sv->readdb(db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, &status_readdb_job2); + sv->readdb(db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(atkmods), &status_readdb_sizefix); + sv->readdb(db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(refine_info), &status_readdb_refine); return 0; } diff --git a/src/map/status.h b/src/map/status.h index 44012566f..4a7af884e 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -16,9 +16,9 @@ struct status_change; * Changing this limit requires edits to refine_db.txt **/ #ifdef RENEWAL -# define MAX_REFINE 20 + #define MAX_REFINE 20 #else -# define MAX_REFINE 10 + #define MAX_REFINE 10 #endif enum refine_type { @@ -650,6 +650,9 @@ typedef enum sc_type { #ifdef RENEWAL SC_EXTREMITYFIST2, #endif + + SC_ALL_RIDING, + SC_HANBOK, SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; @@ -1450,30 +1453,30 @@ enum { }; enum { - OPTION_NOTHING = 0x00000000, - OPTION_SIGHT = 0x00000001, - OPTION_HIDE = 0x00000002, - OPTION_CLOAK = 0x00000004, - OPTION_FALCON = 0x00000010, - OPTION_RIDING = 0x00000020, - OPTION_INVISIBLE = 0x00000040, - OPTION_ORCISH = 0x00000800, - OPTION_WEDDING = 0x00001000, - OPTION_RUWACH = 0x00002000, - OPTION_CHASEWALK = 0x00004000, - OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007. - OPTION_XMAS = 0x00010000, - OPTION_TRANSFORM = 0x00020000, - OPTION_SUMMER = 0x00040000, - OPTION_DRAGON1 = 0x00080000, - OPTION_WUG = 0x00100000, - OPTION_WUGRIDER = 0x00200000, - OPTION_MADOGEAR = 0x00400000, - OPTION_DRAGON2 = 0x00800000, - OPTION_DRAGON3 = 0x01000000, - OPTION_DRAGON4 = 0x02000000, - OPTION_DRAGON5 = 0x04000000, - OPTION_MOUNTING = 0x08000000, + OPTION_NOTHING = 0x00000000, + OPTION_SIGHT = 0x00000001, + OPTION_HIDE = 0x00000002, + OPTION_CLOAK = 0x00000004, + OPTION_FALCON = 0x00000010, + OPTION_RIDING = 0x00000020, + OPTION_INVISIBLE = 0x00000040, + OPTION_ORCISH = 0x00000800, + OPTION_WEDDING = 0x00001000, + OPTION_RUWACH = 0x00002000, + OPTION_CHASEWALK = 0x00004000, + OPTION_FLYING = 0x00008000, //Note that clientside Flying and Xmas are 0x8000 for clients prior to 2007. + OPTION_XMAS = 0x00010000, + OPTION_TRANSFORM = 0x00020000, + OPTION_SUMMER = 0x00040000, + OPTION_DRAGON1 = 0x00080000, + OPTION_WUG = 0x00100000, + OPTION_WUGRIDER = 0x00200000, + OPTION_MADOGEAR = 0x00400000, + OPTION_DRAGON2 = 0x00800000, + OPTION_DRAGON3 = 0x01000000, + OPTION_DRAGON4 = 0x02000000, + OPTION_DRAGON5 = 0x04000000, + OPTION_HANBOK = 0x08000000, #ifndef NEW_CARTS OPTION_CART1 = 0x00000008, @@ -1488,7 +1491,6 @@ enum { // compound constants OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5, - OPTION_MASK = ~OPTION_INVISIBLE, }; //Defines for the manner system [Skotlex] @@ -1501,18 +1503,6 @@ enum manner_flags MANNER_NOROOM = 0x10, }; -/* Status Change State Flags */ -enum scs_flag { - SCS_NOMOVECOND = 0x00000001, /* cond flag for nomove */ - SCS_NOMOVE = 0x00000002, /* unit unable to move */ - SCS_NOPICKITEMCOND = 0x00000004, /* cond flag for nopickitem */ - SCS_NOPICKITEM = 0x00000008, /* player unable to pick up items */ - SCS_NODROPITEMCOND = 0x00000010, /* cond flag for nodropitem */ - SCS_NODROPITEM = 0x00000020, /* player unable to drop items */ - SCS_NOCASTCOND = 0x00000040, /* cond flag for nocast */ - SCS_NOCAST = 0x00000080, /* unit unable to cast skills */ -}; - //Define flags for the status_calc_bl function. [Skotlex] enum scb_flag { @@ -1573,6 +1563,13 @@ struct weapon_atk { #endif }; +sc_type SkillStatusChangeTable[MAX_SKILL]; // skill -> status +int StatusIconChangeTable[SC_MAX]; // status -> "icon" (icon is a bit of a misnomer, since there exist values with no icon associated) +unsigned int StatusChangeFlagTable[SC_MAX]; // status -> flags +int StatusSkillChangeTable[SC_MAX]; // status -> skill +int StatusRelevantBLTypes[SI_MAX]; // "icon" -> enum bl_type (for clif->status_change to identify for which bl types to send packets) +bool StatusDisplayType[SC_MAX]; + //For holding basic status (which can be modified by status changes) struct status_data { @@ -1649,6 +1646,11 @@ struct regen_data { struct regen_data_sub *sregen, *ssregen; }; +struct sc_display_entry { + enum sc_type type; + int val1,val2,val3; +}; + struct status_change_entry { int timer; int val1,val2,val3,val4; @@ -1662,12 +1664,6 @@ struct status_change { unsigned char count; //TODO: See if it is possible to implement the following SC's without requiring extra parameters while the SC is inactive. unsigned char jb_flag; //Joint Beat type flag - struct { - unsigned char move; - unsigned char pickup; - unsigned char drop; - unsigned char cast; - } cant;/* status change state flags */ //int sg_id; //ID of the previous Storm gust that hit you short comet_x, comet_y; // Point where src casted Comet - required to calculate damage from this point /** diff --git a/src/map/storage.c b/src/map/storage.c index eb7760a0f..01da53907 100644 --- a/src/map/storage.c +++ b/src/map/storage.c @@ -73,7 +73,7 @@ void do_final_storage(void) // by [MC Cameri] */ static int storage_reconnect_sub(DBKey key, DBData *data, va_list ap) { - struct guild_storage *stor = db_data2ptr(data); + struct guild_storage *stor = DB->data2ptr(data); if (stor->dirty && stor->storage_status == 0) //Save closed storages. storage_guild_storagesave(0, stor->guild_id,0); @@ -100,14 +100,14 @@ int storage_storageopen(struct map_session_data *sd) if( !pc_can_give_items(sd) ) { //check is this GM level is allowed to put items to storage - clif_displaymessage(sd->fd, msg_txt(246)); + clif->message(sd->fd, msg_txt(246)); return 1; } sd->state.storage_flag = 1; storage_sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); - clif_storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); - clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); + clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items)); + clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); return 0; } @@ -150,7 +150,7 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, if( !itemdb_canstore(item_data, pc_get_group_level(sd)) ) { //Check if item is storable. [Skotlex] - clif_displaymessage (sd->fd, msg_txt(264)); + clif->message (sd->fd, msg_txt(264)); return 1; } @@ -163,7 +163,7 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.storage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; stor->items[i].amount += amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); + clif->storageitemadded(sd,&stor->items[i],i,amount); return 0; } } @@ -178,8 +178,8 @@ static int storage_additem(struct map_session_data* sd, struct item* item_data, memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->storage_amount++; stor->items[i].amount = amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); - clif_updatestorageamount(sd, stor->storage_amount, MAX_STORAGE); + clif->storageitemadded(sd,&stor->items[i],i,amount); + clif->updatestorageamount(sd, stor->storage_amount, MAX_STORAGE); return 0; } @@ -197,9 +197,9 @@ int storage_delitem(struct map_session_data* sd, int n, int amount) { memset(&sd->status.storage.items[n],0,sizeof(sd->status.storage.items[0])); sd->status.storage.storage_amount--; - if( sd->state.storage_flag == 1 ) clif_updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); + if( sd->state.storage_flag == 1 ) clif->updatestorageamount(sd, sd->status.storage.storage_amount, MAX_STORAGE); } - if( sd->state.storage_flag == 1 ) clif_storageitemremoved(sd,n,amount); + if( sd->state.storage_flag == 1 ) clif->storageitemremoved(sd,n,amount); return 0; } @@ -255,7 +255,7 @@ int storage_storageget(struct map_session_data* sd, int index, int amount) if( (flag = pc_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 ) storage_delitem(sd,index,amount); else - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); return 1; } @@ -323,7 +323,7 @@ void storage_storageclose(struct map_session_data* sd) { nullpo_retv(sd); - clif_storageclose(sd); + clif->storageclose(sd); if( save_settings&4 ) chrif_save(sd,0); //Invokes the storage saving as well. @@ -352,13 +352,13 @@ static DBData create_guildstorage(DBKey key, va_list args) struct guild_storage *gs = NULL; gs = (struct guild_storage *) aCalloc(sizeof(struct guild_storage), 1); gs->guild_id=key.i; - return db_ptr2data(gs); + return DB->ptr2data(gs); } struct guild_storage *guild2storage(int guild_id) { struct guild_storage *gs = NULL; - if(guild_search(guild_id) != NULL) + if(guild->search(guild_id) != NULL) gs = idb_ensure(guild_storage_db,guild_id,create_guildstorage); return gs; } @@ -395,7 +395,7 @@ int storage_guild_storageopen(struct map_session_data* sd) return 1; //Can't open both storages at a time. if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus] - clif_displaymessage(sd->fd, msg_txt(246)); + clif->message(sd->fd, msg_txt(246)); return 1; } @@ -412,8 +412,8 @@ int storage_guild_storageopen(struct map_session_data* sd) gstor->storage_status = 1; sd->state.storage_flag = 2; storage_sortitem(gstor->items, ARRAYLENGTH(gstor->items)); - clif_storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); - clif_updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); + clif->storagelist(sd, gstor->items, ARRAYLENGTH(gstor->items)); + clif->updatestorageamount(sd, gstor->storage_amount, MAX_GUILD_STORAGE); return 0; } @@ -444,7 +444,7 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time ) { //Check if item is storable. [Skotlex] - clif_displaymessage (sd->fd, msg_txt(264)); + clif->message (sd->fd, msg_txt(264)); return 1; } @@ -454,7 +454,7 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto if( amount > MAX_AMOUNT - stor->items[i].amount || ( data->stack.guildstorage && amount > data->stack.amount - stor->items[i].amount ) ) return 1; stor->items[i].amount+=amount; - clif_storageitemadded(sd,&stor->items[i],i,amount); + clif->storageitemadded(sd,&stor->items[i],i,amount); stor->dirty = 1; return 0; } @@ -469,8 +469,8 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto memcpy(&stor->items[i],item_data,sizeof(stor->items[0])); stor->items[i].amount=amount; stor->storage_amount++; - clif_storageitemadded(sd,&stor->items[i],i,amount); - clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); + clif->storageitemadded(sd,&stor->items[i],i,amount); + clif->updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); stor->dirty = 1; return 0; } @@ -493,9 +493,9 @@ int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* sto if(stor->items[n].amount==0){ memset(&stor->items[n],0,sizeof(stor->items[0])); stor->storage_amount--; - clif_updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); + clif->updatestorageamount(sd, stor->storage_amount, MAX_GUILD_STORAGE); } - clif_storageitemremoved(sd,n,amount); + clif->storageitemremoved(sd,n,amount); stor->dirty = 1; return 0; } @@ -572,7 +572,7 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount) if((flag = pc_additem(sd,&stor->items[index],amount,LOG_TYPE_GSTORAGE)) == 0) guild_storage_delitem(sd,stor,index,amount); else //inform fail - clif_additem(sd,0,0,flag); + clif->additem(sd,0,0,flag); // log_fromstorage(sd, index, 1); return 0; @@ -691,7 +691,7 @@ int storage_guild_storageclose(struct map_session_data* sd) nullpo_ret(sd); nullpo_ret(stor=guild2storage2(sd->status.guild_id)); - clif_storageclose(sd); + clif->storageclose(sd); if (stor->storage_status) { if (save_settings&4) @@ -716,7 +716,7 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) { //Only during a guild break flag is 1 (don't save storage) sd->state.storage_flag = 0; stor->storage_status = 0; - clif_storageclose(sd); + clif->storageclose(sd); if (save_settings&4) chrif_save(sd,0); return 0; diff --git a/src/map/trade.c b/src/map/trade.c index 0d01b54a6..1417426e9 100644 --- a/src/map/trade.c +++ b/src/map/trade.c @@ -32,24 +32,24 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta nullpo_retv(sd); if (map[sd->bl.m].flag.notrade) { - clif_displaymessage (sd->fd, msg_txt(272)); + clif->message (sd->fd, msg_txt(272)); return; //Can't trade in notrade mapflag maps. } if (target_sd == NULL || sd == target_sd) { - clif_tradestart(sd, 1); // character does not exist + clif->tradestart(sd, 1); // character does not exist return; } if (target_sd->npc_id) { //Trade fails if you are using an NPC. - clif_tradestart(sd, 2); + clif->tradestart(sd, 2); return; } if (!battle_config.invite_request_check) { if (target_sd->guild_invite > 0 || target_sd->party_invite > 0 || target_sd->adopt_invite) { - clif_tradestart(sd, 2); + clif->tradestart(sd, 2); return; } } @@ -58,34 +58,34 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta struct map_session_data *previous_sd = map_id2sd(sd->trade_partner); if( previous_sd ){ previous_sd->trade_partner = 0; - clif_tradecancelled(previous_sd); + clif->tradecancelled(previous_sd); } // Once cancelled then continue to the new one. sd->trade_partner = 0; - clif_tradecancelled(sd); + clif->tradecancelled(sd); } if (target_sd->trade_partner != 0) { - clif_tradestart(sd, 2); // person is in another trade + clif->tradestart(sd, 2); // person is in another trade return; } if (!pc_can_give_items(sd) || !pc_can_give_items(target_sd)) //check if both GMs are allowed to trade { - clif_displaymessage(sd->fd, msg_txt(246)); - clif_tradestart(sd, 2); // GM is not allowed to trade + clif->message(sd->fd, msg_txt(246)); + clif->tradestart(sd, 2); // GM is not allowed to trade return; } // Players can not request trade from far away, unless they are allowed to use @trade. - if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && + if (!pc_can_use_command(sd, "@trade") && (sd->bl.m != target_sd->bl.m || !check_distance_bl(&sd->bl, &target_sd->bl, TRADE_DISTANCE))) { - clif_tradestart(sd, 0); // too far + clif->tradestart(sd, 0); // too far return ; } target_sd->trade_partner = sd->status.account_id; sd->trade_partner = target_sd->status.account_id; - clif_traderequest(target_sd, sd->status.name); + clif->traderequest(target_sd, sd->status.name); } /*========================================== @@ -108,21 +108,21 @@ void trade_tradeack(struct map_session_data *sd, int type) return; //Already trading or no partner set. if ((tsd = map_id2sd(sd->trade_partner)) == NULL) { - clif_tradestart(sd, 1); // character does not exist + clif->tradestart(sd, 1); // character does not exist sd->trade_partner=0; return; } if (tsd->state.trading || tsd->trade_partner != sd->bl.id) { - clif_tradestart(sd, 2); + clif->tradestart(sd, 2); sd->trade_partner=0; return; //Already trading or wrong partner. } if (type == 4) { // Cancel - clif_tradestart(tsd, type); - clif_tradestart(sd, type); + clif->tradestart(tsd, type); + clif->tradestart(sd, type); sd->state.deal_locked = 0; sd->trade_partner = 0; tsd->state.deal_locked = 0; @@ -135,9 +135,9 @@ void trade_tradeack(struct map_session_data *sd, int type) // Players can not request trade from far away, unless they are allowed to use @trade. // Check here as well since the original character could had warped. - if (!pc_can_use_command(sd, "trade", COMMAND_ATCOMMAND) && + if (!pc_can_use_command(sd, "@trade") && (sd->bl.m != tsd->bl.m || !check_distance_bl(&sd->bl, &tsd->bl, TRADE_DISTANCE))) { - clif_tradestart(sd, 0); // too far + clif->tradestart(sd, 0); // too far sd->trade_partner=0; tsd->trade_partner = 0; return; @@ -147,8 +147,8 @@ void trade_tradeack(struct map_session_data *sd, int type) if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag) { //Fail - clif_tradestart(sd, 2); - clif_tradestart(tsd, 2); + clif->tradestart(sd, 2); + clif->tradestart(tsd, 2); sd->state.deal_locked = 0; sd->trade_partner = 0; tsd->state.deal_locked = 0; @@ -161,8 +161,8 @@ void trade_tradeack(struct map_session_data *sd, int type) tsd->state.trading = 1; memset(&sd->deal, 0, sizeof(sd->deal)); memset(&tsd->deal, 0, sizeof(tsd->deal)); - clif_tradestart(tsd, type); - clif_tradestart(sd, type); + clif->tradestart(tsd, type); + clif->tradestart(sd, type); } /*========================================== @@ -178,8 +178,7 @@ int impossible_trade_check(struct map_session_data *sd) nullpo_retr(1, sd); - if(sd->deal.zeny > sd->status.zeny) - { + if(sd->deal.zeny > sd->status.zeny) { pc_setglobalreg(sd,"ZENY_HACKER",1); return -1; } @@ -338,7 +337,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) if( amount == 0 ) { //Why do this.. ~.~ just send an ack, the item won't display on the trade window. - clif_tradeitemok(sd, index, 0); + clif->tradeitemok(sd, index, 0); return; } @@ -356,15 +355,15 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) if( !itemdb_cantrade(item, src_lv, dst_lv) && //Can't trade (pc_get_partner(sd) != target_sd || !itemdb_canpartnertrade(item, src_lv, dst_lv)) ) //Can't partner-trade { - clif_displaymessage (sd->fd, msg_txt(260)); - clif_tradeitemok(sd, index+2, 1); + clif->message (sd->fd, msg_txt(260)); + clif->tradeitemok(sd, index+2, 1); return; } if( item->expire_time ) { // Rental System - clif_displaymessage (sd->fd, msg_txt(260)); - clif_tradeitemok(sd, index+2, 1); + clif->message (sd->fd, msg_txt(260)); + clif->tradeitemok(sd, index+2, 1); return; } @@ -372,14 +371,14 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 ); if( trade_i == 10 ) //No space left { - clif_tradeitemok(sd, index+2, 1); + clif->tradeitemok(sd, index+2, 1); return; } trade_weight = sd->inventory_data[index]->weight * amount; if( target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight ) { //fail to add item -- the player was over weighted. - clif_tradeitemok(sd, index+2, 1); + clif->tradeitemok(sd, index+2, 1); return; } @@ -399,8 +398,8 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount) } sd->deal.weight += trade_weight; - clif_tradeitemok(sd, index+2, 0); // Return the index as it was received - clif_tradeadditem(sd, target_sd, index+2, amount); + clif->tradeitemok(sd, index+2, 0); // Return the index as it was received + clif->tradeadditem(sd, target_sd, index+2, amount); } /*========================================== @@ -427,7 +426,7 @@ void trade_tradeaddzeny(struct map_session_data* sd, int amount) } sd->deal.zeny = amount; - clif_tradeadditem(sd, target_sd, 0, amount); + clif->tradeadditem(sd, target_sd, 0, amount); } /*========================================== @@ -445,9 +444,9 @@ void trade_tradeok(struct map_session_data *sd) return; } sd->state.deal_locked = 1; - clif_tradeitemok(sd, 0, 0); - clif_tradedeal_lock(sd, 0); - clif_tradedeal_lock(target_sd, 1); + clif->tradeitemok(sd, 0, 0); + clif->tradedeal_lock(sd, 0); + clif->tradedeal_lock(target_sd, 1); } /*========================================== @@ -464,29 +463,29 @@ void trade_tradecancel(struct map_session_data *sd) { // Not trade acepted if( target_sd ) { target_sd->trade_partner = 0; - clif_tradecancelled(target_sd); + clif->tradecancelled(target_sd); } sd->trade_partner = 0; - clif_tradecancelled(sd); + clif->tradecancelled(sd); return; } for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) if (!sd->deal.item[trade_i].amount) continue; - clif_additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0); + clif->additem(sd, sd->deal.item[trade_i].index, sd->deal.item[trade_i].amount, 0); sd->deal.item[trade_i].index = 0; sd->deal.item[trade_i].amount = 0; } if (sd->deal.zeny) { - clif_updatestatus(sd, SP_ZENY); + clif->updatestatus(sd, SP_ZENY); sd->deal.zeny = 0; } sd->state.deal_locked = 0; sd->state.trading = 0; sd->trade_partner = 0; - clif_tradecancelled(sd); + clif->tradecancelled(sd); if (!target_sd) return; @@ -494,19 +493,19 @@ void trade_tradecancel(struct map_session_data *sd) for(trade_i = 0; trade_i < 10; trade_i++) { // give items back (only virtual) if (!target_sd->deal.item[trade_i].amount) continue; - clif_additem(target_sd, target_sd->deal.item[trade_i].index, target_sd->deal.item[trade_i].amount, 0); + clif->additem(target_sd, target_sd->deal.item[trade_i].index, target_sd->deal.item[trade_i].amount, 0); target_sd->deal.item[trade_i].index = 0; target_sd->deal.item[trade_i].amount = 0; } if (target_sd->deal.zeny) { - clif_updatestatus(target_sd, SP_ZENY); + clif->updatestatus(target_sd, SP_ZENY); target_sd->deal.zeny = 0; } target_sd->state.deal_locked = 0; target_sd->trade_partner = 0; target_sd->state.trading = 0; - clif_tradecancelled(target_sd); + clif->tradecancelled(target_sd); } /*========================================== @@ -560,7 +559,7 @@ void trade_tradecommit(struct map_session_data *sd) if (flag == 0) pc_delitem(sd, n, sd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); else - clif_additem(sd, n, sd->deal.item[trade_i].amount, 0); + clif->additem(sd, n, sd->deal.item[trade_i].amount, 0); sd->deal.item[trade_i].index = 0; sd->deal.item[trade_i].amount = 0; } @@ -572,7 +571,7 @@ void trade_tradecommit(struct map_session_data *sd) if (flag == 0) pc_delitem(tsd, n, tsd->deal.item[trade_i].amount, 1, 6, LOG_TYPE_TRADE); else - clif_additem(tsd, n, tsd->deal.item[trade_i].amount, 0); + clif->additem(tsd, n, tsd->deal.item[trade_i].amount, 0); tsd->deal.item[trade_i].index = 0; tsd->deal.item[trade_i].amount = 0; } @@ -598,8 +597,8 @@ void trade_tradecommit(struct map_session_data *sd) tsd->trade_partner = 0; tsd->state.trading = 0; - clif_tradecompleted(sd, 0); - clif_tradecompleted(tsd, 0); + clif->tradecompleted(sd, 0); + clif->tradecompleted(tsd, 0); // save both player to avoid crash: they always have no advantage/disadvantage between the 2 players if (save_settings&1) diff --git a/src/map/unit.c b/src/map/unit.c index 0104e9a42..cbc695c4a 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1,5 +1,6 @@ -// 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 #include "../common/showmsg.h" #include "../common/timer.h" @@ -96,9 +97,9 @@ int unit_walktoxy_sub(struct block_list *bl) if (bl->type == BL_PC) { ((TBL_PC *)bl)->head_dir = 0; - clif_walkok((TBL_PC*)bl); + clif->walkok((TBL_PC*)bl); } - clif_move(ud); + clif->move(ud); if(ud->walkpath.path_pos>=ud->walkpath.path_len) i = -1; @@ -157,7 +158,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data return unit_walktoxy_sub(bl); //Refresh view for all those we lose sight - map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); + map_foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); x += dx; y += dy; @@ -169,7 +170,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data return 0; //map_moveblock has altered the object beyond what we expected (moved/warped it) ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets - map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); + map_foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); ud->walktimer = INVALID_TIMER; if(sd) { @@ -214,11 +215,11 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data { if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)) { //Skill used, abort walking - clif_fixpos(bl); //Fix position as walk has been cancelled. + clif->fixpos(bl); //Fix position as walk has been cancelled. return 0; } //Resend walk packet for proper Self Destruction display. - clif_move(ud); + clif->move(ud); } } else if( mrd && mrd->master ) @@ -259,7 +260,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data if(i > 0) { ud->walktimer = add_timer(tick+i,unit_walktoxy_timer,id,i); if( md && DIFF_TICK(tick,md->dmgtick) < 3000 )//not required not damaged recently - clif_move(ud); + clif->move(ud); } else if(ud->state.running) { //Keep trying to run. if ( !(unit_run(bl) || unit_wugdash(bl,sd)) ) @@ -282,7 +283,7 @@ static int unit_walktoxy_timer(int tid, unsigned int tick, int id, intptr_t data { //Aegis uses one before every attack, we should //only need this one for syncing purposes. [Skotlex] ud->target_to = 0; - clif_fixpos(bl); + clif->fixpos(bl); unit_attack(bl, tbl->id, ud->state.attack_continue); } } else { //Update chase-path @@ -315,20 +316,22 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag) { struct unit_data* ud = NULL; struct status_change* sc = NULL; -#ifdef OFFICIAL_WALKPATH struct walkpath_data wpd; -#endif + nullpo_ret(bl); ud = unit_bl2ud(bl); if( ud == NULL) return 0; + path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS); // Count walk path cells #ifdef OFFICIAL_WALKPATH - if( path_search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS) // Check if there is an obstacle between + if( !path_search_long(NULL, bl->m, bl->x, bl->y, x, y, CELL_CHKNOPASS) // Check if there is an obstacle between && wpd.path_len > 14 ) // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett] return 0; #endif + if( (battle_config.max_walk_path < wpd.path_len) && (bl->type != BL_NPC) ) + return 0; if (flag&4 && DIFF_TICK(ud->canmove_tick, gettick()) > 0 && DIFF_TICK(ud->canmove_tick, gettick()) < 2000) @@ -403,7 +406,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int ud = unit_bl2ud(bl); if( ud == NULL) return 0; - + if (!(status_get_mode(bl)&MD_CANMOVE)) return 0; @@ -413,13 +416,13 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int ud->target_to = 0; return 0; } - + ud->state.walk_easy = flag&1; ud->target_to = tbl->id; ud->chaserange = range; //Note that if flag&2, this SHOULD be attack-range ud->state.attack_continue = flag&2?1:0; //Chase to attack. unit_set_target(ud, 0); - + sc = status_get_sc(bl); if (sc && sc->data[SC_CONFUSION]) //Randomize the target position map_random_dir(bl, &ud->to_x, &ud->to_y); @@ -429,7 +432,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int set_mobstate(bl, flag&2); return 1; } - + if(DIFF_TICK(ud->canmove_tick, gettick()) > 0) { //Can't move, wait a bit before invoking the movement. add_timer(ud->canmove_tick+1, unit_walktobl_sub, bl->id, ud->target); @@ -488,15 +491,15 @@ int unit_run(struct block_list *bl) if( (to_x == bl->x && to_y == bl->y ) || (to_x == (bl->x+1) || to_y == (bl->y+1)) || (to_x == (bl->x-1) || to_y == (bl->y-1))) { //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex] - clif_status_change(bl, SI_BUMP, 1, 0, 0, 0, 0); + clif->sc_load(bl,bl->id,AREA,SI_BUMP,0,0,0); //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] unit_bl2ud(bl)->state.running = 0; status_change_end(bl, SC_RUN, INVALID_TIMER); - skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0); - clif_fixpos(bl); //Why is a clif_slide (skill_blown) AND a fixpos needed? Ask Aegis. - clif_status_change(bl, SI_BUMP, 0, 0, 0, 0, 0); + skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit_getdir(bl),0); + clif->fixpos(bl); //Why is a clif->slide (skill->blown) AND a fixpos needed? Ask Aegis. + clif->sc_end(bl,bl->id,AREA,SI_BUMP); return 0; } if (unit_walktoxy(bl, to_x, to_y, 1)) @@ -506,17 +509,17 @@ int unit_run(struct block_list *bl) to_x -= dir_x; to_y -= dir_y; } while (--i > 0 && !unit_walktoxy(bl, to_x, to_y, 1)); - if (i==0) { + if ( i == 0 ) { // copy-paste from above - clif_status_change(bl, SI_BUMP, 1, 0, 0, 0, 0); + clif->sc_load(bl,bl->id,AREA,SI_BUMP,0,0,0); //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] unit_bl2ud(bl)->state.running = 0; status_change_end(bl, SC_RUN, INVALID_TIMER); - skill_blown(bl,bl,skill_get_blewcount(TK_RUN,lv),unit_getdir(bl),0); - clif_fixpos(bl); - clif_status_change(bl, SI_BUMP, 0, 0, 0, 0, 0); + skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit_getdir(bl),0); + clif->fixpos(bl); + clif->sc_end(bl,bl->id,AREA,SI_BUMP); return 0; } return 1; @@ -563,8 +566,8 @@ int unit_wugdash(struct block_list *bl, struct map_session_data *sd) { status_change_end(bl,SC_WUGDASH,INVALID_TIMER); if( sd ){ - clif_fixpos(bl); - skill_castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); + clif->fixpos(bl); + skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); } return 0; } @@ -580,8 +583,8 @@ int unit_wugdash(struct block_list *bl, struct map_session_data *sd) { status_change_end(bl,SC_WUGDASH,INVALID_TIMER); if( sd ){ - clif_fixpos(bl); - skill_castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); + clif->fixpos(bl); + skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, gettick(), SD_LEVEL); } return 0; } @@ -626,12 +629,12 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool dx = dst_x - bl->x; dy = dst_y - bl->y; - map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); + map_foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl); map_moveblock(bl, dst_x, dst_y, gettick()); ud->walktimer = -2; // arbitrary non-INVALID_TIMER value to make the clif code send walking packets - map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); + map_foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, sd?BL_ALL:BL_PC, bl); ud->walktimer = INVALID_TIMER; if(sd) { @@ -655,7 +658,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool if( flag ) { unit_movepos(bl,sd->bl.x,sd->bl.y, 0, 0); - clif_slide(bl,bl->x,bl->y); + clif->slide(bl,bl->x,bl->y); } } } @@ -671,7 +674,7 @@ int unit_setdir(struct block_list *bl,unsigned char dir) ud->dir = dir; if (bl->type == BL_PC) ((TBL_PC *)bl)->head_dir = 0; - clif_changed_dir(bl, AREA); + clif->changed_dir(bl, AREA); return 0; } @@ -716,18 +719,18 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag) dy = ny-bl->y; if(dx || dy) { - map_foreachinmovearea(clif_outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); + map_foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); if(su) { - skill_unit_move_unit_group(su->group, bl->m, dx, dy); + skill->unit_move_unit_group(su->group, bl->m, dx, dy); } else { map_moveblock(bl, nx, ny, gettick()); } - map_foreachinmovearea(clif_insight, bl, AREA_SIZE, -dx, -dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); + map_foreachinmovearea(clif->insight, bl, AREA_SIZE, -dx, -dy, bl->type == BL_PC ? BL_ALL : BL_PC, bl); if(!(flag&1)) { - clif_blown(bl); + clif->blown(bl); } if(sd) { @@ -806,15 +809,15 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) if (bl->m != m && battle_config.clear_unit_onwarp && battle_config.clear_unit_onwarp&bl->type) - skill_clear_unitgroup(bl); + skill->clear_unitgroup(bl); bl->x=ud->to_x=x; bl->y=ud->to_y=y; bl->m=m; map_addblock(bl); - clif_spawn(bl); - skill_unit_move(bl,gettick(),1); + clif->spawn(bl); + skill->unit_move(bl,gettick(),1); return 0; } @@ -853,7 +856,7 @@ int unit_stop_walking(struct block_list *bl,int type) } if(type&0x01) - clif_fixpos(bl); + clif->fixpos(bl); ud->walkpath.path_len = 0; ud->walkpath.path_pos = 0; @@ -874,8 +877,8 @@ int unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id, uin { return unit_skilluse_id2( src, target_id, skill_id, skill_lv, - skill_castfix(src, skill_id, skill_lv), - skill_get_castcancel(skill_id) + skill->cast_fix(src, skill_id, skill_lv), + skill->get_castcancel(skill_id) ); } @@ -890,8 +893,7 @@ int unit_is_walking(struct block_list *bl) /*========================================== * Determines if the bl can move based on status changes. [Skotlex] *------------------------------------------*/ -int unit_can_move(struct block_list *bl) -{ +int unit_can_move(struct block_list *bl) { struct map_session_data *sd; struct unit_data *ud; struct status_change *sc; @@ -904,7 +906,7 @@ int unit_can_move(struct block_list *bl) if (!ud) return 0; - if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill_get_inf2(ud->skill_id)&INF2_GUILD_SKILL)) + if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc_checkskill(sd, SA_FREECAST) || skill->get_inf2(ud->skill_id)&INF2_GUILD_SKILL)) return 0; // prevent moving while casting if (DIFF_TICK(ud->canmove_tick, gettick()) > 0) @@ -919,20 +921,49 @@ int unit_can_move(struct block_list *bl) return 0; //Can't move if (sc) { - if( sc->cant.move /* status placed here are ones that cannot be cached by sc->cant.move for they depend on other conditions other than their availability */ - || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) - || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) - || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && ( - !sc->data[SC_LONGING] || - (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT || - (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE - ) ) - || (sc->data[SC_CLOAKING] && //Need wall at level 1-2 - sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) - ) + if( sc->count && ( + sc->data[SC_ANKLE] + || sc->data[SC_AUTOCOUNTER] + || sc->data[SC_TRICKDEAD] + || sc->data[SC_BLADESTOP] + || sc->data[SC_BLADESTOP_WAIT] + || (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_SELF) // cannot move while gospel is in effect + || (sc->data[SC_BASILICA] && sc->data[SC_BASILICA]->val4 == bl->id) // Basilica caster cannot move + || sc->data[SC_STOP] + || sc->data[SC_CLOSECONFINE] + || sc->data[SC_CLOSECONFINE2] + || sc->data[SC_MADNESSCANCEL] + || (sc->data[SC_GRAVITATION] && sc->data[SC_GRAVITATION]->val3 == BCT_SELF) + || sc->data[SC_WHITEIMPRISON] + || sc->data[SC_ELECTRICSHOCKER] + || sc->data[SC_BITE] + || sc->data[SC_THORNSTRAP] + || sc->data[SC_MAGNETICFIELD] + || sc->data[SC__MANHOLE] + || sc->data[SC_CURSEDCIRCLE_ATKER] + || sc->data[SC_CURSEDCIRCLE_TARGET] + || (sc->data[SC_CRYSTALIZE] && bl->type != BL_MOB) + || sc->data[SC_NETHERWORLD] + || (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 && !(sc->data[SC_CAMOUFLAGE]->val3&1)) + || sc->data[SC_MEIKYOUSISUI] + || sc->data[SC_KAGEHUMI] + || sc->data[SC_KYOUGAKU] + || sc->data[SC_PARALYSIS] + || sc->data[SC_VACUUM_EXTREME] + || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) + || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) + || (sc->data[SC_DANCING] && sc->data[SC_DANCING]->val4 && ( + !sc->data[SC_LONGING] || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_MOONLIT || + (sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE + ) ) + || (sc->data[SC_CLOAKING] && //Need wall at level 1-2 + sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) + ) ) return 0; + - if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && (sc->opt1 != OPT1_CRYSTALIZE && bl->type != BL_MOB)) + if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && !(sc->opt1 == OPT1_CRYSTALIZE && bl->type == BL_MOB)) return 0; if ((sc->option & OPTION_HIDE) && (!sd || pc_checkskill(sd, RG_TUNNELDRIVE) <= 0)) @@ -953,13 +984,13 @@ int unit_resume_running(int tid, unsigned int tick, int id, intptr_t data) TBL_PC * sd = map_id2sd(id); if(sd && pc_isridingwug(sd)) - clif_skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv, + clif->skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv, sc_start4(ud->bl,status_skill2sc(RA_WUGDASH),100,ud->skill_lv,unit_getdir(ud->bl),0,0,1)); else - clif_skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skill_lv, + clif->skill_nodamage(ud->bl,ud->bl,TK_RUN,ud->skill_lv, sc_start4(ud->bl,status_skill2sc(TK_RUN),100,ud->skill_lv,unit_getdir(ud->bl),0,0,0)); - if (sd) clif_walkok(sd); + if (sd) clif->walkok(sd); return 0; @@ -1037,19 +1068,18 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui //temp: used to signal combo-skills right now. if (sc && sc->data[SC_COMBO] && (sc->data[SC_COMBO]->val1 == skill_id || - (sd?skill_check_condition_castbegin(sd,skill_id,skill_lv):0) )) { + (sd?skill->check_condition_castbegin(sd,skill_id,skill_lv):0) )) { if (sc->data[SC_COMBO]->val2) target_id = sc->data[SC_COMBO]->val2; else target_id = ud->target; - if( skill_get_inf(skill_id)&INF_SELF_SKILL && skill_get_nk(skill_id)&NK_NO_DAMAGE )// exploit fix + if( skill->get_inf(skill_id)&INF_SELF_SKILL && skill->get_nk(skill_id)&NK_NO_DAMAGE )// exploit fix target_id = src->id; temp = 1; - } else - if ( target_id == src->id && - skill_get_inf(skill_id)&INF_SELF_SKILL && - skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF ) + } else if ( target_id == src->id && + skill->get_inf(skill_id)&INF_SELF_SKILL && + skill->get_inf2(skill_id)&INF2_NO_TARGET_SELF ) { target_id = ud->target; //Auto-select target. [Skotlex] temp = 1; @@ -1057,41 +1087,40 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if (sd) { //Target_id checking. - if(skillnotok(skill_id, sd)) // [MouseJstr] + if(skill->not_ok(skill_id, sd)) // [MouseJstr] return 0; - switch(skill_id) - { //Check for skills that auto-select target - case MO_CHAINCOMBO: - if (sc && sc->data[SC_BLADESTOP]){ - if ((target=map_id2bl(sc->data[SC_BLADESTOP]->val4)) == NULL) + switch(skill_id) { //Check for skills that auto-select target + case MO_CHAINCOMBO: + if (sc && sc->data[SC_BLADESTOP]){ + if ((target=map_id2bl(sc->data[SC_BLADESTOP]->val4)) == NULL) + return 0; + } + break; + case WE_MALE: + case WE_FEMALE: + if (!sd->status.partner_id) return 0; - } - break; - case WE_MALE: - case WE_FEMALE: - if (!sd->status.partner_id) - return 0; - target = (struct block_list*)map_charid2sd(sd->status.partner_id); - if (!target) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; + target = (struct block_list*)map_charid2sd(sd->status.partner_id); + if (!target) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + break; } if (target) target_id = target->id; } + if (src->type==BL_HOM) - switch(skill_id) - { //Homun-auto-target skills. - case HLIF_HEAL: - case HLIF_AVOID: - case HAMI_DEFENCE: - case HAMI_CASTLE: - target = battle_get_master(src); - if (!target) return 0; - target_id = target->id; + switch(skill_id) { //Homun-auto-target skills. + case HLIF_HEAL: + case HLIF_AVOID: + case HAMI_DEFENCE: + case HAMI_CASTLE: + target = battle->get_master(src); + if (!target) return 0; + target_id = target->id; } if( !target ) // choose default target @@ -1107,7 +1136,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if(ud->skilltimer != INVALID_TIMER && skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST) return 0; - if(skill_get_inf2(skill_id)&INF2_NO_TARGET_SELF && src->id == target_id) + if(skill->get_inf2(skill_id)&INF2_NO_TARGET_SELF && src->id == target_id) return 0; if(!status_check_skilluse(src, target, skill_id, 0)) @@ -1116,56 +1145,51 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui tstatus = status_get_status_data(target); // Record the status of the previous skill) if(sd) { + + if( (skill->get_inf2(skill_id)&INF2_ENSEMBLE_SKILL) && skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1 ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + switch(skill_id){ - case SA_CASTCANCEL: - if(ud->skill_id != skill_id){ - sd->skill_id_old = ud->skill_id; - sd->skill_lv_old = ud->skill_lv; - } - break; - case BD_ENCORE: - //Prevent using the dance skill if you no longer have the skill in your tree. - if(!sd->skill_id_dance || pc_checkskill(sd,sd->skill_id_dance)<=0){ - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - sd->skill_id_old = skill_id; - break; - case BD_LULLABY: - case BD_RICHMANKIM: - case BD_ETERNALCHAOS: - case BD_DRUMBATTLEFIELD: - case BD_RINGNIBELUNGEN: - case BD_ROKISWEIL: - case BD_INTOABYSS: - case BD_SIEGFRIED: - case CG_MOONLIT: - if (skill_check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1) - { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); - return 0; - } - break; - case WL_WHITEIMPRISON: - if( battle_check_target(src,target,BCT_SELF|BCT_ENEMY) < 0 ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); - return 0; - } - break; - case MG_FIREBOLT: - case MG_LIGHTNINGBOLT: - case MG_COLDBOLT: - sd->skill_id_old = skill_id; - sd->skill_lv_old = skill_lv; - break; + case SA_CASTCANCEL: + if(ud->skill_id != skill_id){ + sd->skill_id_old = ud->skill_id; + sd->skill_lv_old = ud->skill_lv; + } + break; + case BD_ENCORE: + //Prevent using the dance skill if you no longer have the skill in your tree. + if(!sd->skill_id_dance || pc_checkskill(sd,sd->skill_id_dance)<=0){ + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + return 0; + } + sd->skill_id_old = skill_id; + break; + case WL_WHITEIMPRISON: + if( battle->check_target(src,target,BCT_SELF|BCT_ENEMY) < 0 ) { + clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); + return 0; + } + break; + case MG_FIREBOLT: + case MG_LIGHTNINGBOLT: + case MG_COLDBOLT: + sd->skill_id_old = skill_id; + sd->skill_lv_old = skill_lv; + break; } - if (!skill_check_condition_castbegin(sd, skill_id, skill_lv)) + /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ +#if 0 + if ( sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) +#else + if ( !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) +#endif return 0; } if( src->type == BL_MOB ) - switch( skill_id ) - { + switch( skill_id ) { case NPC_SUMMONSLAVE: case NPC_SUMMONMONSTER: case AL_TELEPORT: @@ -1176,18 +1200,18 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if (src->type == BL_NPC) // NPC-objects can override cast distance range = AREA_SIZE; // Maximum visible distance before NPC goes out of sight else - range = skill_get_range2(src, skill_id, skill_lv); // Skill cast distance from database + range = skill->get_range2(src, skill_id, skill_lv); // Skill cast distance from database //Check range when not using skill on yourself or is a combo-skill during attack //(these are supposed to always have the same range as your attack) if( src->id != target_id && (!temp || ud->attacktimer == INVALID_TIMER) ) { - if( skill_get_state(ud->skill_id) == ST_MOVE_ENABLE ) { + if( skill->get_state(ud->skill_id) == ST_MOVE_ENABLE ) { if( !unit_can_reach_bl(src, target, range + 1, 1, NULL, NULL) ) return 0; // Walk-path check failed. } else if( src->type == BL_MER && skill_id == MA_REMOVETRAP ) { - if( !battle_check_range(battle_get_master(src), target, range + 1) ) + if( !battle->check_range(battle->get_master(src), target, range + 1) ) return 0; // Aegis calc remove trap based on Master position, ignoring mercenary O.O - } else if( !battle_check_range(src, target, range + (skill_id == RG_CLOSECONFINE?0:2)) ) { + } else if( !battle->check_range(src, target, range + (skill_id == RG_CLOSECONFINE?0:2)) ) { return 0; // Arrow-path check failed. } } @@ -1204,7 +1228,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui switch(skill_id){ case ALL_RESURRECTION: - if(battle_check_undead(tstatus->race,tstatus->def_ele)) { + if(battle->check_undead(tstatus->race,tstatus->def_ele)) { temp = 1; } else if (!status_isdead(target)) return 0; //Can't cast on non-dead characters. @@ -1268,7 +1292,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui case EL_WATER_SCREW: case EL_TIDAL_WEAPON: if( src->type == BL_ELEM ){ - sd = BL_CAST(BL_PC, battle_get_master(src)); + sd = BL_CAST(BL_PC, battle->get_master(src)); if( sd && sd->skill_id_old == SO_EL_ACTION ){ casttime = -1; sd->skill_id_old = 0; @@ -1279,10 +1303,10 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui // moved here to prevent Suffragium from ending if skill fails #ifndef RENEWAL_CAST - if (!(skill_get_castnodex(skill_id, skill_lv)&2)) - casttime = skill_castfix_sc(src, casttime); + if (!(skill->get_castnodex(skill_id, skill_lv)&2)) + casttime = skill->cast_fix_sc(src, casttime); #else - casttime = skill_vfcastfix(src, casttime, skill_id, skill_lv); + casttime = skill->vf_cast_fix(src, casttime, skill_id, skill_lv); #endif if (src->type == BL_NPC) { // NPC-objects do not have cast time @@ -1292,7 +1316,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if(!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026 unit_stop_walking(src,1);// eventhough this is not how official works but this will do the trick. bugreport:6829 // in official this is triggered even if no cast time. - clif_skillcasting(src, src->id, target_id, 0,0, skill_id, skill_get_ele(skill_id, skill_lv), casttime); + clif->skillcasting(src, src->id, target_id, 0,0, skill_id, skill->get_ele(skill_id, skill_lv), casttime); if( casttime > 0 || temp ) { if (sd && target->type == BL_MOB) @@ -1300,7 +1324,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui TBL_MOB *md = (TBL_MOB*)target; mobskill_event(md, src, tick, -1); //Cast targetted skill event. if (tstatus->mode&(MD_CASTSENSOR_IDLE|MD_CASTSENSOR_CHASE) && - battle_check_target(target, src, BCT_ENEMY) > 0) + battle->check_target(target, src, BCT_ENEMY) > 0) { switch (md->state.skillstate) { case MSS_RUSH: @@ -1327,7 +1351,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if( casttime <= 0 ) ud->state.skillcastcancel = 0; - if( !sd || sd->skillitem != skill_id || skill_get_cast(skill_id,skill_lv) ) + if( !sd || sd->skillitem != skill_id || skill->get_cast(skill_id,skill_lv) ) ud->canact_tick = tick + casttime + 100; if( sd ) { @@ -1358,14 +1382,12 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } - if( casttime > 0 ) - { - ud->skilltimer = add_timer( tick+casttime, skill_castend_id, src->id, 0 ); + if( casttime > 0 ) { + ud->skilltimer = add_timer( tick+casttime, skill->castend_id, src->id, 0 ); if( sd && (pc_checkskill(sd,SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK) ) status_calc_bl(&sd->bl, SCB_SPEED); - } - else - skill_castend_id(ud->skilltimer,tick,src->id,0); + } else + skill->castend_id(ud->skilltimer,tick,src->id,0); return 1; } @@ -1374,8 +1396,8 @@ int unit_skilluse_pos(struct block_list *src, short skill_x, short skill_y, uint { return unit_skilluse_pos2( src, skill_x, skill_y, skill_id, skill_lv, - skill_castfix(src, skill_id, skill_lv), - skill_get_castcancel(skill_id) + skill->cast_fix(src, skill_id, skill_lv), + skill->get_castcancel(skill_id) ); } @@ -1406,14 +1428,14 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if( sd ) { - if( skillnotok(skill_id, sd) || !skill_check_condition_castbegin(sd, skill_id, skill_lv) ) + if( skill->not_ok(skill_id, sd) || !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) return 0; /** * "WHY IS IT HEREE": pneuma cannot be cancelled past this point, the client displays the animation even, * if we cancel it from nodamage_id, so it has to be here for it to not display the animation. **/ if( skill_id == AL_PNEUMA && map_getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) { - clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } } @@ -1423,7 +1445,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if( map_getcell(src->m, skill_x, skill_y, CELL_CHKWALL) ) {// can't cast ground targeted spells on wall cells - if (sd) clif_skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); return 0; } @@ -1436,24 +1458,22 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui if (src->type == BL_NPC) // NPC-objects can override cast distance range = AREA_SIZE; // Maximum visible distance before NPC goes out of sight else - range = skill_get_range2(src, skill_id, skill_lv); // Skill cast distance from database + range = skill->get_range2(src, skill_id, skill_lv); // Skill cast distance from database - if( skill_get_state(ud->skill_id) == ST_MOVE_ENABLE ) - { + if( skill->get_state(ud->skill_id) == ST_MOVE_ENABLE ) { if( !unit_can_reach_bl(src, &bl, range + 1, 1, NULL, NULL) ) return 0; //Walk-path check failed. - } - else if( !battle_check_range(src, &bl, range + 1) ) + } else if( !battle->check_range(src, &bl, range + 1) ) return 0; //Arrow-path check failed. unit_stop_attack(src); // moved here to prevent Suffragium from ending if skill fails #ifndef RENEWAL_CAST - if (!(skill_get_castnodex(skill_id, skill_lv)&2)) - casttime = skill_castfix_sc(src, casttime); + if (!(skill->get_castnodex(skill_id, skill_lv)&2)) + casttime = skill->cast_fix_sc(src, casttime); #else - casttime = skill_vfcastfix(src, casttime, skill_id, skill_lv ); + casttime = skill->vf_cast_fix(src, casttime, skill_id, skill_lv ); #endif if (src->type == BL_NPC) { // NPC-objects do not have cast time @@ -1461,7 +1481,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui } ud->state.skillcastcancel = castcancel&&casttime>0?1:0; - if( !sd || sd->skillitem != skill_id || skill_get_cast(skill_id,skill_lv) ) + if( !sd || sd->skillitem != skill_id || skill->get_cast(skill_id,skill_lv) ) ud->canact_tick = tick + casttime + 100; // if( sd ) // { @@ -1492,17 +1512,14 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui unit_stop_walking(src,1); // in official this is triggered even if no cast time. - clif_skillcasting(src, src->id, 0, skill_x, skill_y, skill_id, skill_get_ele(skill_id, skill_lv), casttime); - if( casttime > 0 ) - { - ud->skilltimer = add_timer( tick+casttime, skill_castend_pos, src->id, 0 ); + clif->skillcasting(src, src->id, 0, skill_x, skill_y, skill_id, skill->get_ele(skill_id, skill_lv), casttime); + if( casttime > 0 ) { + ud->skilltimer = add_timer( tick+casttime, skill->castend_pos, src->id, 0 ); if( (sd && pc_checkskill(sd,SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK) status_calc_bl(&sd->bl, SCB_SPEED); - } - else - { + } else { ud->skilltimer = INVALID_TIMER; - skill_castend_pos(ud->skilltimer,tick,src->id,0); + skill->castend_pos(ud->skilltimer,tick,src->id,0); } return 1; } @@ -1586,7 +1603,7 @@ int unit_attack(struct block_list *src,int target_id,int continuous) return 0; } } - if( battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) { + if( battle->check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) ) { unit_unattackable(src); return 1; } @@ -1771,7 +1788,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t return 0; if( status_isdead(src) || status_isdead(target) || - battle_check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) + battle->check_target(src,target,BCT_ENEMY) <= 0 || !status_check_skilluse(src, target, 0, 0) #ifdef OFFICIAL_WALKPATH || !path_search_long(NULL, src->m, src->x, src->y, target->x, target->y, CELL_CHKWALL) #endif @@ -1792,7 +1809,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t { // attacking when under cast delay has restrictions: if( tid == INVALID_TIMER ) { //requested attack. - if(sd) clif_skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0); + if(sd) clif->skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0); return 0; } //Otherwise, we are in a combo-attack, delay this until your canact time is over. [Skotlex] @@ -1812,12 +1829,12 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t range++; //Extra range when chasing if( !check_distance_bl(src,target,range) ) { //Chase if required. if(sd) - clif_movetoattack(sd,target); + clif->movetoattack(sd,target); else if(ud->state.attack_continue) unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2); return 1; } - if( !battle_check_range(src,target,range) ) { + if( !battle->check_range(src,target,range) ) { //Within range, but no direct line of attack if( ud->state.attack_continue ) { if(ud->chaserange > 2) ud->chaserange-=2; @@ -1827,7 +1844,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t } //Sync packet only for players. //Non-players use the sync packet on the walk timer. [Skotlex] - if (tid == INVALID_TIMER && sd) clif_fixpos(src); + if (tid == INVALID_TIMER && sd) clif->fixpos(src); if( DIFF_TICK(ud->attackabletime,tick) <= 0 ) { @@ -1849,7 +1866,7 @@ static int unit_attack_timer_sub(struct block_list* src, int tid, unsigned int t return 1; map_freeblock_lock(); - ud->attacktarget_lv = battle_weapon_attack(src,target,tick,0); + ud->attacktarget_lv = battle->weapon_attack(src,target,tick,0); if(sd && sd->status.pet_id > 0 && sd->pd && battle_config.pet_attack_support) pet_target_check(sd,target,0); @@ -1892,7 +1909,7 @@ int unit_skillcastcancel(struct block_list *bl,int type) struct map_session_data *sd = NULL; struct unit_data *ud = unit_bl2ud( bl); unsigned int tick=gettick(); - int ret=0, skill; + int ret=0, skill_id; nullpo_ret(bl); if (!ud || ud->skilltimer == INVALID_TIMER) @@ -1913,15 +1930,15 @@ int unit_skillcastcancel(struct block_list *bl,int type) ud->canact_tick = tick; if(type&1 && sd) - skill = sd->skill_id_old; + skill_id = sd->skill_id_old; else - skill = ud->skill_id; + skill_id = ud->skill_id; - if (skill_get_inf(skill) & INF_GROUND_SKILL) - ret=delete_timer( ud->skilltimer, skill_castend_pos ); + if (skill->get_inf(skill_id) & INF_GROUND_SKILL) + ret = delete_timer( ud->skilltimer, skill->castend_pos ); else - ret=delete_timer( ud->skilltimer, skill_castend_id ); - if(ret<0) + ret = delete_timer( ud->skilltimer, skill->castend_id ); + if( ret < 0 ) ShowError("delete timer error : skill_id : %d\n",ret); ud->skilltimer = INVALID_TIMER; @@ -1929,19 +1946,17 @@ int unit_skillcastcancel(struct block_list *bl,int type) if( sd && pc_checkskill(sd,SA_FREECAST) > 0 ) status_calc_bl(&sd->bl, SCB_SPEED); - if( sd ) - { - switch( skill ) - { - case CG_ARROWVULCAN: - sd->canequip_tick = tick; - break; + if( sd ) { + switch( skill_id ) { + case CG_ARROWVULCAN: + sd->canequip_tick = tick; + break; } } if(bl->type==BL_MOB) ((TBL_MOB*)bl)->skill_idx = -1; - clif_skillcastcancel(bl); + clif->skillcastcancel(bl); return 1; } @@ -1982,7 +1997,7 @@ int unit_fixdamage(struct block_list *src,struct block_list *target,unsigned int if(damage+damage2 <= 0) return 0; - return status_fix_damage(src,target,damage+damage2,clif_damage(target,target,tick,sdelay,ddelay,damage,div,type,damage2)); + return status_fix_damage(src,target,damage+damage2,clif->damage(target,target,tick,sdelay,ddelay,damage,div,type,damage2)); } /*========================================== @@ -2001,7 +2016,7 @@ int unit_changeviewsize(struct block_list *bl,short size) } else return 0; if(size!=0) - clif_specialeffect(bl,421+size, AREA); + clif->specialeffect(bl,421+size, AREA); return 0; } @@ -2069,21 +2084,26 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, } if (bl->type&(BL_CHAR|BL_PET)) { - skill_unit_move(bl,gettick(),4); - skill_cleartimerskill(bl); + skill->unit_move(bl,gettick(),4); + skill->cleartimerskill(bl); } switch( bl->type ) { case BL_PC: { struct map_session_data *sd = (struct map_session_data*)bl; + if(sd->shadowform_id){ + struct block_list *d_bl = map_id2bl(sd->shadowform_id); + if( d_bl ) + status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER); + } //Leave/reject all invitations. if(sd->chatID) chat_leavechat(sd,0); if(sd->trade_partner) trade_tradecancel(sd); - buyingstore_close(sd); - searchstore_close(sd); + buyingstore->close(sd); + searchstore->close(sd); if(sd->state.storage_flag == 1) storage_storage_quit(sd,0); else if (sd->state.storage_flag == 2) @@ -2092,9 +2112,9 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, if(sd->party_invite>0) party_reply_invite(sd,sd->party_invite,0); if(sd->guild_invite>0) - guild_reply_invite(sd,sd->guild_invite,0); + guild->reply_invite(sd,sd->guild_invite,0); if(sd->guild_alliance>0) - guild_reply_reqalliance(sd,sd->guild_alliance_account,0); + guild->reply_reqalliance(sd,sd->guild_alliance_account,0); if(sd->menuskill_id) sd->menuskill_id = sd->menuskill_val = 0; if( sd->touching_id ) @@ -2120,10 +2140,10 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, if(pc_issit(sd)) { pc_setstand(sd); - skill_sit(sd,0); + skill->sit(sd,0); } party_send_dot_remove(sd);//minimap dot fix [Kevin] - guild_send_dot_remove(sd); + guild->send_dot_remove(sd); bg_send_dot_remove(sd); if( map[bl->m].users <= 0 || sd->state.debug_remove_map ) @@ -2178,7 +2198,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, struct pet_data *pd = (struct pet_data*)bl; if( pd->pet.intimate <= 0 && !(pd->msd && !pd->msd->state.active) ) { //If logging out, this is deleted on unit_free - clif_clearunit_area(bl,clrtype); + clif->clearunit_area(bl,clrtype); map_delblock(bl); unit_free(bl,CLR_OUTSIGHT); map_freeblock_unlock(); @@ -2192,8 +2212,8 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, ud->canact_tick = ud->canmove_tick; //It appears HOM do reset the can-act tick. if( !hd->homunculus.intimacy && !(hd->master && !hd->master->state.active) ) { //If logging out, this is deleted on unit_free - clif_emotion(bl, E_SOB); - clif_clearunit_area(bl,clrtype); + clif->emotion(bl, E_SOB); + clif->clearunit_area(bl,clrtype); map_delblock(bl); unit_free(bl,CLR_OUTSIGHT); map_freeblock_unlock(); @@ -2206,7 +2226,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, ud->canact_tick = ud->canmove_tick; if( mercenary_get_lifetime(md) <= 0 && !(md->master && !md->master->state.active) ) { - clif_clearunit_area(bl,clrtype); + clif->clearunit_area(bl,clrtype); map_delblock(bl); unit_free(bl,CLR_OUTSIGHT); map_freeblock_unlock(); @@ -2219,7 +2239,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, ud->canact_tick = ud->canmove_tick; if( elemental_get_lifetime(ed) <= 0 && !(ed->master && !ed->master->state.active) ) { - clif_clearunit_area(bl,clrtype); + clif->clearunit_area(bl,clrtype); map_delblock(bl); unit_free(bl,0); map_freeblock_unlock(); @@ -2233,7 +2253,7 @@ int unit_remove_map_(struct block_list *bl, clr_type clrtype, const char* file, * BL_MOB is handled by mob_dead unless the monster is not dead. **/ if( bl->type != BL_MOB || !status_isdead(bl) ) - clif_clearunit_area(bl,clrtype); + clif->clearunit_area(bl,clrtype); map_delblock(bl); map_freeblock_unlock(); return 1; @@ -2247,7 +2267,7 @@ void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype) if(sd->pd) unit_remove_map(&sd->pd->bl, clrtype); - if(merc_is_hom_active(sd->hd)) + if(homun_alive(sd->hd)) unit_remove_map(&sd->hd->bl, clrtype); if(sd->md) unit_remove_map(&sd->md->bl, clrtype); @@ -2277,8 +2297,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) if( bl->prev ) //Players are supposed to logout with a "warp" effect. unit_remove_map(bl, clrtype); - switch( bl->type ) - { + switch( bl->type ) { case BL_PC: { struct map_session_data *sd = (struct map_session_data*)bl; @@ -2299,9 +2318,9 @@ int unit_free(struct block_list *bl, clr_type clrtype) duel_reject(sd->duel_invite, sd); // Notify friends that this char logged out. [Skotlex] - map_foreachpc(clif_friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0); + map_foreachpc(clif->friendslist_toggle_sub, sd->status.account_id, sd->status.char_id, 0); party_send_logout(sd); - guild_send_memberinfoshort(sd,0); + guild->send_memberinfoshort(sd,0); pc_cleareventtimer(sd); pc_inventory_rental_clear(sd); pc_delspiritball(sd,sd->spiritball,1); @@ -2314,7 +2333,6 @@ int unit_free(struct block_list *bl, clr_type clrtype) sd->reg_num = 0; } if( sd->regstr ) { - int i; for( i = 0; i < sd->regstr_num; ++i ) if( sd->regstr[i].data ) aFree(sd->regstr[i].data); @@ -2332,6 +2350,15 @@ int unit_free(struct block_list *bl, clr_type clrtype) aFree(sd->combos.id); sd->combos.count = 0; } + /* [Ind/Hercules] */ + if( sd->sc_display_count ) { + for(i = 0; i < sd->sc_display_count; i++) { + ers_free(pc_sc_display_ers, sd->sc_display[i]); + } + sd->sc_display_count = 0; + aFree(sd->sc_display); + sd->sc_display = NULL; + } break; } case BL_PET: @@ -2450,11 +2477,10 @@ int unit_free(struct block_list *bl, clr_type clrtype) { struct homun_data *hd = (TBL_HOM*)bl; struct map_session_data *sd = hd->master; - merc_hom_hungry_timer_delete(hd); + homun->hunger_timer_delete(hd); if( hd->homunculus.intimacy > 0 ) - merc_save(hd); - else - { + homun->save(hd); + else { intif_homunculus_requestdelete(hd->homunculus.hom_id); if( sd ) sd->status.hom_id = 0; @@ -2499,7 +2525,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) } } - skill_clear_unitgroup(bl); + skill->clear_unitgroup(bl); status_change_clear(bl,1); map_deliddb(bl); if( bl->type != BL_PC ) //Players are handled by map_quit diff --git a/src/map/vending.c b/src/map/vending.c index 0f8255788..1576b684e 100644 --- a/src/map/vending.c +++ b/src/map/vending.c @@ -1,5 +1,6 @@ -// 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 #include "../common/nullpo.h" #include "../common/strlib.h" @@ -20,33 +21,28 @@ #include <stdio.h> #include <string.h> -static int vending_nextid = 0; - /// Returns an unique vending shop id. -static int vending_getuid(void) -{ - return vending_nextid++; +static inline unsigned int getid(void) { + return vending->next_id++; } /*========================================== * Close shop *------------------------------------------*/ -void vending_closevending(struct map_session_data* sd) -{ +void vending_closevending(struct map_session_data* sd) { nullpo_retv(sd); - if( sd->state.vending ) - { + if( sd->state.vending ) { sd->state.vending = false; - clif_closevendingboard(&sd->bl, 0); + clif->closevendingboard(&sd->bl, 0); + idb_remove(vending->db, sd->status.char_id); } } /*========================================== * Request a shop's item list *------------------------------------------*/ -void vending_vendinglistreq(struct map_session_data* sd, int id) -{ +void vending_vendinglistreq(struct map_session_data* sd, unsigned int id) { struct map_session_data* vsd; nullpo_retv(sd); @@ -55,41 +51,39 @@ void vending_vendinglistreq(struct map_session_data* sd, int id) if( !vsd->state.vending ) return; // not vending - if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) //check if both GMs are allowed to trade - { // GM is not allowed to trade - clif_displaymessage(sd->fd, msg_txt(246)); + if (!pc_can_give_items(sd) || !pc_can_give_items(vsd)) { //check if both GMs are allowed to trade + // GM is not allowed to trade + clif->message(sd->fd, msg_txt(246)); return; } sd->vended_id = vsd->vender_id; // register vending uid - clif_vendinglist(sd, id, vsd->vending); + clif->vendinglist(sd, id, vsd->vending); } /*========================================== * Purchase item(s) from a shop *------------------------------------------*/ -void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count) -{ +void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid, const uint8* data, int count) { int i, j, cursor, w, new_ = 0, blank, vend_list[MAX_VENDING]; double z; - struct s_vending vending[MAX_VENDING]; // against duplicate packets + struct s_vending vend[MAX_VENDING]; // against duplicate packets struct map_session_data* vsd = map_id2sd(aid); nullpo_retv(sd); if( vsd == NULL || !vsd->state.vending || vsd->bl.id == sd->bl.id ) return; // invalid shop - if( vsd->vender_id != uid ) - {// shop has changed - clif_buyvending(sd, 0, 0, 6); // store information was incorrect + if( vsd->vender_id != uid ) { // shop has changed + clif->buyvending(sd, 0, 0, 6); // store information was incorrect return; } - if( !searchstore_queryremote(sd, aid) && ( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) ) ) + if( !searchstore->queryremote(sd, aid) && ( sd->bl.m != vsd->bl.m || !check_distance_bl(&sd->bl, &vsd->bl, AREA_SIZE) ) ) return; // shop too far away - searchstore_clearremote(sd); + searchstore->clearremote(sd); if( count < 1 || count > MAX_VENDING || count > vsd->vend_num ) return; // invalid amount of purchased items @@ -97,13 +91,12 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui blank = pc_inventoryblank(sd); //number of free cells in the buyer's inventory // duplicate item in vending to check hacker with multiple packets - memcpy(&vending, &vsd->vending, sizeof(vsd->vending)); // copy vending list + memcpy(&vend, &vsd->vending, sizeof(vsd->vending)); // copy vending list // some checks z = 0.; // zeny counter w = 0; // weight counter - for( i = 0; i < count; i++ ) - { + for( i = 0; i < count; i++ ) { short amount = *(uint16*)(data + 4*i + 0); short idx = *(uint16*)(data + 4*i + 2); idx -= 2; @@ -122,49 +115,45 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui vend_list[i] = j; z += ((double)vsd->vending[j].value * (double)amount); - if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) - { - clif_buyvending(sd, idx, amount, 1); // you don't have enough zeny + if( z > (double)sd->status.zeny || z < 0. || z > (double)MAX_ZENY ) { + clif->buyvending(sd, idx, amount, 1); // you don't have enough zeny return; } - if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max ) - { - clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow + if( z + (double)vsd->status.zeny > (double)MAX_ZENY && !battle_config.vending_over_max ) { + clif->buyvending(sd, idx, vsd->vending[j].amount, 4); // too much zeny = overflow return; } w += itemdb_weight(vsd->status.cart[idx].nameid) * amount; - if( w + sd->weight > sd->max_weight ) - { - clif_buyvending(sd, idx, amount, 2); // you can not buy, because overweight + if( w + sd->weight > sd->max_weight ) { + clif->buyvending(sd, idx, amount, 2); // you can not buy, because overweight return; } //Check to see if cart/vend info is in sync. - if( vending[j].amount > vsd->status.cart[idx].amount ) - vending[j].amount = vsd->status.cart[idx].amount; + if( vend[j].amount > vsd->status.cart[idx].amount ) + vend[j].amount = vsd->status.cart[idx].amount; // if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples). // here, we check cumulative amounts - if( vending[j].amount < amount ) - { + if( vend[j].amount < amount ) { // send more quantity is not a hack (an other player can have buy items just before) - clif_buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity + clif->buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity return; } - vending[j].amount -= amount; + vend[j].amount -= amount; switch( pc_checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) { - case ADDITEM_EXIST: - break; //We'd add this item to the existing one (in buyers inventory) - case ADDITEM_NEW: - new_++; - if (new_ > blank) - return; //Buyer has no space in his inventory - break; - case ADDITEM_OVERAMOUNT: - return; //too many items + case ADDITEM_EXIST: + break; //We'd add this item to the existing one (in buyers inventory) + case ADDITEM_NEW: + new_++; + if (new_ > blank) + return; //Buyer has no space in his inventory + break; + case ADDITEM_OVERAMOUNT: + return; //too many items } } @@ -173,8 +162,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui z -= z * (battle_config.vending_tax/10000.); pc_getzeny(vsd, (int)z, LOG_TYPE_VENDING, sd); - for( i = 0; i < count; i++ ) - { + for( i = 0; i < count; i++ ) { short amount = *(uint16*)(data + 4*i + 0); short idx = *(uint16*)(data + 4*i + 2); idx -= 2; @@ -183,25 +171,22 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui pc_additem(sd, &vsd->status.cart[idx], amount, LOG_TYPE_VENDING); vsd->vending[vend_list[i]].amount -= amount; pc_cart_delitem(vsd, idx, amount, 0, LOG_TYPE_VENDING); - clif_vendingreport(vsd, idx, amount); + clif->vendingreport(vsd, idx, amount); //print buyer's name - if( battle_config.buyer_name ) - { + if( battle_config.buyer_name ) { char temp[256]; sprintf(temp, msg_txt(265), sd->status.name); - clif_disp_onlyself(vsd,temp,strlen(temp)); + clif->disp_onlyself(vsd,temp,strlen(temp)); } } // compact the vending list - for( i = 0, cursor = 0; i < vsd->vend_num; i++ ) - { + for( i = 0, cursor = 0; i < vsd->vend_num; i++ ) { if( vsd->vending[i].amount == 0 ) continue; - if( cursor != i ) // speedup - { + if( cursor != i ) { // speedup vsd->vending[cursor].index = vsd->vending[i].index; vsd->vending[cursor].amount = vsd->vending[i].amount; vsd->vending[cursor].value = vsd->vending[i].value; @@ -212,84 +197,52 @@ void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const ui vsd->vend_num = cursor; //Always save BOTH: buyer and customer - if( save_settings&2 ) - { + if( save_settings&2 ) { chrif_save(sd,0); chrif_save(vsd,0); } //check for @AUTOTRADE users [durf] - if( vsd->state.autotrade ) - { + if( vsd->state.autotrade ) { //see if there is anything left in the shop ARR_FIND( 0, vsd->vend_num, i, vsd->vending[i].amount > 0 ); - if( i == vsd->vend_num ) - { + if( i == vsd->vend_num ) { //Close Vending (this was automatically done by the client, we have to do it manually for autovenders) [Skotlex] - vending_closevending(vsd); + vending->close(vsd); map_quit(vsd); //They have no reason to stay around anymore, do they? } } } -static int vending_checknearnpc_sub(struct block_list* bl, va_list args) { - struct npc_data *nd = (struct npc_data*)bl; - - if( nd->sc.option & (OPTION_HIDE|OPTION_INVISIBLE) ) - return 0; - return 1; -} -bool vending_checknearnpc(struct block_list * bl) { - - if( battle_config.min_npc_vending_distance > 0 && - map_foreachinrange(vending_checknearnpc_sub,bl, battle_config.min_npc_vending_distance, BL_NPC) ) - return true; - - return false; -} /*========================================== * Open shop * data := {<index>.w <amount>.w <value>.l}[count] *------------------------------------------*/ -void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count) { +void vending_openvending(struct map_session_data* sd, const char* message, const uint8* data, int count) { int i, j; int vending_skill_lvl; nullpo_retv(sd); - if( !flag ) // cancelled - return; // nothing to do - if ( pc_isdead(sd) || !sd->state.prevend || pc_istrading(sd)) return; // can't open vendings lying dead || didn't use via the skill (wpe/hack) || can't have 2 shops at once vending_skill_lvl = pc_checkskill(sd, MC_VENDING); // skill level and cart check - if( !vending_skill_lvl || !pc_iscarton(sd) ) - { - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); + if( !vending_skill_lvl || !pc_iscarton(sd) ) { + clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return; } // check number of items in shop - if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) - { // invalid item count - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); + if( count < 1 || count > MAX_VENDING || count > 2 + vending_skill_lvl ) { + // invalid item count + clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); return; } - //check if nearby npc, (perhaps we should check for nearby shop too - if( vending_checknearnpc(&sd->bl) ) { - char output[150]; - sprintf(output,"You're too close to a NPC, you must be at least %d cells away from any NPC.",battle_config.min_npc_vending_distance); - clif_displaymessage(sd->fd, output); - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); - return; - } - // filter out invalid items i = 0; - for( j = 0; j < count; j++ ) - { + for( j = 0; j < count; j++ ) { short index = *(uint16*)(data + 8*j + 0); short amount = *(uint16*)(data + 8*j + 2); unsigned int value = *(uint32*)(data + 8*j + 4); @@ -313,38 +266,35 @@ void vending_openvending(struct map_session_data* sd, const char* message, bool } if( i != j ) - clif_displaymessage (sd->fd, msg_txt(266)); //"Some of your items cannot be vended and were removed from the shop." + clif->message (sd->fd, msg_txt(266)); //"Some of your items cannot be vended and were removed from the shop." - if( i == 0 ) - { // no valid item found - clif_skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet + if( i == 0 ) { // no valid item found + clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0); // custom reply packet return; } sd->state.prevend = 0; sd->state.vending = true; - sd->vender_id = vending_getuid(); + sd->vender_id = getid(); sd->vend_num = i; safestrncpy(sd->message, message, MESSAGE_SIZE); - pc_stop_walking(sd,1); - clif_openvending(sd,sd->bl.id,sd->vending); - clif_showvendingboard(&sd->bl,message,0); + clif->openvending(sd,sd->bl.id,sd->vending); + clif->showvendingboard(&sd->bl,message,0); + + idb_put(vending->db, sd->vender_id, sd); } /// Checks if an item is being sold in given player's vending. -bool vending_search(struct map_session_data* sd, unsigned short nameid) -{ +bool vending_search(struct map_session_data* sd, unsigned short nameid) { int i; - if( !sd->state.vending ) - {// not vending + if( !sd->state.vending ) { // not vending return false; } ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)nameid ); - if( i == sd->vend_num ) - {// not found + if( i == sd->vend_num ) { // not found return false; } @@ -354,46 +304,36 @@ bool vending_search(struct map_session_data* sd, unsigned short nameid) /// Searches for all items in a vending, that match given ids, price and possible cards. /// @return Whether or not the search should be continued. -bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s) -{ +bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s) { int i, c, slot; unsigned int idx, cidx; struct item* it; - if( !sd->state.vending ) - {// not vending + if( !sd->state.vending ) // not vending return true; - } - for( idx = 0; idx < s->item_count; idx++ ) - { + for( idx = 0; idx < s->item_count; idx++ ) { ARR_FIND( 0, sd->vend_num, i, sd->status.cart[sd->vending[i].index].nameid == (short)s->itemlist[idx] ); - if( i == sd->vend_num ) - {// not found + if( i == sd->vend_num ) {// not found continue; } it = &sd->status.cart[sd->vending[i].index]; - if( s->min_price && s->min_price > sd->vending[i].value ) - {// too low price + if( s->min_price && s->min_price > sd->vending[i].value ) {// too low price continue; } - if( s->max_price && s->max_price < sd->vending[i].value ) - {// too high price + if( s->max_price && s->max_price < sd->vending[i].value ) {// too high price continue; } - if( s->card_count ) - {// check cards - if( itemdb_isspecial(it->card[0]) ) - {// something, that is not a carded + if( s->card_count ) {// check cards + if( itemdb_isspecial(it->card[0]) ) {// something, that is not a carded continue; } slot = itemdb_slot(it->nameid); - for( c = 0; c < slot && it->card[c]; c ++ ) - { + for( c = 0; c < slot && it->card[c]; c ++ ) { ARR_FIND( 0, s->card_count, cidx, s->cardlist[cidx] == it->card[c] ); if( cidx != s->card_count ) {// found @@ -401,13 +341,12 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_ } } - if( c == slot || !it->card[c] ) - {// no card match + if( c == slot || !it->card[c] ) {// no card match continue; } } - if( !searchstore_result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine) ) + if( !searchstore->result(s->search_sd, sd->vender_id, sd->status.account_id, sd->message, it->nameid, sd->vending[i].amount, sd->vending[i].value, it->card, it->refine) ) {// result set full return false; } @@ -415,3 +354,25 @@ bool vending_searchall(struct map_session_data* sd, const struct s_search_store_ return true; } +void final(void) { + db_destroy(vending->db); +} + +void init(void) { + vending->db = idb_alloc(DB_OPT_BASE); + vending->next_id = 0; +} + +void vending_defaults(void) { + vending = &vending_s; + + vending->init = init; + vending->final = final; + + vending->close = vending_closevending; + vending->open = vending_openvending; + vending->list = vending_vendinglistreq; + vending->purchase = vending_purchasereq; + vending->search = vending_search; + vending->searchall = vending_searchall; +} diff --git a/src/map/vending.h b/src/map/vending.h index 2ed52b9bd..0148deb71 100644 --- a/src/map/vending.h +++ b/src/map/vending.h @@ -1,11 +1,12 @@ -// 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 _VENDING_H_ #define _VENDING_H_ #include "../common/cbasetypes.h" -//#include "map.h" +#include "../common/db.h" struct map_session_data; struct s_search_store_search; @@ -15,12 +16,23 @@ struct s_vending { unsigned int value; //at wich price }; -void vending_closevending(struct map_session_data* sd); -void vending_openvending(struct map_session_data* sd, const char* message, bool flag, const uint8* data, int count); -void vending_vendinglistreq(struct map_session_data* sd, int id); -void vending_purchasereq(struct map_session_data* sd, int aid, int uid, const uint8* data, int count); -bool vending_search(struct map_session_data* sd, unsigned short nameid); -bool vending_searchall(struct map_session_data* sd, const struct s_search_store_search* s); -bool vending_checknearnpc(struct block_list * bl); +struct vending_interface { + unsigned int next_id;/* next vender id */ + DBMap *db; + /* */ + void (*init) (void); + void (*final) (void); + /* */ + void (*close) (struct map_session_data* sd); + void (*open) (struct map_session_data* sd, const char* message, const uint8* data, int count); + void (*list) (struct map_session_data* sd, unsigned int id); + void (*purchase) (struct map_session_data* sd, int aid, unsigned int uid, const uint8* data, int count); + bool (*search) (struct map_session_data* sd, unsigned short nameid); + bool (*searchall) (struct map_session_data* sd, const struct s_search_store_search* s); +} vending_s; + +struct vending_interface * vending; + +void vending_defaults(void); #endif /* _VENDING_H_ */ diff --git a/src/plugins/CMakeLists.txt b/src/plugins/CMakeLists.txt new file mode 100644 index 000000000..4e4851bc5 --- /dev/null +++ b/src/plugins/CMakeLists.txt @@ -0,0 +1,36 @@ +# +# setup +# +get_property( CAN_BUILD_SHARED_LIBS GLOBAL PROPERTY TARGET_SUPPORTS_SHARED_LIBS ) +if( NOT CAN_BUILD_SHARED_LIBS ) + return() +endif() + +# +# sample +# +option( BUILD_PLUGIN_sample "build sample plugin" OFF ) +if( BUILD_PLUGIN_sample ) +message( STATUS "Creating target sample" ) +set( SAMPLE_SOURCES + "${CMAKE_CURRENT_SOURCE_DIR}/sample.c" + ) +set( LIBRARIES ${GLOBAL_LIBRARIES} ) +set( INCLUDE_DIRS ${GLOBAL_INCLUDE_DIRS} ) +set( DEFINITIONS ${GLOBAL_DEFINITIONS} ) +set( SOURCE_FILES ${SAMPLE_SOURCES} ) +source_group( sample FILES ${SAMPLE_SOURCES} ) +include_directories( ${INCLUDE_DIRS} ) +add_library( sample SHARED ${SOURCE_FILES} ) +target_link_libraries( sample ${LIBRARIES} ) +set_target_properties( sample PROPERTIES COMPILE_FLAGS "${DEFINITIONS}" ) +set_target_properties( sample PROPERTIES PREFIX "" ) +if( INSTALL_COMPONENT_RUNTIME ) + cpack_add_component( Runtime_sample DESCRIPTION "sample plugin" DISPLAY_NAME "sample" GROUP Runtime ) + install( TARGETS sample + DESTINATION "plugins" + COMPONENT Runtime_sample ) +endif( INSTALL_COMPONENT_RUNTIME ) +set( TARGET_LIST ${TARGET_LIST} sample CACHE INTERNAL "" ) +message( STATUS "Creating target sample - done" ) +endif( BUILD_PLUGIN_sample )
\ No newline at end of file diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in new file mode 100644 index 000000000..71b743dca --- /dev/null +++ b/src/plugins/Makefile.in @@ -0,0 +1,28 @@ + +COMMON_H = ../common/HPMi.h ../common/cbasetypes.h + +PLUGINS = sample + +@SET_MAKE@ + +##################################################################### +.PHONY : all $(PLUGINS) sample clean help + +all: $(PLUGINS) + +sample: sample@DLLEXT@ + +clean: + @echo " CLEAN plugins" + @rm -rf *.o + +help: + @echo "possible targets are $(PLUGINS:%='%') 'all' 'clean' 'help'" + @echo "'sample' - sample plugin" + @echo "'help' - outputs this message" + +##################################################################### + +%@DLLEXT@: %.c $(COMMON_H) + @echo " CC $<" + @@CC@ @DEFS@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ @SOFLAGS@ -o ../../plugins/$@ $<
\ No newline at end of file diff --git a/src/plugins/sample.c b/src/plugins/sample.c new file mode 100644 index 000000000..7f7528cb7 --- /dev/null +++ b/src/plugins/sample.c @@ -0,0 +1,70 @@ +// Copyright (c) Hercules Dev Team, licensed under GNU GPL. +// See the LICENSE file +// Sample Hercules Plugin + +#include <stdio.h> +#include <string.h> +#include "../common/HPMi.h" +#include "../map/script.h" +#include "../map/pc.h" + +HPExport struct hplugin_info pinfo = { + "Sample", // Plugin name + SERVER_TYPE_MAP,// Which server types this plugin works with? + "0.1", // Plugin version + HPM_VERSION, // HPM Version (don't change, macro is automatically updated) +}; +ACMD(sample) {//@sample command - 5 params: const int fd, struct map_session_data* sd, const char* command, const char* message, struct AtCommandInfo *info + printf("I'm being run! message -> '%s' by %s\n",message,sd->status.name); + return true; +} +BUILDIN(sample) {//script command 'sample(num);' - 1 param: struct script_state* st + int arg = script_getnum(st,2); + ShowInfo("I'm being run! arg -> '%d'\n",arg); + return true; +} +CPCMD(sample) {//console command 'sample' - 1 param: char *line + ShowInfo("I'm being run! arg -> '%s'\n",line?line:"NONE"); +} +struct script_interface *script;/* used by script commands */ +/* run when server starts */ +HPExport void plugin_init (void) { + char *server_type; + char *server_name; + + //get the symbols from the server + server_type = GET_SYMBOL("SERVER_TYPE"); + server_name = GET_SYMBOL("SERVER_NAME"); + + script = GET_SYMBOL("script"); + + ShowInfo ("Server type is "); + + switch (*server_type) { + case SERVER_TYPE_LOGIN: printf ("Login Server\n"); break; + case SERVER_TYPE_CHAR: printf ("Char Server\n"); break; + case SERVER_TYPE_MAP: printf ("Map Server\n"); break; + } + + ShowInfo ("I'm being run from the '%s' filename\n", server_name); + + if( HPMi->addCommand != NULL ) {//link our '@sample' command + HPMi->addCommand("sample",ACMD_A(sample)); + } + + if( HPMi->addScript != NULL ) {//link our 'sample' script command + HPMi->addScript("sample","i",BUILDIN_A(sample)); + } + + if( HPMi->addCPCommand != NULL ) {//link our 'sample' console command + HPMi->addCPCommand("this:is:a:sample",CPCMD_A(sample)); + } +} +/* run when server is ready (online) */ +HPExport void server_online (void) { + +} +/* run when server is shutting down */ +HPExport void plugin_final (void) { + ShowInfo ("%s says ~Bye world\n",pinfo.name); +}
\ No newline at end of file diff --git a/src/tool/Makefile.in b/src/tool/Makefile.in index d72ef5405..1e149c2b3 100644 --- a/src/tool/Makefile.in +++ b/src/tool/Makefile.in @@ -1,10 +1,10 @@ COMMON_OBJ = ../common/obj_all/minicore.o ../common/obj_all/malloc.o \ ../common/obj_all/showmsg.o ../common/obj_all/strlib.o \ - ../common/obj_all/utils.o ../common/obj_all/des.o ../common/obj_all/grfio.o + ../common/obj_all/utils.o ../common/obj_all/des.o ../common/obj_all/grfio.o ../common/obj_all/miniconsole.o COMMON_H = ../common/core.h ../common/mmo.h \ ../common/malloc.h ../common/showmsg.h ../common/strlib.h \ - ../common/utils.h ../common/cbasetypes.h ../common/des.h ../common/grfio.h ../config/renewal.h + ../common/utils.h ../common/cbasetypes.h ../common/des.h ../common/grfio.h ../common/console.h ../config/renewal.h LIBCONFIG_OBJ = ../../3rdparty/libconfig/libconfig.o ../../3rdparty/libconfig/grammar.o \ ../../3rdparty/libconfig/scanctx.o ../../3rdparty/libconfig/scanner.o ../../3rdparty/libconfig/strbuf.o @@ -42,7 +42,8 @@ help: ##################################################################### obj_all: - -mkdir obj_all + @echo " MKDIR obj_all" + @-mkdir obj_all obj_all/%.o: %.c $(COMMON_H) $(OTHER_H) $(LIBCONFIG_H) @echo " CC $<" @@ -50,10 +51,10 @@ obj_all/%.o: %.c $(COMMON_H) $(OTHER_H) $(LIBCONFIG_H) # missing common object files ../common/obj_all/%.o: - @$(MAKE) -C ../common txt + @$(MAKE) -C ../common sql ../common/obj_all/mini%.o: - @$(MAKE) -C ../common txt + @$(MAKE) -C ../common sql LIBCONFIG_OBJ: @$(MAKE) -C ../../3rdparty/libconfig |