summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/char/HPMchar.c53
-rw-r--r--src/char/HPMchar.h21
-rw-r--r--src/char/Makefile.in14
-rw-r--r--src/char/char.c117
-rw-r--r--src/char/char.h2
-rw-r--r--src/char/int_mail.c3
-rw-r--r--src/char/int_storage.c1
-rw-r--r--src/char/inter.c25
-rw-r--r--src/common/HPM.c115
-rw-r--r--src/common/HPM.h4
-rw-r--r--src/common/HPMDataCheck.h73
-rw-r--r--src/common/HPMi.h1
-rw-r--r--src/common/db.h99
-rw-r--r--src/common/mmo.h2
-rw-r--r--src/common/socket.c7
-rw-r--r--src/config/core.h13
-rw-r--r--src/login/HPMlogin.c53
-rw-r--r--src/login/HPMlogin.h20
-rw-r--r--src/login/Makefile.in6
-rw-r--r--src/login/account_sql.c14
-rw-r--r--src/login/ipban_sql.c4
-rw-r--r--src/login/login.c51
-rw-r--r--src/login/loginlog_sql.c4
-rw-r--r--src/map/HPMmap.c44
-rw-r--r--src/map/HPMmap.h2
-rw-r--r--src/map/Makefile.in2
-rw-r--r--src/map/atcommand.c44
-rw-r--r--src/map/battle.c57
-rw-r--r--src/map/battle.h8
-rw-r--r--src/map/chrif.c7
-rw-r--r--src/map/clif.c417
-rw-r--r--src/map/clif.h49
-rw-r--r--src/map/guild.c10
-rw-r--r--src/map/intif.c6
-rw-r--r--src/map/itemdb.c6
-rw-r--r--src/map/itemdb.h2
-rw-r--r--src/map/log.h2
-rw-r--r--src/map/map.c146
-rw-r--r--src/map/map.h18
-rw-r--r--src/map/mob.c169
-rw-r--r--src/map/mob.h5
-rw-r--r--src/map/npc.c75
-rw-r--r--src/map/packets.h127
-rw-r--r--src/map/packets_struct.h70
-rw-r--r--src/map/party.c8
-rw-r--r--src/map/path.c95
-rw-r--r--src/map/path.h12
-rw-r--r--src/map/pc.c168
-rw-r--r--src/map/pc.h28
-rw-r--r--src/map/pet.c2
-rw-r--r--src/map/script.c527
-rw-r--r--src/map/script.h8
-rw-r--r--src/map/skill.c210
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c182
-rw-r--r--src/map/status.h8
-rw-r--r--src/map/storage.c28
-rw-r--r--src/map/storage.h3
-rw-r--r--src/map/unit.c354
-rw-r--r--src/map/unit.h8
-rw-r--r--src/plugins/HPMHooking.c46
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.GetSymbol.inc7
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc55
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc21
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.Hooks.inc269
-rw-r--r--src/plugins/HPMHooking/HPMHooking_char.sources.inc7
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.GetSymbol.inc6
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc14
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc10
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.Hooks.inc6
-rw-r--r--src/plugins/HPMHooking/HPMHooking_login.sources.inc6
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.GetSymbol.inc (renamed from src/plugins/HPMHooking/HPMHooking.GetSymbol.inc)0
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc (renamed from src/plugins/HPMHooking/HPMHooking.HPMHooksCore.inc)84
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc (renamed from src/plugins/HPMHooking/HPMHooking.HookingPoints.inc)21
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.Hooks.inc (renamed from src/plugins/HPMHooking/HPMHooking.Hooks.inc)560
-rw-r--r--src/plugins/HPMHooking/HPMHooking_map.sources.inc (renamed from src/plugins/HPMHooking/HPMHooking.sources.inc)0
-rw-r--r--src/plugins/Makefile.in20
-rw-r--r--src/plugins/sample.c2
-rw-r--r--src/tool/Makefile.in2
79 files changed, 3659 insertions, 1087 deletions
diff --git a/src/char/HPMchar.c b/src/char/HPMchar.c
new file mode 100644
index 000000000..4b153b244
--- /dev/null
+++ b/src/char/HPMchar.c
@@ -0,0 +1,53 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#define HERCULES_CORE
+
+#include "HPMchar.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/db.h"
+#include "../common/des.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/mapindex.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+
+#include "../common/HPMDataCheck.h"
+
+bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
+ /* record address */
+ switch( type ) {
+ default:
+ return false;
+ }
+ return true;
+}
+
+void HPM_char_plugin_load_sub(struct hplugin *plugin) {
+}
+
+void HPM_char_do_init(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+ HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
+#else
+ HPM->DataCheck = NULL;
+#endif
+}
+
+void HPM_char_do_final(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+ HPM->datacheck_final();
+#endif
+}
diff --git a/src/char/HPMchar.h b/src/char/HPMchar.h
new file mode 100644
index 000000000..9d367725c
--- /dev/null
+++ b/src/char/HPMchar.h
@@ -0,0 +1,21 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef CHAR_HPMCHAR_H
+#define CHAR_HPMCHAR_H
+
+#include "../common/cbasetypes.h"
+#include "../common/HPM.h"
+
+struct hplugin;
+
+bool HPM_char_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+
+void HPM_char_plugin_load_sub(struct hplugin *plugin);
+
+void HPM_char_do_final(void);
+
+void HPM_char_do_init(void);
+
+#endif /* CHAR_HPMCHAR_H */
+
diff --git a/src/char/Makefile.in b/src/char/Makefile.in
index 59dc56076..d591a5370 100644
--- a/src/char/Makefile.in
+++ b/src/char/Makefile.in
@@ -22,13 +22,13 @@ MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
MT19937AR_INCLUDE = -I$(MT19937AR_D)
-CHAR_C = char.c inter.c int_auction.c int_elemental.c int_guild.c int_homun.c \
- int_mail.c int_mercenary.c int_party.c int_pet.c int_quest.c \
- int_storage.c pincode.c
+CHAR_C = char.c HPMchar.c inter.c int_auction.c int_elemental.c int_guild.c \
+ int_homun.c int_mail.c int_mercenary.c int_party.c int_pet.c \
+ int_quest.c int_storage.c pincode.c
CHAR_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(CHAR_C)))
-CHAR_H = char.h inter.h int_auction.h int_elemental.h int_guild.h int_homun.h \
- int_mail.h int_mercenary.h int_party.h int_pet.h int_quest.h \
- int_storage.h pincode.h
+CHAR_H = char.h HPMchar.h inter.h int_auction.h int_elemental.h int_guild.h \
+ int_homun.h int_mail.h int_mercenary.h int_party.h int_pet.h \
+ int_quest.h int_storage.h pincode.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
@@ -91,7 +91,7 @@ char-server: ../../char-server@EXEEXT@
../../char-server@EXEEXT@: $(CHAR_SERVER_SQL_DEPENDS) Makefile
@echo " LD $(notdir $@)"
- @$(CC) @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
+ @$(CC) @STATIC@ @LDFLAGS@ -o ../../char-server@EXEEXT@ $(CHAR_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
$(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
# char object files
diff --git a/src/char/char.c b/src/char/char.c
index 0d96d40cb..60ef11397 100644
--- a/src/char/char.c
+++ b/src/char/char.c
@@ -15,6 +15,7 @@
#include <sys/types.h>
#include <time.h>
+#include "HPMchar.h"
#include "int_elemental.h"
#include "int_guild.h"
#include "int_homun.h"
@@ -750,6 +751,7 @@ int memitemdata_to_sql(const struct item items[], int max, int id, int tableswit
return 1;
}
+ memset(&item, 0, sizeof(item));
SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
@@ -893,6 +895,7 @@ int inventory_to_sql(const struct item items[], int max, int id) {
return 1;
}
+ memset(&item, 0, sizeof(item));
SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
@@ -1009,6 +1012,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
int j = 0, i;
char last_map[MAP_NAME_LENGTH_EXT];
time_t unban_time = 0;
+ char sex[2];
stmt = SQL->StmtMalloc(sql_handle);
if( stmt == NULL ) {
@@ -1028,7 +1032,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
"`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`,`slotchange`,`unban_time`"
+ "`robe`,`slotchange`,`unban_time`,`sex`"
" FROM `%s` WHERE `account_id`='%d' AND `char_num` < '%d'", char_db, sd->account_id, MAX_CHARS)
|| SQL_ERROR == SQL->StmtExecute(stmt)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &p.char_id, 0, NULL, NULL)
@@ -1069,6 +1073,7 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 35, SQLDT_SHORT, &p.robe, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 36, SQLDT_USHORT, &p.slotchange, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 37, SQLDT_LONG, &unban_time, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 38, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL)
)
{
SqlStmt_ShowDebug(stmt);
@@ -1080,6 +1085,18 @@ int mmo_chars_fromsql(struct char_session_data* sd, uint8* buf)
p.last_point.map = mapindex->name2id(last_map);
sd->found_char[p.slot] = p.char_id;
sd->unban_time[p.slot] = unban_time;
+ switch( sex[0] ) {
+ case 'M':
+ p.sex = 1;
+ break;
+ case 'F':
+ p.sex = 0;
+ break;
+ case 'U':
+ default:
+ p.sex = 99;
+ break;
+ }
j += mmo_char_tobuf(WBUFP(buf, j), &p);
}
@@ -1110,6 +1127,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
#endif
unsigned int opt;
int account_id;
+ char sex[2];
memset(p, 0, sizeof(struct mmo_charstatus));
@@ -1129,7 +1147,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
"`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`,`slotchange`,"
- "`char_opt`,`font`,`uniqueitem_counter`"
+ "`char_opt`,`font`,`uniqueitem_counter`,`sex`"
" FROM `%s` WHERE `char_id`=? LIMIT 1", char_db)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1189,6 +1207,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 53, SQLDT_UINT, &opt, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 54, SQLDT_UCHAR, &p->font, 0, NULL, NULL)
|| SQL_ERROR == SQL->StmtBindColumn(stmt, 55, SQLDT_UINT, &p->uniqueitem_counter, 0, NULL, NULL)
+ || SQL_ERROR == SQL->StmtBindColumn(stmt, 56, SQLDT_ENUM, &sex, sizeof(sex), NULL, NULL)
)
{
SqlStmt_ShowDebug(stmt);
@@ -1202,6 +1221,19 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
return 0;
}
+ switch( sex[0] ) {
+ case 'M':
+ p->sex = 1;
+ break;
+ case 'F':
+ p->sex = 0;
+ break;
+ case 'U':
+ default:
+ p->sex = 99;
+ break;
+ }
+
account_id = p->account_id;
p->last_point.map = mapindex->name2id(last_map);
@@ -1229,6 +1261,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
//read memo data
//`memo` (`memo_id`,`char_id`,`map`,`x`,`y`)
+ memset(&tmp_point, 0, sizeof(tmp_point));
if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `map`,`x`,`y` FROM `%s` WHERE `char_id`=? ORDER by `memo_id` LIMIT %d", memo_db, MAX_MEMOPOINTS)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1251,6 +1284,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
StrBuf->Printf(&buf, ", `card%d`", i);
StrBuf->Printf(&buf, " FROM `%s` WHERE `char_id`=? LIMIT %d", inventory_db, MAX_INVENTORY);
+ memset(&tmp_item, 0, sizeof(tmp_item));
if( SQL_ERROR == SQL->StmtPrepareStr(stmt, StrBuf->Value(&buf))
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1312,6 +1346,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
//read skill
//`skill` (`char_id`, `id`, `lv`)
+ memset(&tmp_skill, 0, sizeof(tmp_skill));
if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `id`, `lv`,`flag` FROM `%s` WHERE `char_id`=? LIMIT %d", skill_db, MAX_SKILL)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1333,6 +1368,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
//read friends
//`friends` (`char_id`, `friend_account`, `friend_id`)
+ memset(&tmp_friend, 0, sizeof(tmp_friend));
if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT c.`account_id`, c.`char_id`, c.`name` FROM `%s` c LEFT JOIN `%s` f ON f.`friend_account` = c.`account_id` AND f.`friend_id` = c.`char_id` WHERE f.`char_id`=? LIMIT %d", char_db, friend_db, MAX_FRIENDS)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1348,6 +1384,7 @@ int mmo_char_fromsql(int char_id, struct mmo_charstatus* p, bool load_everything
#ifdef HOTKEY_SAVING
//read hotkeys
//`hotkey` (`char_id`, `hotkey`, `type`, `itemskill_id`, `skill_lvl`
+ memset(&tmp_hotkey, 0, sizeof(tmp_hotkey));
if( SQL_ERROR == SQL->StmtPrepare(stmt, "SELECT `hotkey`, `type`, `itemskill_id`, `skill_lvl` FROM `%s` WHERE `char_id`=?", hotkey_db)
|| SQL_ERROR == SQL->StmtBindParam(stmt, 0, SQLDT_INT, &char_id, 0)
|| SQL_ERROR == SQL->StmtExecute(stmt)
@@ -1892,7 +1929,7 @@ int count_users(void)
// Writes char data to the buffer in the format used by the client.
// Used in packets 0x6b (chars info) and 0x6d (new char info)
// Returns the size
-#define MAX_CHAR_BUF 144 //Max size (for WFIFOHEAD calls)
+#define MAX_CHAR_BUF 150 //Max size (for WFIFOHEAD calls)
int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
unsigned short offset = 0;
uint8* buf;
@@ -1927,9 +1964,16 @@ int mmo_char_tobuf(uint8* buffer, struct mmo_charstatus* p) {
WBUFW(buf,52) = p->class_;
WBUFW(buf,54) = p->hair;
+#if PACKETVER >= 20141022
+ //When the weapon is sent and your option is riding, the client crashes on login!?
+ WBUFL(buf,56) = p->option&(0x20|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000) ? 0 : p->weapon;
+ offset+=2;
+ buf = WBUFP(buffer,offset);
+#else
//When the weapon is sent and your option is riding, the client crashes on login!?
WBUFW(buf,56) = p->option&(0x20|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000) ? 0 : p->weapon;
-
+#endif
+
WBUFW(buf,58) = p->base_level;
WBUFW(buf,60) = min(p->skill_point, INT16_MAX);
WBUFW(buf,62) = p->head_bottom;
@@ -1964,13 +2008,17 @@ 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) = ( p->slotchange > 0 ) ? 1 : 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
WBUFL(buf,136) = ( p->rename > 0 ) ? 1 : 0; // (0 = disabled, otherwise displays "Add-Ons" sidebar)
offset += 4;
#endif
+ #if PACKETVER >= 20141016
+ WBUFB(buf,140) = p->sex;// sex - (0 = female, 1 = male, 99 = logindefined)
+ offset += 1;
+ #endif
#endif
return 106+offset;
@@ -2037,8 +2085,8 @@ void mmo_char_send082d(int fd, struct char_session_data* sd) {
WFIFOB(fd,8) = sd->char_slots;
memset(WFIFOP(fd,9), 0, 20); // unused bytes
WFIFOSET(fd,29);
- mmo_char_send006b(fd,sd);
+ mmo_char_send006b(fd,sd);
}
//----------------------------------------
// Function to send characters to a player
@@ -2239,7 +2287,7 @@ void loginif_on_ready(void)
send_accounts_tologin(INVALID_TIMER, timer->gettick(), 0, 0);
// if no map-server already connected, display a message...
- ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map[0] );
+ ARR_FIND( 0, ARRAYLENGTH(server), i, server[i].fd > 0 && server[i].map );
if( i == ARRAYLENGTH(server) )
ShowStatus("Awaiting maps from map-server.\n");
}
@@ -3061,6 +3109,7 @@ int parse_frommap(int fd)
int count;
char* data;
+ memset(&scdata, 0, sizeof(scdata));
WFIFOHEAD(fd,14+50*sizeof(struct status_change_data));
WFIFOW(fd,0) = 0x2b1d;
WFIFOL(fd,4) = aid;
@@ -3232,7 +3281,6 @@ int parse_frommap(int fd)
{
int map_id, map_fd = -1;
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)
@@ -3240,6 +3288,7 @@ int parse_frommap(int 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.
+ struct mmo_charstatus char_dat;
mmo_char_fromsql(RFIFOL(fd,14), &char_dat, true);
char_data = (struct mmo_charstatus*)uidb_get(char_db_,RFIFOL(fd,14));
}
@@ -3690,11 +3739,12 @@ int parse_frommap(int fd)
node != NULL &&
node->account_id == account_id &&
node->char_id == char_id &&
- node->login_id1 == login_id1 &&
- node->sex == sex /*&&
+ node->login_id1 == login_id1 /*&&
+ node->sex == sex &&
node->ip == ip*/ )
{// auth ok
- cd->sex = sex;
+ if( cd->sex == 99 )
+ cd->sex = sex;
WFIFOHEAD(fd,25 + sizeof(struct mmo_charstatus));
WFIFOW(fd,0) = 0x2afd;
@@ -4279,7 +4329,7 @@ int parse_char(int fd)
}
#endif
- ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map[0] );
+ ARR_FIND( 0, ARRAYLENGTH(server), server_id, server[server_id].fd > 0 && server[server_id].map );
/* not available, tell it to wait (client wont close; char select will respawn).
* magic response found by Ind thanks to Yommy <3 */
if( server_id == ARRAYLENGTH(server) ) {
@@ -4330,7 +4380,8 @@ int parse_char(int fd)
//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( cd->sex == 99 )
+ cd->sex = sd->sex;
if (log_char) {
char esc_name[NAME_LENGTH*2+1];
@@ -4350,7 +4401,7 @@ int parse_char(int fd)
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] );
+ ARR_FIND( 0, ARRAYLENGTH(server), j, server[j].fd >= 0 && server[j].map );
if (j == ARRAYLENGTH(server)) {
ShowInfo("Connection Closed. No map servers available.\n");
WFIFOHEAD(fd,3);
@@ -4787,6 +4838,12 @@ int parse_char(int fd)
RFIFOSKIP(fd,10);
break;
+ case 0x9a1:
+ FIFOSD_CHECK(2);
+ mmo_char_send099d(fd, sd);
+ RFIFOSKIP(fd,2);
+ break;
+
/* 0x8d4 <from>.W <to>.W <unused>.W (2+2+2+2) */
case 0x8d4:
FIFOSD_CHECK(8);
@@ -5367,6 +5424,8 @@ int do_final(void) {
char_fd = -1;
}
+ HPM_char_do_final();
+
SQL->Free(sql_handle);
mapindex->final();
@@ -5374,6 +5433,8 @@ int do_final(void) {
if( server[i].map )
aFree(server[i].map);
+ HPM->event(HPET_POST_FINAL);
+
ShowStatus("Finished.\n");
return EXIT_SUCCESS;
}
@@ -5408,6 +5469,9 @@ void do_shutdown(void)
}
}
+void char_hp_symbols(void) {
+ HPM->share(sql_handle,"sql_handle");
+}
int do_init(int argc, char **argv) {
int i;
@@ -5418,6 +5482,29 @@ int do_init(int argc, char **argv) {
mapindex_defaults();
pincode_defaults();
+
+ HPM_char_do_init();
+ HPM->symbol_defaults_sub = char_hp_symbols;
+#if 0
+ /* TODO: Move to common code */
+ for( i = 1; i < argc; i++ ) {
+ const char* arg = argv[i];
+ if( strcmp(arg, "--load-plugin") == 0 ) {
+ if( map->arg_next_value(arg, i, argc, true) ) {
+ RECREATE(load_extras, char *, ++load_extras_count);
+ load_extras[load_extras_count-1] = argv[++i];
+ }
+ }
+ }
+ HPM->config_read((const char * const *)load_extras, load_extras_count);
+ if (load_extras) {
+ aFree(load_extras);
+ load_extras = NULL;
+ load_extras_count = 0;
+ }
+#endif
+ HPM->config_read(NULL, 0);
+ HPM->event(HPET_PRE_INIT);
//Read map indexes
mapindex->init();
@@ -5438,8 +5525,6 @@ int do_init(int argc, char **argv) {
auth_db = idb_alloc(DB_OPT_RELEASE_DATA);
online_char_db = idb_alloc(DB_OPT_RELEASE_DATA);
- HPM->share(sql_handle,"sql_handle");
- HPM->config_read(NULL, 0);
HPM->event(HPET_INIT);
mmo_char_sql_init();
diff --git a/src/char/char.h b/src/char/char.h
index 5a70d2ca7..4d053484b 100644
--- a/src/char/char.h
+++ b/src/char/char.h
@@ -14,8 +14,6 @@ enum E_CHARSERVER_ST {
CHARSERVER_ST_LAST
};
-struct mmo_charstatus;
-
struct char_session_data {
bool auth; // whether the session is authed or not
int account_id, login_id1, login_id2, sex;
diff --git a/src/char/int_mail.c b/src/char/int_mail.c
index 86a36d59f..47d2cc1c5 100644
--- a/src/char/int_mail.c
+++ b/src/char/int_mail.c
@@ -148,6 +148,7 @@ static bool mail_loadmessage(int mail_id, struct mail_message* msg)
{
int j;
StringBuf buf;
+ memset(msg, 0, sizeof(struct mail_message)); // Initialize data
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, "SELECT `id`,`send_name`,`send_id`,`dest_name`,`dest_id`,`title`,`message`,`time`,`status`,"
@@ -206,6 +207,7 @@ static bool mail_loadmessage(int mail_id, struct mail_message* msg)
static void mapif_Mail_sendinbox(int fd, int char_id, unsigned char flag)
{
struct mail_data md;
+ memset(&md, 0, sizeof(md));
mail_fromsql(char_id, &md);
//FIXME: dumping the whole structure like this is unsafe [ultramage]
@@ -262,6 +264,7 @@ static bool mail_DeleteAttach(int mail_id)
static void mapif_Mail_getattach(int fd, int char_id, int mail_id)
{
struct mail_message msg;
+ memset(&msg, 0, sizeof(msg));
if( !mail_loadmessage(mail_id, &msg) )
return;
diff --git a/src/char/int_storage.c b/src/char/int_storage.c
index 882d9b2a5..b9d9f2e2c 100644
--- a/src/char/int_storage.c
+++ b/src/char/int_storage.c
@@ -282,6 +282,7 @@ int mapif_parse_ItemBoundRetrieve_sub(int fd)
return 1;
}
+ memset(&item, 0, sizeof(item));
SQL->StmtBindColumn(stmt, 0, SQLDT_INT, &item.id, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 1, SQLDT_SHORT, &item.nameid, 0, NULL, NULL);
SQL->StmtBindColumn(stmt, 2, SQLDT_SHORT, &item.amount, 0, NULL, NULL);
diff --git a/src/char/inter.c b/src/char/inter.c
index e5a7d411c..df2920aa0 100644
--- a/src/char/inter.c
+++ b/src/char/inter.c
@@ -41,7 +41,7 @@ Sql* sql_handle = NULL;
int char_server_port = 3306;
char char_server_ip[32] = "127.0.0.1";
char char_server_id[32] = "ragnarok";
-char char_server_pw[32] = "ragnarok";
+char char_server_pw[100] = "ragnarok";
char char_server_db[32] = "ragnarok";
char default_codepage[32] = ""; //Feature by irmin.
@@ -483,19 +483,19 @@ void geoip_init(void) {
geoip.active = true;
db = fopen("./db/GeoIP.dat","rb");
- if( db == NULL ) {
+ if (db == NULL) {
ShowError("geoip_readdb: Error reading GeoIP.dat!\n");
geoip_final(false);
return;
}
fno = fileno(db);
- if( fstat(fno, &bufa) < 0 ) {
+ if (fstat(fno, &bufa) < 0) {
ShowError("geoip_readdb: Error stating GeoIP.dat! Error %d\n", errno);
geoip_final(false);
return;
}
geoip.cache = aMalloc( (sizeof(geoip.cache) * bufa.st_size) );
- if( fread(geoip.cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size ) {
+ if (fread(geoip.cache, sizeof(unsigned char), bufa.st_size, db) != bufa.st_size) {
ShowError("geoip_cache: Couldn't read all elements!\n");
fclose(db);
geoip_final(false);
@@ -504,10 +504,15 @@ void geoip_init(void) {
// Search database type
fseek(db, -3l, SEEK_END);
- for( i = 0; i < GEOIP_STRUCTURE_INFO_MAX_SIZE; i++ ) {
- fread(delim, sizeof(delim[0]), 3, db);
- if( delim[0] == 255 && delim[1] == 255 && delim[2] == 255 ) {
- fread(&db_type, sizeof(db_type), 1, db);
+ for (i = 0; i < GEOIP_STRUCTURE_INFO_MAX_SIZE; i++) {
+ if (fread(delim, sizeof(delim[0]), 3, db) != 3) {
+ db_type = 0;
+ break;
+ }
+ if (delim[0] == 255 && delim[1] == 255 && delim[2] == 255) {
+ if (fread(&db_type, sizeof(db_type), 1, db) != 1) {
+ db_type = 0;
+ }
break;
} else {
fseek(db, -4l, SEEK_CUR);
@@ -516,8 +521,8 @@ void geoip_init(void) {
fclose(db);
- if( db_type != 1 ) {
- if( db_type )
+ if (db_type != 1) {
+ if (db_type)
ShowError("geoip_init(): Database type is not supported %d!\n", db_type);
else
ShowError("geoip_init(): GeoIP is corrupted!\n");
diff --git a/src/common/HPM.c b/src/common/HPM.c
index f39954175..7a875d1c4 100644
--- a/src/common/HPM.c
+++ b/src/common/HPM.c
@@ -31,6 +31,13 @@
struct malloc_interface iMalloc_HPM;
struct malloc_interface *HPMiMalloc;
+/**
+ * (char*) data name -> (unsigned int) HPMDataCheck[] index
+ **/
+DBMap *datacheck_db;
+int datacheck_version;
+const struct s_HPMDataCheck *datacheck_data;
+
void hplugin_trigger_event(enum hp_event_types type) {
unsigned int i;
for( i = 0; i < HPM->plugin_count; i++ ) {
@@ -122,6 +129,7 @@ struct hplugin *hplugin_load(const char* filename) {
bool anyEvent = false;
void **import_symbol_ref;
Sql **sql_handle;
+ int *HPMDataCheckVer;
unsigned int *HPMDataCheckLen;
struct s_HPMDataCheck *HPMDataCheck;
@@ -217,13 +225,20 @@ struct hplugin *hplugin_load(const char* filename) {
return NULL;
}
+ if( !( HPMDataCheckVer = plugin_import(plugin->dll, "HPMDataCheckVer", int *) ) ) {
+ ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheckVer' for '"CL_WHITE"%s"CL_RESET"', most likely an outdated plugin, skipping...\n", filename);
+ HPM->unload(plugin);
+ return NULL;
+ }
+
if( !( HPMDataCheck = plugin_import(plugin->dll, "HPMDataCheck", struct s_HPMDataCheck *) ) ) {
ShowWarning("HPM:plugin_load: failed to retrieve 'HPMDataCheck' for '"CL_WHITE"%s"CL_RESET"', most likely not including HPMDataCheck.h, skipping...\n", filename);
HPM->unload(plugin);
return NULL;
}
- if( HPM->DataCheck && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,plugin->info->name) ) {
+ // TODO: Remove the HPM->DataCheck != NULL check once login and char support is complete
+ if (HPM->DataCheck != NULL && !HPM->DataCheck(HPMDataCheck,*HPMDataCheckLen,*HPMDataCheckVer,plugin->info->name)) {
ShowWarning("HPM:plugin_load: '"CL_WHITE"%s"CL_RESET"' failed DataCheck, out of sync from the core (recompile plugin), skipping...\n", filename);
HPM->unload(plugin);
return NULL;
@@ -282,12 +297,6 @@ void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_c
FILE *fp;
int i;
-// uncomment once login/char support is wrapped up
-// if( !HPM->DataCheck ) {
-// ShowError("HPM:config_read: HPM->DataCheck not set! Failure\n");
-// return;
-// }
-
/* yes its ugly, its temporary and will be gone as soon as the new inter-server.conf is set */
if( (fp = fopen("conf/import/plugins.conf","r")) ) {
config_filename = "conf/import/plugins.conf";
@@ -309,27 +318,40 @@ void hplugins_config_read(const char * const *extra_plugins, int extra_plugins_c
if (plist != NULL) {
int length = libconfig->setting_length(plist);
char filename[60];
- for(i = 0; i < length; i++) {
- if( !strcmpi(libconfig->setting_get_string_elem(plist,i),"HPMHooking") ) {//must load it first
+ char hooking_plugin_name[32];
+ const char *plugin_name_suffix = "";
+ if (SERVER_TYPE == SERVER_TYPE_LOGIN)
+ plugin_name_suffix = "_login";
+ else if (SERVER_TYPE == SERVER_TYPE_CHAR)
+ plugin_name_suffix = "_char";
+ else if (SERVER_TYPE == SERVER_TYPE_MAP)
+ plugin_name_suffix = "_map";
+ snprintf(hooking_plugin_name, sizeof(hooking_plugin_name), "HPMHooking%s", plugin_name_suffix);
+
+ for (i = 0; i < length; i++) {
+ const char *plugin_name = libconfig->setting_get_string_elem(plist,i);
+ if (strcmpi(plugin_name, "HPMHooking") == 0 || strcmpi(plugin_name, hooking_plugin_name) == 0) { //must load it first
struct hplugin *plugin;
- snprintf(filename, 60, "plugins/%s%s", libconfig->setting_get_string_elem(plist,i), DLL_EXT);
- if( ( plugin = HPM->load(filename) ) ) {
+ snprintf(filename, 60, "plugins/%s%s", hooking_plugin_name, DLL_EXT);
+ if ((plugin = HPM->load(filename))) {
bool (*func)(bool *fr);
bool (*addhook_sub) (enum HPluginHookType type, const char *target, void *hook, unsigned int pID);
- if( ( func = plugin_import(plugin->dll, "Hooked",bool (*)(bool *)) ) && ( addhook_sub = plugin_import(plugin->dll, "HPM_Plugin_AddHook",bool (*)(enum HPluginHookType, const char *, void *, unsigned int)) ) ) {
- if( func(&HPM->force_return) ) {
+ if ((func = plugin_import(plugin->dll, "Hooked",bool (*)(bool *)))
+ && (addhook_sub = plugin_import(plugin->dll, "HPM_Plugin_AddHook",bool (*)(enum HPluginHookType, const char *, void *, unsigned int)))) {
+ if (func(&HPM->force_return)) {
HPM->hooking = true;
HPM->addhook_sub = addhook_sub;
}
}
}
+ break;
}
}
- for(i = 0; i < length; i++) {
- if( strcmpi(libconfig->setting_get_string_elem(plist,i),"HPMHooking") ) {//now all others
- snprintf(filename, 60, "plugins/%s%s", libconfig->setting_get_string_elem(plist,i), DLL_EXT);
- HPM->load(filename);
- }
+ for (i = 0; i < length; i++) {
+ if (strncmpi(libconfig->setting_get_string_elem(plist,i),"HPMHooking", 10) == 0) // Already loaded, skip
+ continue;
+ snprintf(filename, 60, "plugins/%s%s", libconfig->setting_get_string_elem(plist,i), DLL_EXT);
+ HPM->load(filename);
}
libconfig->destroy(&plugins_conf);
}
@@ -688,6 +710,56 @@ bool hplugins_parse_conf(const char *w1, const char *w2, enum HPluginConfType po
return false;
}
+/**
+ * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching!
+ **/
+bool HPM_DataCheck(struct s_HPMDataCheck *src, unsigned int size, int version, char *name) {
+ unsigned int i, j;
+
+ if (version != datacheck_version) {
+ ShowError("HPMDataCheck:%s: DataCheck API version mismatch %d != %d\n", name, datacheck_version, version);
+ return false;
+ }
+
+ for (i = 0; i < size; i++) {
+ if (!(src[i].type|SERVER_TYPE))
+ continue;
+
+ if (!strdb_exists(datacheck_db, src[i].name)) {
+ ShowError("HPMDataCheck:%s: '%s' was not found\n",name,src[i].name);
+ return false;
+ } else {
+ j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */
+ if (src[i].size != datacheck_data[j].size) {
+ ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,datacheck_data[j].size);
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void HPM_datacheck_init(const struct s_HPMDataCheck *src, unsigned int length, int version) {
+ unsigned int i;
+
+ datacheck_version = version;
+ datacheck_data = src;
+
+ /**
+ * Populates datacheck_db for easy lookup later on
+ **/
+ datacheck_db = strdb_alloc(DB_OPT_BASE,0);
+
+ for(i = 0; i < length; i++) {
+ strdb_uiput(datacheck_db, src[i].name, i);
+ }
+}
+
+void HPM_datacheck_final(void) {
+ db_destroy(datacheck_db);
+}
+
void hplugins_share_defaults(void) {
/* console */
#ifdef CONSOLE_INPUT
@@ -729,6 +801,9 @@ void hplugins_share_defaults(void) {
void hpm_init(void) {
unsigned int i;
+ datacheck_db = NULL;
+ datacheck_data = NULL;
+ datacheck_version = 0;
HPM->symbols = NULL;
HPM->plugins = NULL;
@@ -866,5 +941,7 @@ void hpm_defaults(void) {
HPM->grabHPData = hplugins_grabHPData;
HPM->grabHPDataSub = NULL;
HPM->parseConf = hplugins_parse_conf;
- HPM->DataCheck = NULL;
+ HPM->DataCheck = HPM_DataCheck;
+ HPM->datacheck_init = HPM_datacheck_init;
+ HPM->datacheck_final = HPM_datacheck_final;
}
diff --git a/src/common/HPM.h b/src/common/HPM.h
index fe8d45066..a4ea504e6 100644
--- a/src/common/HPM.h
+++ b/src/common/HPM.h
@@ -151,7 +151,9 @@ struct HPM_interface {
/* for custom config parsing */
bool (*parseConf) (const char *w1, const char *w2, enum HPluginConfType point);
/* validates plugin data */
- bool (*DataCheck) (struct s_HPMDataCheck *src, unsigned int size, char *name);
+ bool (*DataCheck) (struct s_HPMDataCheck *src, unsigned int size, int version, char *name);
+ void (*datacheck_init) (const struct s_HPMDataCheck *src, unsigned int length, int version);
+ void (*datacheck_final) (void);
} HPM_s;
struct HPM_interface *HPM;
diff --git a/src/common/HPMDataCheck.h b/src/common/HPMDataCheck.h
index 79ec36472..9f4316617 100644
--- a/src/common/HPMDataCheck.h
+++ b/src/common/HPMDataCheck.h
@@ -9,134 +9,135 @@
HPExport const struct s_HPMDataCheck HPMDataCheck[] = {
#ifdef COMMON_CONF_H
- { "libconfig_interface", sizeof(struct libconfig_interface) },
+ { "libconfig_interface", sizeof(struct libconfig_interface), SERVER_TYPE_ALL },
#else
#define COMMON_CONF_H
#endif // COMMON_CONF_H
#ifdef COMMON_DB_H
- { "DBData", sizeof(struct DBData) },
- { "DBIterator", sizeof(struct DBIterator) },
- { "DBMap", sizeof(struct DBMap) },
+ { "DBData", sizeof(struct DBData), SERVER_TYPE_ALL },
+ { "DBIterator", sizeof(struct DBIterator), SERVER_TYPE_ALL },
+ { "DBMap", sizeof(struct DBMap), SERVER_TYPE_ALL },
#else
#define COMMON_DB_H
#endif // COMMON_DB_H
#ifdef COMMON_DES_H
- { "BIT64", sizeof(struct BIT64) },
+ { "BIT64", sizeof(struct BIT64), SERVER_TYPE_ALL },
#else
#define COMMON_DES_H
#endif // COMMON_DES_H
#ifdef COMMON_ERS_H
- { "eri", sizeof(struct eri) },
+ { "eri", sizeof(struct eri), SERVER_TYPE_ALL },
#else
#define COMMON_ERS_H
#endif // COMMON_ERS_H
#ifdef COMMON_MAPINDEX_H
- { "mapindex_interface", sizeof(struct mapindex_interface) },
+ { "mapindex_interface", sizeof(struct mapindex_interface), SERVER_TYPE_ALL },
#else
#define COMMON_MAPINDEX_H
#endif // COMMON_MAPINDEX_H
#ifdef COMMON_MMO_H
- { "quest", sizeof(struct quest) },
+ { "quest", sizeof(struct quest), SERVER_TYPE_ALL },
#else
#define COMMON_MMO_H
#endif // COMMON_MMO_H
#ifdef COMMON_SOCKET_H
- { "socket_interface", sizeof(struct socket_interface) },
+ { "socket_interface", sizeof(struct socket_interface), SERVER_TYPE_ALL },
#else
#define COMMON_SOCKET_H
#endif // COMMON_SOCKET_H
#ifdef COMMON_STRLIB_H
- { "StringBuf", sizeof(struct StringBuf) },
- { "s_svstate", sizeof(struct s_svstate) },
+ { "StringBuf", sizeof(struct StringBuf), SERVER_TYPE_ALL },
+ { "s_svstate", sizeof(struct s_svstate), SERVER_TYPE_ALL },
#else
#define COMMON_STRLIB_H
#endif // COMMON_STRLIB_H
#ifdef COMMON_SYSINFO_H
- { "sysinfo_interface", sizeof(struct sysinfo_interface) },
+ { "sysinfo_interface", sizeof(struct sysinfo_interface), SERVER_TYPE_ALL },
#else
#define COMMON_SYSINFO_H
#endif // COMMON_SYSINFO_H
#ifdef MAP_ATCOMMAND_H
- { "AliasInfo", sizeof(struct AliasInfo) },
- { "atcommand_interface", sizeof(struct atcommand_interface) },
+ { "AliasInfo", sizeof(struct AliasInfo), SERVER_TYPE_MAP },
+ { "atcommand_interface", sizeof(struct atcommand_interface), SERVER_TYPE_MAP },
#else
#define MAP_ATCOMMAND_H
#endif // MAP_ATCOMMAND_H
#ifdef MAP_BATTLE_H
- { "Damage", sizeof(struct Damage) },
- { "battle_interface", sizeof(struct battle_interface) },
+ { "Damage", sizeof(struct Damage), SERVER_TYPE_MAP },
+ { "battle_interface", sizeof(struct battle_interface), SERVER_TYPE_MAP },
#else
#define MAP_BATTLE_H
#endif // MAP_BATTLE_H
#ifdef MAP_BUYINGSTORE_H
- { "buyingstore_interface", sizeof(struct buyingstore_interface) },
- { "s_buyingstore_item", sizeof(struct s_buyingstore_item) },
+ { "buyingstore_interface", sizeof(struct buyingstore_interface), SERVER_TYPE_MAP },
+ { "s_buyingstore_item", sizeof(struct s_buyingstore_item), SERVER_TYPE_MAP },
#else
#define MAP_BUYINGSTORE_H
#endif // MAP_BUYINGSTORE_H
#ifdef MAP_CHRIF_H
- { "auth_node", sizeof(struct auth_node) },
+ { "auth_node", sizeof(struct auth_node), SERVER_TYPE_MAP },
#else
#define MAP_CHRIF_H
#endif // MAP_CHRIF_H
#ifdef MAP_CLIF_H
- { "clif_interface", sizeof(struct clif_interface) },
+ { "clif_interface", sizeof(struct clif_interface), SERVER_TYPE_MAP },
#else
#define MAP_CLIF_H
#endif // MAP_CLIF_H
#ifdef MAP_ELEMENTAL_H
- { "elemental_skill", sizeof(struct elemental_skill) },
+ { "elemental_skill", sizeof(struct elemental_skill), SERVER_TYPE_MAP },
#else
#define MAP_ELEMENTAL_H
#endif // MAP_ELEMENTAL_H
#ifdef MAP_GUILD_H
- { "eventlist", sizeof(struct eventlist) },
- { "guardian_data", sizeof(struct guardian_data) },
+ { "eventlist", sizeof(struct eventlist), SERVER_TYPE_MAP },
+ { "guardian_data", sizeof(struct guardian_data), SERVER_TYPE_MAP },
#else
#define MAP_GUILD_H
#endif // MAP_GUILD_H
#ifdef MAP_MAPREG_H
- { "mapreg_save", sizeof(struct mapreg_save) },
+ { "mapreg_save", sizeof(struct mapreg_save), SERVER_TYPE_MAP },
#else
#define MAP_MAPREG_H
#endif // MAP_MAPREG_H
#ifdef MAP_MAP_H
- { "map_data_other_server", sizeof(struct map_data_other_server) },
+ { "map_data_other_server", sizeof(struct map_data_other_server), SERVER_TYPE_MAP },
#else
#define MAP_MAP_H
#endif // MAP_MAP_H
#ifdef MAP_PACKETS_STRUCT_H
- { "EQUIPSLOTINFO", sizeof(struct EQUIPSLOTINFO) },
+ { "EQUIPSLOTINFO", sizeof(struct EQUIPSLOTINFO), SERVER_TYPE_MAP },
#else
#define MAP_PACKETS_STRUCT_H
#endif // MAP_PACKETS_STRUCT_H
#ifdef MAP_PC_H
- { "autotrade_vending", sizeof(struct autotrade_vending) },
- { "item_cd", sizeof(struct item_cd) },
+ { "autotrade_vending", sizeof(struct autotrade_vending), SERVER_TYPE_MAP },
+ { "item_cd", sizeof(struct item_cd), SERVER_TYPE_MAP },
#else
#define MAP_PC_H
#endif // MAP_PC_H
#ifdef MAP_SCRIPT_H
- { "Script_Config", sizeof(struct Script_Config) },
- { "reg_db", sizeof(struct reg_db) },
- { "script_interface", sizeof(struct script_interface) },
+ { "Script_Config", sizeof(struct Script_Config), SERVER_TYPE_MAP },
+ { "reg_db", sizeof(struct reg_db), SERVER_TYPE_MAP },
+ { "script_interface", sizeof(struct script_interface), SERVER_TYPE_MAP },
#else
#define MAP_SCRIPT_H
#endif // MAP_SCRIPT_H
#ifdef MAP_SEARCHSTORE_H
- { "searchstore_interface", sizeof(struct searchstore_interface) },
+ { "searchstore_interface", sizeof(struct searchstore_interface), SERVER_TYPE_MAP },
#else
#define MAP_SEARCHSTORE_H
#endif // MAP_SEARCHSTORE_H
#ifdef MAP_SKILL_H
- { "skill_cd", sizeof(struct skill_cd) },
- { "skill_condition", sizeof(struct skill_condition) },
- { "skill_interface", sizeof(struct skill_interface) },
- { "skill_unit_save", sizeof(struct skill_unit_save) },
+ { "skill_cd", sizeof(struct skill_cd), SERVER_TYPE_MAP },
+ { "skill_condition", sizeof(struct skill_condition), SERVER_TYPE_MAP },
+ { "skill_interface", sizeof(struct skill_interface), SERVER_TYPE_MAP },
+ { "skill_unit_save", sizeof(struct skill_unit_save), SERVER_TYPE_MAP },
#else
#define MAP_SKILL_H
#endif // MAP_SKILL_H
};
HPExport unsigned int HPMDataCheckLen = ARRAYLENGTH(HPMDataCheck);
+HPExport int HPMDataCheckVer = 1;
#endif /* HPM_DATA_CHECK_H */
diff --git a/src/common/HPMi.h b/src/common/HPMi.h
index 478cfbdd9..485586f6f 100644
--- a/src/common/HPMi.h
+++ b/src/common/HPMi.h
@@ -36,6 +36,7 @@ struct hplugin_info {
struct s_HPMDataCheck {
char *name;
unsigned int size;
+ int type;
};
HPExport void *(*import_symbol) (char *name, unsigned int pID);
diff --git a/src/common/db.h b/src/common/db.h
index bf59e37d6..f807188eb 100644
--- a/src/common/db.h
+++ b/src/common/db.h
@@ -1347,6 +1347,7 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...);
/////////////////////////////////////////////////////////////////////
// Binary heap library based on defines. (uses the vector defines above)
// uses aMalloc, aRealloc, aFree
+// WARNING: BHEAP implementation details affect behaviour of A* pathfinding
@@ -1459,6 +1460,21 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...);
+/// See BHEAP_PUSH. Version used by A* implementation, matching client bheap.
+///
+/// @param __heap Binary heap
+/// @param __val Value
+/// @param __topcmp Comparator
+/// @param __swp Swapper
+#define BHEAP_PUSH2(__heap,__val,__topcmp,__swp) \
+ do{ \
+ size_t _i_ = VECTOR_LENGTH(__heap); \
+ VECTOR_PUSH(__heap,__val); /* insert at end */ \
+ BHEAP_SIFTDOWN(__heap,0,_i_,__topcmp,__swp); \
+ }while(0)
+
+
+
/// Removes the top value of the heap. (using the '=' operator)
/// Assumes the heap is not empty.
///
@@ -1474,6 +1490,21 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...);
+/// See BHEAP_POP. Version used by A* implementation, matching client bheap.
+///
+/// @param __heap Binary heap
+/// @param __topcmp Comparator
+/// @param __swp Swapper
+#define BHEAP_POP2(__heap,__topcmp,__swp) \
+ do{ \
+ VECTOR_INDEX(__heap,0) = VECTOR_POP(__heap); /* put last at index */ \
+ if( !VECTOR_LENGTH(__heap) ) /* removed last, nothing to do */ \
+ break; \
+ BHEAP_SIFTUP(__heap,0,__topcmp,__swp); \
+ }while(0)
+
+
+
/// Removes the target value of the heap. (using the '=' operator)
/// Assumes the index exists.
///
@@ -1522,6 +1553,74 @@ void linkdb_foreach (struct linkdb_node** head, LinkDBFunc func, ...);
+/// Follow path up towards (but not all the way to) the root, swapping nodes until finding
+/// a place where the new item that was placed at __idx fits.
+/// Only goes as high as __startidx (usually 0).
+///
+/// @param __heap Binary heap
+/// @param __startidx Index of an ancestor of __idx
+/// @param __idx Index of an inserted element
+/// @param __topcmp Comparator
+/// @param __swp Swapper
+#define BHEAP_SIFTDOWN(__heap,__startidx,__idx,__topcmp,__swp) \
+ do{ \
+ size_t _i2_ = __idx; \
+ while( _i2_ > __startidx ) \
+ { /* restore heap property in parents */ \
+ size_t _parent_ = (_i2_-1)/2; \
+ if( __topcmp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i2_)) <= 0 ) \
+ break; /* done */ \
+ __swp(VECTOR_INDEX(__heap,_parent_),VECTOR_INDEX(__heap,_i2_)); \
+ _i2_ = _parent_; \
+ } \
+ }while(0)
+
+
+
+/// Repeatedly swap the smaller child with parent, after placing a new item at __idx.
+///
+/// @param __heap Binary heap
+/// @param __idx Index of an inserted element
+/// @param __topcmp Comparator
+/// @param __swp Swapper
+#define BHEAP_SIFTUP(__heap,__idx,__topcmp,__swp) \
+ do{ \
+ size_t _i_ = __idx; \
+ size_t _lchild_ = _i_*2 + 1; \
+ while( _lchild_ < VECTOR_LENGTH(__heap) ) \
+ { /* restore heap property in childs */ \
+ size_t _rchild_ = _i_*2 + 2; \
+ if( _rchild_ >= VECTOR_LENGTH(__heap) || __topcmp(VECTOR_INDEX(__heap,_lchild_),VECTOR_INDEX(__heap,_rchild_)) < 0 ) \
+ { /* left child */ \
+ __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_lchild_)); \
+ _i_ = _lchild_; \
+ } \
+ else \
+ { /* right child */ \
+ __swp(VECTOR_INDEX(__heap,_i_),VECTOR_INDEX(__heap,_rchild_)); \
+ _i_ = _rchild_; \
+ } \
+ _lchild_ = _i_*2 + 1; \
+ } \
+ BHEAP_SIFTDOWN(__heap,__idx,_i_,__topcmp,__swp); \
+ }while(0)
+
+
+
+/// Call this after modifying the item at __idx__ to restore the heap
+///
+/// @param __heap Binary heap
+/// @param __idx Index
+/// @param __topcmp Comparator
+/// @param __swp Swapper
+#define BHEAP_UPDATE(__heap,__idx,__topcmp,__swp) \
+ do{ \
+ BHEAP_SIFTDOWN(__heap,0,__idx,__topcmp,__swp); \
+ BHEAP_SIFTUP(__heap,__idx,__topcmp,__swp); \
+ }while(0)
+
+
+
/// Clears the binary heap, freeing allocated data.
///
/// @param __heap Binary heap
diff --git a/src/common/mmo.h b/src/common/mmo.h
index ff7c1da28..597b25126 100644
--- a/src/common/mmo.h
+++ b/src/common/mmo.h
@@ -49,7 +49,7 @@
// 20120307 - 2012-03-07aRagexeRE+ - 0x970
#ifndef PACKETVER
- #define PACKETVER 20131223
+ #define PACKETVER 20141022
#endif // PACKETVER
//Uncomment the following line if your client is ragexeRE instead of ragexe (required because of conflicting packets in ragexe vs ragexeRE).
diff --git a/src/common/socket.c b/src/common/socket.c
index 0c48c7c46..c57cba32d 100644
--- a/src/common/socket.c
+++ b/src/common/socket.c
@@ -744,13 +744,6 @@ int WFIFOSET(int fd, size_t len)
return 0;
}
- if (s->wdata_size+len > WFIFO_MAX) { // reached maximum write fifo size
- ShowError("WFIFOSET: Maximum write buffer size for client connection %d exceeded, most likely caused by packet 0x%04x (len=%"PRIuS", ip=%u.%u.%u.%u).\n",
- fd, WFIFOW(fd,0), len, CONVIP(s->client_addr));
- set_eof(fd);
- return 0;
- }
-
}
s->wdata_size += len;
#ifdef SHOW_SERVER_STATS
diff --git a/src/config/core.h b/src/config/core.h
index ac59563b5..da9296bda 100644
--- a/src/config/core.h
+++ b/src/config/core.h
@@ -35,15 +35,16 @@
//#define STATS_OPT_OUT
/// Uncomment to enable the Cell Stack Limit mod.
-/// It's only config is the battle_config cell_stack_limit.
-/// Only chars affected are those defined in BL_CHAR (mobs and players currently)
+/// It's only config is the battle_config custom_cell_stack_limit.
+/// Only chars affected are those defined in BL_CHAR
//#define CELL_NOSTACK
/// Uncomment to enable circular area checks.
-/// By default, all range checks in Aegis are of Square shapes, so a weapon range
-/// - of 10 allows you to attack from anywhere within a 21x21 area.
-/// Enabling this changes such checks to circular checks, which is more realistic,
-/// - but is not the official behavior.
+/// By default, most server-sided range checks in Aegis are of square shapes, so a monster
+/// with a range of 4 can attack anything within a 9x9 area.
+/// Client-sided range checks are, however, are always circular.
+/// Enabling this changes all checks to circular checks, which is more realistic,
+/// - but is not the official behaviour.
//#define CIRCULAR_AREA
//This is the distance at which @autoloot works,
diff --git a/src/login/HPMlogin.c b/src/login/HPMlogin.c
new file mode 100644
index 000000000..6b223d249
--- /dev/null
+++ b/src/login/HPMlogin.c
@@ -0,0 +1,53 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#define HERCULES_CORE
+
+#include "HPMlogin.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "../common/HPM.h"
+#include "../common/cbasetypes.h"
+#include "../common/conf.h"
+#include "../common/db.h"
+#include "../common/des.h"
+#include "../common/ers.h"
+#include "../common/malloc.h"
+#include "../common/mapindex.h"
+#include "../common/mmo.h"
+#include "../common/showmsg.h"
+#include "../common/socket.h"
+#include "../common/strlib.h"
+#include "../common/sysinfo.h"
+
+#include "../common/HPMDataCheck.h"
+
+bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
+ /* record address */
+ switch( type ) {
+ default:
+ return false;
+ }
+ return true;
+}
+
+void HPM_login_plugin_load_sub(struct hplugin *plugin) {
+}
+
+void HPM_login_do_init(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+ HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
+#else
+ HPM->DataCheck = NULL;
+#endif
+}
+
+void HPM_login_do_final(void) {
+#if 0 // TODO (HPMDataCheck is disabled for the time being)
+ HPM->datacheck_final();
+#endif
+}
diff --git a/src/login/HPMlogin.h b/src/login/HPMlogin.h
new file mode 100644
index 000000000..6bdc0fb7b
--- /dev/null
+++ b/src/login/HPMlogin.h
@@ -0,0 +1,20 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+
+#ifndef LOGIN_HPMLOGIN_H
+#define LOGIN_HPMLOGIN_H
+
+#include "../common/cbasetypes.h"
+#include "../common/HPM.h"
+
+struct hplugin;
+
+bool HPM_login_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr);
+
+void HPM_login_plugin_load_sub(struct hplugin *plugin);
+
+void HPM_login_do_final(void);
+
+void HPM_login_do_init(void);
+
+#endif /* LOGIN_HPMLOGIN_H */
diff --git a/src/login/Makefile.in b/src/login/Makefile.in
index 7551eed5f..9b1db69c2 100644
--- a/src/login/Makefile.in
+++ b/src/login/Makefile.in
@@ -22,9 +22,9 @@ MT19937AR_OBJ = $(MT19937AR_D)/mt19937ar.o
MT19937AR_H = $(MT19937AR_D)/mt19937ar.h
MT19937AR_INCLUDE = -I$(MT19937AR_D)
-LOGIN_C = account_sql.c ipban_sql.c login.c loginlog_sql.c
+LOGIN_C = account_sql.c HPMlogin.c ipban_sql.c login.c loginlog_sql.c
LOGIN_OBJ = $(addprefix obj_sql/, $(patsubst %.c,%.o,$(LOGIN_C)))
-LOGIN_H = login.h account.h ipban.h loginlog.h
+LOGIN_H = login.h account.h HPMlogin.h ipban.h loginlog.h
HAVE_MYSQL=@HAVE_MYSQL@
ifeq ($(HAVE_MYSQL),yes)
@@ -87,7 +87,7 @@ login-server: ../../login-server@EXEEXT@
../../login-server@EXEEXT@: $(LOGIN_SERVER_SQL_DEPENDS) Makefile
@echo " LD $(notdir $@)"
- @$(CC) @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
+ @$(CC) @STATIC@ @LDFLAGS@ -o ../../login-server@EXEEXT@ $(LOGIN_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
$(COMMON_D)/obj_all/common.a $(MT19937AR_OBJ) $(LIBCONFIG_OBJ) @LIBS@ @MYSQL_LIBS@
# login object files
diff --git a/src/login/account_sql.c b/src/login/account_sql.c
index 51e499369..5f9357c81 100644
--- a/src/login/account_sql.c
+++ b/src/login/account_sql.c
@@ -33,14 +33,14 @@ typedef struct AccountDB_SQL
char global_db_hostname[32];
uint16 global_db_port;
char global_db_username[32];
- char global_db_password[32];
+ char global_db_password[100];
char global_db_database[32];
char global_codepage[32];
// local sql settings
char db_hostname[32];
uint16 db_port;
char db_username[32];
- char db_password[32];
+ char db_password[100];
char db_database[32];
char codepage[32];
// other settings
@@ -169,6 +169,10 @@ static bool account_db_sql_init(AccountDB* self)
if( codepage[0] != '\0' && SQL_ERROR == SQL->SetEncoding(sql_handle, codepage) )
Sql_ShowDebug(sql_handle);
+ Sql_HerculesUpdateCheck(db->accounts);
+#ifdef CONSOLE_INPUT
+ console->input->setSQL(db->accounts);
+#endif
return true;
}
@@ -655,11 +659,7 @@ static bool mmo_auth_tosql(AccountDB_SQL* db, const struct mmo_account* acc, boo
Sql* account_db_sql_up(AccountDB* self) {
AccountDB_SQL* db = (AccountDB_SQL*)self;
- Sql_HerculesUpdateCheck(db->accounts);
-#ifdef CONSOLE_INPUT
- console->input->setSQL(db->accounts);
-#endif
- return db->accounts;
+ return db ? db->accounts : NULL;
}
void mmo_save_accreg2(AccountDB* self, int fd, int account_id, int char_id) {
Sql* sql_handle = ((AccountDB_SQL*)self)->accounts;
diff --git a/src/login/ipban_sql.c b/src/login/ipban_sql.c
index 081f28d84..82512b0f0 100644
--- a/src/login/ipban_sql.c
+++ b/src/login/ipban_sql.c
@@ -23,14 +23,14 @@
static char global_db_hostname[32] = "127.0.0.1";
static uint16 global_db_port = 3306;
static char global_db_username[32] = "ragnarok";
-static char global_db_password[32] = "ragnarok";
+static char global_db_password[100] = "ragnarok";
static char global_db_database[32] = "ragnarok";
static char global_codepage[32] = "";
// local sql settings
static char ipban_db_hostname[32] = "";
static uint16 ipban_db_port = 0;
static char ipban_db_username[32] = "";
-static char ipban_db_password[32] = "";
+static char ipban_db_password[100] = "";
static char ipban_db_database[32] = "";
static char ipban_codepage[32] = "";
static char ipban_table[32] = "ipbanlist";
diff --git a/src/login/login.c b/src/login/login.c
index 828afb22b..9aa2e778b 100644
--- a/src/login/login.c
+++ b/src/login/login.c
@@ -10,6 +10,7 @@
#include <stdlib.h>
#include <string.h>
+#include "HPMlogin.h"
#include "account.h"
#include "ipban.h"
#include "loginlog.h"
@@ -1651,6 +1652,7 @@ int login_config_read(const char* cfgName)
else if(!strcmpi(w1, "client_hash")) {
int group = 0;
char md5[33];
+ memset(md5, '\0', 33);
if (sscanf(w2, "%d, %32s", &group, md5) == 2) {
struct client_hash_node *nnode;
@@ -1736,6 +1738,10 @@ int do_final(void) {
login_fd = -1;
}
+ HPM_login_do_final();
+
+ HPM->event(HPET_POST_FINAL);
+
ShowStatus("Finished.\n");
return EXIT_SUCCESS;
}
@@ -1769,6 +1775,9 @@ void do_shutdown(void)
}
}
+void login_hp_symbols(void) {
+ HPM->share(account_db_sql_up(accounts),"sql_handle");
+}
//------------------------------
// Login server initialization
@@ -1779,9 +1788,38 @@ int do_init(int argc, char** argv)
// initialize engine (to accept config settings)
account_engine[0].db = account_engine[0].constructor();
+ accounts = account_engine[0].db;
+ if( accounts == NULL ) {
+ ShowFatalError("do_init: account engine 'sql' not found.\n");
+ exit(EXIT_FAILURE);
+ }
// read login-server configuration
login_set_defaults();
+
+ HPM_login_do_init();
+ HPM->symbol_defaults_sub = login_hp_symbols;
+ HPM->config_read(NULL, 0);
+#if 0
+ /* TODO: Move to common code */
+ for( i = 1; i < argc; i++ ) {
+ const char* arg = argv[i];
+ if( strcmp(arg, "--load-plugin") == 0 ) {
+ if( map->arg_next_value(arg, i, argc, true) ) {
+ RECREATE(load_extras, char *, ++load_extras_count);
+ load_extras[load_extras_count-1] = argv[++i];
+ }
+ }
+ }
+ HPM->config_read((const char * const *)load_extras, load_extras_count);
+ if (load_extras) {
+ aFree(load_extras);
+ load_extras = NULL;
+ load_extras_count = 0;
+ }
+#endif
+ HPM->event(HPET_PRE_INIT);
+
login_config_read((argc > 1) ? argv[1] : LOGIN_CONF_NAME);
login_lan_config_read((argc > 2) ? argv[2] : LAN_CONF_NAME);
@@ -1816,20 +1854,11 @@ int do_init(int argc, char** argv)
}
// Account database init
- accounts = account_engine[0].db;
- if( accounts == NULL ) {
- ShowFatalError("do_init: account engine 'sql' not found.\n");
+ if(!accounts->init(accounts)) {
+ ShowFatalError("do_init: Failed to initialize account engine 'sql'.\n");
exit(EXIT_FAILURE);
- } else {
-
- if(!accounts->init(accounts)) {
- ShowFatalError("do_init: Failed to initialize account engine 'sql'.\n");
- exit(EXIT_FAILURE);
- }
}
- HPM->share(account_db_sql_up(accounts),"sql_handle");
- HPM->config_read(NULL, 0);
HPM->event(HPET_INIT);
// server port open & binding
diff --git a/src/login/loginlog_sql.c b/src/login/loginlog_sql.c
index 2c0b1cc03..5654b4c5b 100644
--- a/src/login/loginlog_sql.c
+++ b/src/login/loginlog_sql.c
@@ -19,14 +19,14 @@
static char global_db_hostname[32] = "127.0.0.1";
static uint16 global_db_port = 3306;
static char global_db_username[32] = "ragnarok";
-static char global_db_password[32] = "ragnarok";
+static char global_db_password[100] = "ragnarok";
static char global_db_database[32] = "ragnarok";
static char global_codepage[32] = "";
// local sql settings
static char log_db_hostname[32] = "";
static uint16 log_db_port = 0;
static char log_db_username[32] = "";
-static char log_db_password[32] = "";
+static char log_db_password[100] = "";
static char log_db_database[32] = "";
static char log_codepage[32] = "";
static char log_login_db[256] = "loginlog";
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c
index cb8c979c6..a0701ae45 100644
--- a/src/map/HPMmap.c
+++ b/src/map/HPMmap.c
@@ -74,11 +74,6 @@ struct HPM_atcommand_list {
struct HPM_atcommand_list *atcommand_list = NULL;
unsigned int atcommand_list_items = 0;
-/**
- * (char*) data name -> (unsigned int) HPMDataCheck[] index
- **/
-DBMap *datacheck_db;
-
bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataTypes type, void *ptr) {
/* record address */
switch( type ) {
@@ -147,29 +142,6 @@ void HPM_map_atcommands(void) {
}
/**
- * Called by HPM->DataCheck on a plugins incoming data, ensures data structs in use are matching!
- **/
-bool HPM_map_DataCheck (struct s_HPMDataCheck *src, unsigned int size, char *name) {
- unsigned int i, j;
-
- for(i = 0; i < size; i++) {
-
- if( !strdb_exists(datacheck_db, src[i].name) ) {
- ShowError("HPMDataCheck:%s: '%s' was not found\n",name,src[i].name);
- return false;
- } else {
- j = strdb_uiget(datacheck_db, src[i].name);/* not double lookup; exists sets cache to found data */
- if( src[i].size != HPMDataCheck[j].size ) {
- ShowWarning("HPMDataCheck:%s: '%s' size mismatch %u != %u\n",name,src[i].name,src[i].size,HPMDataCheck[j].size);
- return false;
- }
- }
- }
-
- return true;
-}
-
-/**
* Adds a new group permission to the HPM-provided list
**/
void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask) {
@@ -183,17 +155,9 @@ void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned in
}
void HPM_map_do_init(void) {
- unsigned int i;
-
- /**
- * Populates datacheck_db for easy lookup later on
- **/
- datacheck_db = strdb_alloc(DB_OPT_BASE,0);
-
- for(i = 0; i < HPMDataCheckLen; i++) {
- strdb_uiput(datacheck_db, HPMDataCheck[i].name, i);
- }
-
+ HPM->load_sub = HPM_map_plugin_load_sub;
+ HPM->grabHPDataSub = HPM_map_grabHPData;
+ HPM->datacheck_init(HPMDataCheck, HPMDataCheckLen, HPMDataCheckVer);
}
void HPM_map_do_final(void) {
@@ -211,5 +175,5 @@ void HPM_map_do_final(void) {
if( pcg->HPMpermissions )
aFree(pcg->HPMpermissions);
- db_destroy(datacheck_db);
+ HPM->datacheck_final();
}
diff --git a/src/map/HPMmap.h b/src/map/HPMmap.h
index 99c4224ff..fa2f625c0 100644
--- a/src/map/HPMmap.h
+++ b/src/map/HPMmap.h
@@ -22,8 +22,6 @@ void HPM_map_do_final(void);
void HPM_map_add_group_permission(unsigned int pluginID, char *name, unsigned int *mask);
-bool HPM_map_DataCheck(struct s_HPMDataCheck *src, unsigned int size, char *name);
-
void HPM_map_do_init(void);
#endif /* MAP_HPMMAP_H */
diff --git a/src/map/Makefile.in b/src/map/Makefile.in
index fc58c9d70..ee8b7ac56 100644
--- a/src/map/Makefile.in
+++ b/src/map/Makefile.in
@@ -104,7 +104,7 @@ map-server: ../../map-server@EXEEXT@
../../map-server@EXEEXT@: $(MAP_SERVER_SQL_DEPENDS) Makefile
@echo " LD $(notdir $@)"
- @$(CC) @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
+ @$(CC) @STATIC@ @LDFLAGS@ -o ../../map-server@EXEEXT@ $(MAP_OBJ) $(COMMON_D)/obj_sql/common_sql.a \
$(COMMON_D)/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 497e46520..ef528c454 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -583,7 +583,7 @@ ACMD(who) {
iter = mapit_getallusers();
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 (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || pc_isinvisible(pl_sd)) && 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;
@@ -689,7 +689,7 @@ ACMD(whogm)
continue;
}
if (pl_level > level) {
- if (pl_sd->sc.option & OPTION_INVISIBLE)
+ if (pc_isinvisible(pl_sd))
continue;
sprintf(atcmd_output, msg_txt(913), pl_sd->status.name); // Name: %s (GM)
clif->message(fd, atcmd_output);
@@ -889,7 +889,7 @@ ACMD(option)
*
*------------------------------------------*/
ACMD(hide) {
- if (sd->sc.option & OPTION_INVISIBLE) {
+ if (pc_isinvisible(sd)) {
sd->sc.option &= ~OPTION_INVISIBLE;
if (sd->disguise != -1 )
status->set_viewdata(&sd->bl, sd->disguise);
@@ -3923,12 +3923,12 @@ ACMD(mount_peco)
clif->message(fd, atcmd_output);
return false;
}
- if( !(sd->sc.option&OPTION_DRAGON1) ) {
+ if (!pc_isridingdragon(sd)) {
clif->message(sd->fd,msg_txt(1119)); // You have mounted your Dragon.
- pc->setoption(sd, sd->sc.option|OPTION_DRAGON1);
+ pc->setridingdragon(sd, OPTION_DRAGON1);
} else {
clif->message(sd->fd,msg_txt(1120)); // You have released your Dragon.
- pc->setoption(sd, sd->sc.option&~OPTION_DRAGON1);
+ pc->setridingdragon(sd, 0);
}
return true;
}
@@ -3940,34 +3940,34 @@ ACMD(mount_peco)
}
if( !pc_isridingwug(sd) ) {
clif->message(sd->fd,msg_txt(1121)); // You have mounted your Warg.
- pc->setoption(sd, sd->sc.option|OPTION_WUGRIDER);
+ pc->setridingwug(sd, true);
} else {
clif->message(sd->fd,msg_txt(1122)); // You have released your Warg.
- pc->setoption(sd, sd->sc.option&~OPTION_WUGRIDER);
+ pc->setridingwug(sd, false);
}
return true;
}
if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC ) {
if( !pc_ismadogear(sd) ) {
clif->message(sd->fd,msg_txt(1123)); // You have mounted your Mado Gear.
- pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR);
+ pc->setmadogear(sd, true);
} else {
clif->message(sd->fd,msg_txt(1124)); // You have released your Mado Gear.
- pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR);
+ pc->setmadogear(sd, false);
}
return true;
}
if( sd->class_&MAPID_SWORDMAN && sd->class_&JOBL_2 ) {
- if( !pc_isriding(sd) ) { // if actually no peco
+ if (!pc_isridingpeco(sd)) { // if actually no peco
if (!pc->checkskill(sd, KN_RIDING)) {
sprintf(atcmd_output, msg_txt(213), skill->get_desc(KN_RIDING)); // You need %s to mount!
clif->message(fd, atcmd_output);
return false;
}
- pc->setoption(sd, sd->sc.option | OPTION_RIDING);
+ pc->setridingpeco(sd, true);
clif->message(fd, msg_txt(102)); // You have mounted a Peco Peco.
} else {//Dismount
- pc->setoption(sd, sd->sc.option & ~OPTION_RIDING);
+ pc->setridingpeco(sd, false);
clif->message(fd, msg_txt(214)); // You have released your Peco Peco.
}
return true;
@@ -4621,8 +4621,7 @@ ACMD(disguise)
return false;
}
- if(pc_isriding(sd))
- {
+ if (pc_hasmount(sd)) {
clif->message(fd, msg_txt(1144)); // Character cannot be disguised while mounted.
return false;
}
@@ -4709,8 +4708,8 @@ ACMD(disguiseguild)
return false;
}
- for( i = 0; i < g->max_member; i++ )
- if( (pl_sd = g->member[i].sd) && !pc_isriding(pl_sd) )
+ for (i = 0; i < g->max_member; i++)
+ if ((pl_sd = g->member[i].sd) && !pc_hasmount(pl_sd))
pc->disguise(pl_sd, id);
clif->message(fd, msg_txt(122)); // Disguise applied.
@@ -5143,7 +5142,7 @@ ACMD(cleargstorage)
return false;
}
- guild_storage = gstorage->id2storage2(sd->status.guild_id);
+ guild_storage = idb_get(gstorage->db,sd->status.guild_id);
if (guild_storage == NULL) {// Doesn't have opened @gstorage yet, so we skip the deletion since *shouldn't* have any item there.
return false;
}
@@ -8358,15 +8357,16 @@ ACMD(charcommands)
return true;
}
/* for new mounts */
-ACMD(mount2) {
+ACMD(cashmount)
+{
- if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) {
+ if (pc_hasmount(sd)) {
clif->message(fd, msg_txt(1476)); // You are already mounting something else
return false;
}
clif->message(sd->fd,msg_txt(1362)); // NOTICE: If you crash with mount your LUA is outdated.
- if( !(sd->sc.data[SC_ALL_RIDING]) ) {
+ if (!sd->sc.data[SC_ALL_RIDING]) {
clif->message(sd->fd,msg_txt(1363)); // You have mounted.
sc_start(NULL,&sd->bl,SC_ALL_RIDING,100,0,-1);
} else {
@@ -9634,7 +9634,7 @@ void atcommand_basecommands(void) {
ACMD_DEF2("rmvperm", addperm),
ACMD_DEF(unloadnpcfile),
ACMD_DEF(cart),
- ACMD_DEF(mount2),
+ ACMD_DEF(cashmount),
ACMD_DEF(join),
ACMD_DEF(channel),
ACMD_DEF(fontcolor),
diff --git a/src/map/battle.c b/src/map/battle.c
index 544d53a1c..73b563d4b 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -220,9 +220,9 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
src = map->id2bl(dat->src_id);
//Check to see if you haven't teleported. [Skotlex]
- if( src && target->m == src->m
+ if( src
&& (target->type != BL_PC || ((TBL_PC*)target)->invincible_timer == INVALID_TIMER)
- && check_distance_bl(src, target, dat->distance)
+ && (dat->skill_id == MO_EXTREMITYFIST || (target->m == src->m && check_distance_bl(src, target, dat->distance)) )
) {
map->freeblock_lock();
status_fix_damage(src, target, dat->damage, dat->delay);
@@ -663,10 +663,10 @@ int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,in
break;
case W_1HSPEAR:
case W_2HSPEAR:
- if((skill_lv = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) {
- if(pc_isridingdragon(sd))
+ if ((skill_lv = pc->checkskill(sd,KN_SPEARMASTERY)) > 0) {
+ if (pc_isridingdragon(sd))
damage += (skill_lv * 10);
- else if(pc_isriding(sd))
+ else if (pc_isridingpeco(sd))
damage += (skill_lv * 5);
else
damage += (skill_lv * 4);
@@ -2707,10 +2707,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
sc_start2(src,bl,SC_COMBOATTACK,100,GC_WEAPONBLOCKING,src->id,2000);
return 0;
}
- if( sc->data[SC_HOVERING] && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL || skill_id == SR_WINDMILL) ) {
- d->dmg_lv = ATK_BLOCK;
- return 0;
- }
if ((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2) {
int delay;
struct block_list *d_bl = NULL;
@@ -2783,7 +2779,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
return 0;
}
- if((sc->data[SC_HERMODE] || sc->data[SC_HOVERING]) && flag&BF_MAGIC)
+ if((sc->data[SC_HERMODE]) && flag&BF_MAGIC)
return 0;
if(sc->data[SC_NJ_TATAMIGAESHI] && (flag&(BF_MAGIC|BF_LONG)) == BF_LONG)
@@ -3190,8 +3186,9 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
switch (skill_id) {
#ifndef RENEWAL
case MO_TRIPLEATTACK:
-#endif
case HW_GRAVITATION:
+#endif
+ case TF_DOUBLE:
break;
default:
return 0;
@@ -5105,6 +5102,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
#endif
+#ifndef RENEWAL // Offensive damage increment in renewal is done somewhere else
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);
@@ -5126,7 +5124,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(10*sd->status.inventory[index].refine);
}
}
-
+#endif
//Card Fix, tsd side
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?1:0), wd.flag);
@@ -5814,6 +5812,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
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);
wd.damage = ad.damage;
+ damage_div_fix(wd.damage, wd.div_);
}else
status_change_end(src,SC_SPELLFIST,INVALID_TIMER);
}
@@ -6146,7 +6145,7 @@ 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...
+ if( skill->get_inf2(su->group->skill_id)&INF2_TRAP && su->group->unit_id != UNT_USED_TRAPS) { //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
case RK_DRAGONBREATH_WATER:
@@ -6245,6 +6244,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
break;
case BL_SKILL: {
struct skill_unit *su = (struct skill_unit *)src;
+ struct status_change* sc = status->get_sc(target);
if (!su->group)
return 0;
@@ -6255,6 +6255,11 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if (inf2&INF2_TARGET_SELF)
return 1;
}
+ //Status changes that prevent traps from triggering
+ if (sc && sc->count && skill->get_inf2(su->group->skill_id)&INF2_TRAP) {
+ if( sc->data[SC_WZ_SIGHTBLASTER] && sc->data[SC_WZ_SIGHTBLASTER]->val2 > 0 && sc->data[SC_WZ_SIGHTBLASTER]->val4%2 == 0)
+ return -1;
+ }
}
break;
case BL_MER:
@@ -6417,6 +6422,12 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range
if( src->m != bl->m )
return false;
+#ifndef CIRCULAR_AREA
+ if( src->type == BL_PC ) { // Range for players' attacks and skills should always have a circular check. [Angezerus]
+ if ( !check_distance_client_bl(src, bl, range) )
+ return false;
+ } else
+#endif
if( !check_distance_bl(src, bl, range) )
return false;
@@ -6451,7 +6462,7 @@ static const struct battle_data {
{ "skill_add_range", &battle_config.skill_add_range, 0, 0, INT_MAX, },
{ "skill_out_range_consume", &battle_config.skill_out_range_consume, 1, 0, 1, },
{ "skillrange_by_distance", &battle_config.skillrange_by_distance, ~BL_PC, BL_NUL, BL_ALL, },
- { "skillrange_from_weapon", &battle_config.use_weapon_skill_range, ~BL_PC, BL_NUL, BL_ALL, },
+ { "skillrange_from_weapon", &battle_config.use_weapon_skill_range, BL_NUL, BL_NUL, BL_ALL, },
{ "player_damage_delay_rate", &battle_config.pc_damage_delay_rate, 100, 0, INT_MAX, },
{ "defunit_not_enemy", &battle_config.defnotenemy, 0, 0, 1, },
{ "gvg_traps_target_all", &battle_config.vs_traps_bctall, BL_PC, BL_NUL, BL_ALL, },
@@ -6628,7 +6639,8 @@ static const struct battle_data {
{ "bone_drop", &battle_config.bone_drop, 0, 0, 2, },
{ "buyer_name", &battle_config.buyer_name, 1, 0, 1, },
{ "skill_wall_check", &battle_config.skill_wall_check, 1, 0, 1, },
- { "cell_stack_limit", &battle_config.cell_stack_limit, 1, 1, 255, },
+ { "official_cell_stack_limit", &battle_config.official_cell_stack_limit, 1, 1, 255, },
+ { "custom_cell_stack_limit", &battle_config.custom_cell_stack_limit, 1, 1, 255, },
{ "dancing_weaponswitch_fix", &battle_config.dancing_weaponswitch_fix, 1, 0, 1, },
// eAthena additions
@@ -6826,6 +6838,10 @@ static const struct battle_data {
{ "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, },
{ "song_timer_reset", &battle_config.song_timer_reset, 0, 0, 1, },
{ "snap_dodge", &battle_config.snap_dodge, 0, 0, 1, },
+ { "monster_chase_refresh", &battle_config.mob_chase_refresh, 1, 0, 30, },
+ { "mob_icewall_walk_block", &battle_config.mob_icewall_walk_block, 75, 0, 255, },
+ { "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, },
+ { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, },
};
#ifndef STATS_OPT_OUT
/**
@@ -7077,6 +7093,13 @@ void battle_adjust_conf(void) {
}
#endif
+#if PACKETVER < 20141022
+ if( battle_config.feature_roulette ) {
+ ShowWarning("conf/battle/feature.conf roulette is enabled but it requires PACKETVER 2014-10-22 or newer, disabling...\n");
+ battle_config.feature_roulette = 0;
+ }
+#endif
+
#if PACKETVER > 20120000 && PACKETVER < 20130515 /* exact date (when it started) not known */
if( battle_config.feature_auction == 1 ) {
ShowWarning("conf/battle/feature.conf:feature.auction is enabled but it is not stable on PACKETVER "EXPAND_AND_QUOTE(PACKETVER)", disabling...\n");
@@ -7087,8 +7110,8 @@ void battle_adjust_conf(void) {
#ifndef CELL_NOSTACK
- if (battle_config.cell_stack_limit != 1)
- ShowWarning("Battle setting 'cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support (CELL_NOSTACK).\n");
+ if (battle_config.custom_cell_stack_limit != 1)
+ ShowWarning("Battle setting 'custom_cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n");
#endif
}
diff --git a/src/map/battle.h b/src/map/battle.h
index 734a6187d..c44e3e19d 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -381,7 +381,8 @@ struct Battle_Config {
int allow_skill_without_day; // [Komurka]
int allow_es_magic_pc; // [Skotlex]
int skill_wall_check; // [Skotlex]
- int cell_stack_limit; // [Skotlex]
+ int official_cell_stack_limit; // [Playtester]
+ int custom_cell_stack_limit; // [Skotlex]
int skill_caster_check; // [Skotlex]
int sc_castcancel; // [Skotlex]
int pc_sc_def_rate; // [Skotlex]
@@ -451,6 +452,9 @@ struct Battle_Config {
int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95]
int bowling_bash_area;
+ int mob_chase_refresh; //How often a monster should refresh its chase [Playtester]
+ int mob_icewall_walk_block; //How a normal monster should be trapped in icewall [Playtester]
+ int boss_icewall_walk_block; //How a boss monster should be trapped in icewall [Playtester]
/** Hercules **/
int skill_trap_type;
@@ -477,6 +481,8 @@ struct Battle_Config {
int song_timer_reset; // [csnv]
int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
+
+ int feature_roulette;
};
extern struct Battle_Config battle_config;
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 34e92bee0..c78b34309 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -1125,9 +1125,12 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th
continue;
if (sc->data[i]->timer != INVALID_TIMER) {
td = timer->get(sc->data[i]->timer);
- if (td == NULL || td->func != status->change_timer || DIFF_TICK(td->tick,tick) < 0)
+ if (td == NULL || td->func != status->change_timer)
continue;
- data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending.
+ if (DIFF_TICK32(td->tick,tick) > 0)
+ data.tick = DIFF_TICK32(td->tick,tick); //Duration that is left before ending.
+ else
+ data.tick = 0; //Negative tick does not necessarily mean that sc has expired
} else
data.tick = -1; //Infinite duration
data.type = i;
diff --git a/src/map/clif.c b/src/map/clif.c
index 018087000..169f30793 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -619,7 +619,9 @@ void clif_authok(struct map_session_data *sd)
#if PACKETVER >= 20080102
p.font = sd->status.font;
#endif
-
+#if PACKETVER >= 20141016
+ p.sex = sd->status.sex;
+#endif
clif->send(&p,sizeof(p),&sd->bl,SELF);
}
@@ -2703,14 +2705,15 @@ void read_channels_config(void) {
} else {
unsigned char d = 0, dlen = strlen(irc_server);
char server[40];
-
+ if (dlen > 39)
+ dlen = 39;
memset(server, '\0', sizeof(server));
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);
+ memcpy(server, &irc_server[d+1], dlen - d - 1);
hChSys.irc_server_port = atoi(server);
break;
}
@@ -3432,7 +3435,6 @@ void clif_arrowequip(struct map_session_data *sd,int val)
nullpo_retv(sd);
- pc_stop_attack(sd); // [Valaris]
#if PACKETVER >= 20121128
clif->status_change(&sd->bl, SI_CLIENT_ONLY_EQUIP_ARROW, 1, INVALID_TIMER, 0, 0, 0);
#endif
@@ -4786,7 +4788,9 @@ int clif_outsight(struct block_list *bl,va_list ap)
}
if (sd && sd->fd) { //sd is watching tbl go out of view.
nullpo_ret(tbl);
- if (((vd=status->get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) &&
+ if(tbl->type == BL_SKILL) //Trap knocked out of sight
+ clif->clearchar_skillunit((struct skill_unit *)tbl,sd->fd);
+ else if (((vd=status->get_viewdata(tbl)) && vd->class_ != INVISIBLE_CLASS) &&
!(tbl->type == BL_NPC && (((TBL_NPC*)tbl)->option&OPTION_INVISIBLE)))
clif->clearunit_single(tbl->id,CLR_OUTSIGHT,sd->fd);
}
@@ -5579,6 +5583,7 @@ void clif_status_change(struct block_list *bl,int type,int flag,int tick,int val
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
@@ -5599,6 +5604,11 @@ void clif_displaymessage(const int fd, const char* mes) {
if( map->cpsd_active && fd == 0 ) {
ShowInfo("HCP: %s\n",mes);
} else if ( fd > 0 ) {
+ #if PACKETVER == 20141022
+ /** for some reason game client crashes depending on message pattern (only for this packet) **/
+ /** so we redirect to ZC_NPC_CHAT **/
+ clif->colormes(fd,COLOR_DEFAULT,mes);
+ #else
size_t 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.
@@ -5608,6 +5618,7 @@ void clif_displaymessage(const int fd, const char* mes) {
safestrncpy((char *)WFIFOP(fd,4), mes, len + 1);
WFIFOSET(fd, 5 + len);
}
+ #endif
}
}
void clif_displaymessage2(const int fd, const char* mes) {
@@ -5832,12 +5843,12 @@ void clif_pvpset(struct map_session_data *sd,int pvprank,int pvpnum,int type)
unsigned char buf[32];
WBUFW(buf,0) = 0x19a;
WBUFL(buf,2) = sd->bl.id;
- if(sd->sc.option&(OPTION_HIDE|OPTION_CLOAK))
+ if (sd->sc.option&(OPTION_HIDE|OPTION_CLOAK)) // TODO[Haru] Should this be pc_ishiding(sd)? (i.e. include Chase Walk and any new options)
WBUFL(buf,6) = UINT32_MAX; //On client displays as --
else
WBUFL(buf,6) = pvprank;
WBUFL(buf,10) = pvpnum;
- if(sd->sc.option&OPTION_INVISIBLE || sd->disguise != -1) //Causes crashes when a 'mob' with pvp info dies.
+ if (pc_isinvisible(sd) || 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);
@@ -8444,7 +8455,7 @@ void clif_refresh_storagewindow( struct map_session_data *sd ) {
// remain locked forever and nobody will be able to access it
if( sd->state.storage_flag == 2 ) {
struct guild_storage *gstor;
- if( (gstor = gstorage->id2storage2(sd->status.guild_id)) == NULL) {
+ if( (gstor = idb_get(gstorage->db,sd->status.guild_id)) == NULL) {
// Shouldn't happen... The information should already be at the map-server
intif->request_guild_storage(sd->status.account_id,sd->status.guild_id);
} else {
@@ -9339,7 +9350,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
sd->state.hpmeter_visible = 1;
}
- if( !(sd->sc.option&OPTION_INVISIBLE) ) { // increment the number of pvp players on the map
+ if (!pc_isinvisible(sd)) { // increment the number of pvp players on the map
map->list[sd->bl.m].users_pvp++;
}
@@ -9360,7 +9371,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
if( sd->bg_id ) clif->bg_hp(sd); // BattleGround System
- if(map->list[sd->bl.m].flag.pvp && !(sd->sc.option&OPTION_INVISIBLE)) {
+ if (map->list[sd->bl.m].flag.pvp && !pc_isinvisible(sd)) {
if(!battle_config.pk_mode) { // remove pvp stuff for pk_mode [Valaris]
if (!map->list[sd->bl.m].flag.pvp_nocalcrank)
sd->pvp_timer = timer->add(timer->gettick()+200, pc->calc_pvprank_timer, sd->bl.id, 0);
@@ -9445,11 +9456,11 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
clif->updatestatus(sd,SP_SKILLPOINT);
clif->initialstatus(sd);
- if (sd->sc.option&OPTION_FALCON)
+ if (pc_isfalcon(sd))
clif->status_change(&sd->bl, SI_FALCON, 1, 0, 0, 0, 0);
- if (sd->sc.option&(OPTION_RIDING|OPTION_DRAGON))
+ if (pc_isridingpeco(sd) || pc_isridingdragon(sd))
clif->status_change(&sd->bl, SI_RIDING, 1, 0, 0, 0, 0);
- else if (sd->sc.option&OPTION_WUGRIDER)
+ else if (pc_isridingwug(sd))
clif->status_change(&sd->bl, SI_WUGRIDER, 1, 0, 0, 0, 0);
if(sd->status.manner < 0)
@@ -9650,18 +9661,22 @@ void clif_hotkeys_send(struct map_session_data *sd) {
#ifdef HOTKEY_SAVING
const int fd = sd->fd;
int i;
+ int offset = 2;
#if PACKETVER < 20090603
const int cmd = 0x2b9;
-#else
+#elif PACKETVER < 20141022
const int cmd = 0x7d9;
+#else
+ const int cmd = 0xa00;
+ offset = 3;
#endif
if (!fd) return;
- WFIFOHEAD(fd, 2+MAX_HOTKEYS*7);
+ WFIFOHEAD(fd, offset+MAX_HOTKEYS*7);
WFIFOW(fd, 0) = cmd;
for(i = 0; i < MAX_HOTKEYS; i++) {
- WFIFOB(fd, 2 + 0 + i * 7) = sd->status.hotkeys[i].type; // type: 0: item, 1: skill
- WFIFOL(fd, 2 + 1 + i * 7) = sd->status.hotkeys[i].id; // item or skill ID
- WFIFOW(fd, 2 + 5 + i * 7) = sd->status.hotkeys[i].lv; // skill level
+ WFIFOB(fd, offset + 0 + i * 7) = sd->status.hotkeys[i].type; // type: 0: item, 1: skill
+ WFIFOL(fd, offset + 1 + i * 7) = sd->status.hotkeys[i].id; // item or skill ID
+ WFIFOW(fd, offset + 5 + i * 7) = sd->status.hotkeys[i].lv; // item qty or skill level
}
WFIFOSET(fd, packet_len(cmd));
#endif
@@ -10122,7 +10137,8 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
)
return;
- pc_stop_walking(sd, 1);
+ if(action_type != 0x00 && action_type != 0x07)
+ pc_stop_walking(sd, 1);
pc_stop_attack(sd);
if(target_id<0 && -target_id == sd->bl.id) // for disguises [Valaris]
@@ -10488,7 +10504,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
// if player ignores everyone
if (dstsd->state.ignoreAll && pc_get_group_level(sd) <= pc_get_group_level(dstsd)) {
- if (dstsd->sc.option & OPTION_INVISIBLE && pc_get_group_level(sd) < pc_get_group_level(dstsd))
+ if (pc_isinvisible(dstsd) && pc_get_group_level(sd) < pc_get_group_level(dstsd))
clif->wis_end(fd, 1); // 1: target character is not logged in
else
clif->wis_end(fd, 3); // 3: everyone ignored by target
@@ -11162,16 +11178,17 @@ void clif_parse_GetItemFromCart(int fd,struct map_session_data *sd)
/// 012a
void clif_parse_RemoveOption(int fd,struct map_session_data *sd)
{
- if( !(sd->sc.option&(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR))
+ if (pc_isridingpeco(sd) || pc_isfalcon(sd) || pc_isridingdragon(sd) || pc_ismadogear(sd)) {
+ // priority to remove this option before we can clear cart
+ pc->setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR));
+ } else {
#ifdef NEW_CARTS
- && sd->sc.data[SC_PUSH_CART] ){
- pc->setcart(sd,0);
-#else
- ){
+ if (sd->sc.data[SC_PUSH_CART])
+ pc->setcart(sd,0);
+#else // not NEW_CARTS
pc->setoption(sd,sd->sc.option&~OPTION_CART);
-#endif
- }else // priority to remove this option before we can clear cart
- pc->setoption(sd,sd->sc.option&~(OPTION_RIDING|OPTION_FALCON|OPTION_DRAGON|OPTION_MADOGEAR));
+#endif // NEW_CARTS
+ }
}
@@ -12234,7 +12251,7 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
void clif_parse_PartyChangeLeader(int fd, struct map_session_data* sd) {
party->changeleader(sd, map->id2sd(RFIFOL(fd,2)));
}
-
+
/// Party Booking in KRO [Spiria]
///
@@ -15116,7 +15133,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
+ memset(&msg, 0, sizeof(msg));
+ if (!mail->setattachment(sd, &msg)) { // Invalid Append condition
clif->mail_send(sd->fd, true); // fail
mail->removeitem(sd,0);
mail->removezeny(sd,0);
@@ -15334,9 +15352,10 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
struct auction_data auction;
struct item_data *item;
- if( !battle_config.feature_auction )
+ if (!battle_config.feature_auction)
return;
+ memset(&auction, 0, sizeof(auction));
auction.price = RFIFOL(fd,2);
auction.buynow = RFIFOL(fd,6);
auction.hours = RFIFOW(fd,10);
@@ -15794,19 +15813,34 @@ void clif_parse_PartyTick(int fd, struct map_session_data* sd)
/// 02b1 <packet len>.W <num>.L { <quest id>.L <active>.B }*num
void clif_quest_send_list(struct map_session_data *sd) {
int fd = sd->fd;
- int i;
- int len = sd->avail_quests*5+8;
-
+ int i;
+#if PACKETVER >= 20141022
+ int info_len = 15;
+ int len = sd->avail_quests*info_len+8;
WFIFOHEAD(fd,len);
- WFIFOW(fd, 0) = 0x2b1;
+ WFIFOW(fd, 0) = 0x97a;
+#else
+ int info_len = 5;
+ int len = sd->avail_quests*info_len+8;
+ WFIFOHEAD(fd,len);
+ WFIFOW(fd, 0) = 0x2b1;
+#endif
WFIFOW(fd, 2) = len;
WFIFOL(fd, 4) = sd->avail_quests;
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;
+ #if PACKETVER >= 20141022
+ struct quest_db *qi = quest->db(sd->quest_log[i].quest_id);
+ #endif
+ WFIFOL(fd, i*info_len+8) = sd->quest_log[i].quest_id;
+ WFIFOB(fd, i*info_len+12) = sd->quest_log[i].state;
+ #if PACKETVER >= 20141022
+ WFIFOL(fd, i*info_len+13) = sd->quest_log[i].time - qi->time;
+ WFIFOL(fd, i*info_len+17) = sd->quest_log[i].time;
+ WFIFOW(fd, i*info_len+21) = qi->num_objectives;
+ #endif
}
-
+
WFIFOSET(fd, len);
}
@@ -18254,6 +18288,296 @@ void clif_parse_NPCMarketPurchase(int fd, struct map_session_data *sd) {
clif->npc_market_purchase_ack(sd,p,npc->market_buylist(sd,(p->PacketLength - 4) / sizeof(p->list[0]),p));
#endif
}
+
+void clif_PartyLeaderChanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid) {
+ struct packet_party_leader_changed p;
+
+ p.PacketType = partyleaderchangedType;
+
+ p.prev_leader_aid = prev_leader_aid;
+ p.new_leader_aid = new_leader_aid;
+
+ clif->send(&p,sizeof(p),&sd->bl,PARTY);
+}
+
+/* Roulette System [Yommy/Hercules] */
+void clif_parse_RouletteOpen(int fd, struct map_session_data* sd) {
+ struct packet_roulette_open_ack p;
+
+ if( !battle_config.feature_roulette ) {
+ clif->message(fd,"Roulette is disabled");
+ return;
+ }
+
+ p.PacketType = 0xa1a;
+ p.Result = 0;
+ p.Serial = 0;
+ p.Step = sd->roulette.stage - 1;
+ p.Idx = sd->roulette.prizeIdx;
+ p.AdditionItemID = -1; /** TODO **/
+ p.BronzePoint = pc_readglobalreg(sd, script->add_str("TmpRouletteBronze"));
+ p.GoldPoint = pc_readglobalreg(sd, script->add_str("TmpRouletteGold"));
+ p.SilverPoint = pc_readglobalreg(sd, script->add_str("TmpRouletteSilver"));
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+void clif_parse_RouletteInfo(int fd, struct map_session_data* sd) {
+ struct packet_roulette_info_ack p;
+ unsigned short i, j, count = 0;
+
+ if( !battle_config.feature_roulette ) {
+ clif->message(fd,"Roulette is disabled");
+ return;
+ }
+
+ p.PacketType = rouletteinfoackType;
+ p.PacketLength = 8 + (42 * 8);
+ p.RouletteSerial = 1;
+
+ for(i = 0; i < MAX_ROULETTE_LEVEL; i++) {
+ for(j = 0; j < MAX_ROULETTE_COLUMNS-i; j++) {
+ p.ItemInfo[count].Row = i;
+ p.ItemInfo[count].Position = j;
+ p.ItemInfo[count].ItemId = clif->rd.nameid[i][j];
+ p.ItemInfo[count].Count = clif->rd.qty[i][j];
+ count++;
+ }
+ }
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+ return;
+}
+void clif_parse_RouletteClose(int fd, struct map_session_data* sd) {
+
+ if( !battle_config.feature_roulette ) {
+ clif->message(fd,"Roulette is disabled");
+ return;
+ }
+
+
+ /** What do we need this for? (other than state tracking), game client closes the window without our response. **/
+
+ //ShowDebug("clif_parse_RouletteClose\n");
+
+ return;
+}
+void clif_parse_RouletteGenerate(int fd, struct map_session_data* sd) {
+ unsigned char result = GENERATE_ROULETTE_SUCCESS;
+ short stage = sd->roulette.stage;
+
+ if( !battle_config.feature_roulette ) {
+ clif->message(fd,"Roulette is disabled");
+ return;
+ }
+
+ if( sd->roulette.stage >= MAX_ROULETTE_LEVEL )
+ stage = sd->roulette.stage = 0;
+
+ if( stage == 0 ) {
+ if( pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) <= 0 &&
+ pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")) < 10 &&
+ pc_readglobalreg(sd, script->add_str("TmpRouletteGold")) < 10 )
+ result = GENERATE_ROULETTE_NO_ENOUGH_POINT;
+ }
+
+ if( result == GENERATE_ROULETTE_SUCCESS ) {
+
+ if( stage == 0 ) {
+ if( pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) > 0 ) {
+ pc_setglobalreg(sd, script->add_str("TmpRouletteBronze"), pc_readglobalreg(sd, script->add_str("TmpRouletteBronze")) - 1);
+ } else if( pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")) > 9 ) {
+ pc_setglobalreg(sd, script->add_str("TmpRouletteSilver"), pc_readglobalreg(sd, script->add_str("TmpRouletteSilver")) - 10);
+ stage = sd->roulette.stage = 2;
+ } else if( pc_readglobalreg(sd, script->add_str("TmpRouletteGold")) > 9 ) {
+ pc_setglobalreg(sd, script->add_str("TmpRouletteGold"), pc_readglobalreg(sd, script->add_str("TmpRouletteGold")) - 10);
+ stage = sd->roulette.stage = 4;
+ }
+ }
+
+ sd->roulette.prizeStage = stage;
+ sd->roulette.prizeIdx = rnd()%clif->rd.items[stage];
+ if( sd->roulette.prizeIdx == 0 ) {
+ struct item it;
+ memset(&it, 0, sizeof(it));
+
+ it.nameid = clif->rd.nameid[stage][0];
+ it.identify = 1;
+
+ pc->additem(sd, &it, clif->rd.qty[stage][0], LOG_TYPE_OTHER);/** TODO maybe a new log type for roulette items? **/
+
+ sd->roulette.stage = 0;
+ result = GENERATE_ROULETTE_LOSING;
+ } else
+ sd->roulette.claimPrize = true;
+ }
+
+ clif->roulette_generate_ack(sd,result,stage,sd->roulette.prizeIdx,0);
+ if( result == GENERATE_ROULETTE_SUCCESS )
+ sd->roulette.stage++;
+}
+/**
+ * Request to cash in!
+ **/
+void clif_parse_RouletteRecvItem(int fd, struct map_session_data* sd) {
+ struct packet_roulette_itemrecv_ack p;
+
+ if( !battle_config.feature_roulette ) {
+ clif->message(fd,"Roulette is disabled");
+ return;
+ }
+
+ p.PacketType = roulettercvitemackType;
+ p.AdditionItemID = 0;/** TODO **/
+
+ if( sd->roulette.claimPrize ) {
+ struct item it;
+ memset(&it, 0, sizeof(it));
+
+ it.nameid = clif->rd.nameid[sd->roulette.prizeStage][sd->roulette.prizeIdx];
+ it.identify = 1;
+
+ switch (pc->additem(sd, &it, clif->rd.qty[sd->roulette.prizeStage][sd->roulette.prizeIdx], LOG_TYPE_OTHER)) {
+ case 0:
+ p.Result = RECV_ITEM_SUCCESS;
+ sd->roulette.claimPrize = false;
+ sd->roulette.prizeStage = 0;
+ sd->roulette.prizeIdx = 0;
+ sd->roulette.stage = 0;
+ break;
+ case 1:
+ case 4:
+ case 5:
+ p.Result = RECV_ITEM_OVERCOUNT;
+ break;
+ case 2:
+ p.Result = RECV_ITEM_OVERWEIGHT;
+ break;
+ default:
+ case 7:
+ p.Result = RECV_ITEM_FAILED;
+ break;
+ }
+ } else
+ p.Result = RECV_ITEM_FAILED;
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+ return;
+}
+
+bool clif_parse_roulette_db(void) {
+ config_t roulette_conf;
+ config_setting_t *roulette = NULL, *levels = NULL;
+ const char *config_filename = "db/roulette_db.conf"; // FIXME hardcoded name
+ int i, j, item_count_t = 0;
+
+ for( i = 0; i < MAX_ROULETTE_LEVEL; i++ ) {
+ clif->rd.items[i] = 0;
+ }
+
+ if (libconfig->read_file(&roulette_conf, config_filename)) {
+ ShowError("can't read %s\n", config_filename);
+ return false;
+ }
+
+ roulette = libconfig->lookup(&roulette_conf, "roulette");
+
+ if( roulette != NULL && (levels = libconfig->setting_get_elem(roulette, 0)) != NULL ) {
+ for(i = 0; i < MAX_ROULETTE_LEVEL; i++) {
+ config_setting_t *level;
+ char entry_name[10];
+
+ sprintf(entry_name,"level_%d",i+1);
+
+ if( (level = libconfig->setting_get_member(levels, entry_name)) != NULL ) {
+ int k, item_count = libconfig->setting_length(level);
+
+ for(k = 0; k < item_count; k++) {
+ config_setting_t *entry = libconfig->setting_get_elem(level,k);
+ const char *name = config_setting_name(entry);
+ int qty = libconfig->setting_get_int(entry);
+ struct item_data * data = NULL;
+
+ if( qty < 1 ) {
+ ShowWarning("roulette_db: unsupported qty '%d' for entry named '%s' in category '%s'\n", qty, name, entry_name);
+ continue;
+ }
+
+ if( name[0] == 'I' && name[1] == 'D' && strlen(name) <= 7 ) {
+ if( !( data = itemdb->exists(atoi(name+2))) ) {
+ ShowWarning("roulette_db: unknown item id '%s' in category '%s'\n", name+2, entry_name);
+ continue;
+ }
+ } else {
+ if( !( data = itemdb->search_name(name) ) ) {
+ ShowWarning("roulette_db: unknown item name '%s' in category '%s'\n", name, entry_name);
+ continue;
+ }
+ }
+
+ j = clif->rd.items[i];
+ RECREATE(clif->rd.nameid[i],int,++clif->rd.items[i]);
+ RECREATE(clif->rd.qty[i],int,clif->rd.items[i]);
+
+ clif->rd.nameid[i][j] = data->nameid;
+ clif->rd.qty[i][j] = qty;
+
+ item_count_t++;
+ }
+ }
+ }
+
+ libconfig->destroy(&roulette_conf);
+ }
+
+ for(i = 0; i < MAX_ROULETTE_LEVEL; i++) {
+ int limit = MAX_ROULETTE_COLUMNS-i;
+ if( clif->rd.items[i] == limit ) continue;
+
+ if( clif->rd.items[i] > limit ) {
+ ShowWarning("roulette_db: level %d has %d items, only %d supported, capping...\n",i+1,clif->rd.items[i],limit);
+ clif->rd.items[i] = limit;
+ continue;
+ }
+ /** this scenario = clif->rd.items[i] < limit **/
+ ShowWarning("roulette_db: level %d has %d items, %d are required. filling with apples\n",i+1,clif->rd.items[i],limit);
+
+ clif->rd.items[i] = limit;
+ RECREATE(clif->rd.nameid[i],int,clif->rd.items[i]);
+ RECREATE(clif->rd.qty[i],int,clif->rd.items[i]);
+
+
+ for(j = 0; j < MAX_ROULETTE_COLUMNS-i; j++) {
+ if( clif->rd.qty[i][j] ) continue;
+
+ clif->rd.nameid[i][j] = ITEMID_APPLE;
+ clif->rd.qty[i][j] = 1;
+ }
+ }
+
+
+ ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' entries in '"CL_WHITE"%s"CL_RESET"'.\n", item_count_t, config_filename);
+
+ return true;
+}
+
+/**
+ *
+ **/
+void clif_roulette_generate_ack(struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID) {
+ struct packet_roulette_generate_ack p;
+
+ p.PacketType = roulettgenerateackType;
+ p.Result = result;
+ p.Step = stage;
+ p.Idx = prizeIdx;
+ p.AdditionItemID = bonusItemID;
+ p.RemainBronze = pc_readglobalreg(sd, script->add_str("TmpRouletteBronze"));
+ p.RemainGold = pc_readglobalreg(sd, script->add_str("TmpRouletteGold"));
+ p.RemainSilver = pc_readglobalreg(sd, script->add_str("TmpRouletteSilver"));
+
+ clif->send(&p,sizeof(p), &sd->bl, SELF);
+}
+
/* */
unsigned short clif_decrypt_cmd( int cmd, struct map_session_data *sd ) {
if( sd ) {
@@ -18570,6 +18894,13 @@ void do_final_clif(void) {
}
aFree(clif->cs.data[i]);
}
+
+ for(i = 0; i < MAX_ROULETTE_LEVEL; i++) {
+ if( clif->rd.nameid[i] )
+ aFree(clif->rd.nameid[i]);
+ if( clif->rd.qty[i] )
+ aFree(clif->rd.qty[i]);
+ }
}
void clif_defaults(void) {
@@ -18884,6 +19215,7 @@ void clif_defaults(void) {
clif->party_xy_remove = clif_party_xy_remove;
clif->party_show_picker = clif_party_show_picker;
clif->partyinvitationstate = clif_partyinvitationstate;
+ clif->PartyLeaderChanged = clif_PartyLeaderChanged;
/* guild-specific */
clif->guild_created = clif_guild_created;
clif->guild_belonginfo = clif_guild_belonginfo;
@@ -19070,6 +19402,9 @@ void clif_defaults(void) {
/* NPC Market */
clif->npc_market_open = clif_npc_market_open;
clif->npc_market_purchase_ack = clif_npc_market_purchase_ack;
+ /* */
+ clif->parse_roulette_db = clif_parse_roulette_db;
+ clif->roulette_generate_ack = clif_roulette_generate_ack;
/*------------------------
*- Parse Incoming Packet
*------------------------*/
@@ -19299,6 +19634,12 @@ void clif_defaults(void) {
clif->pBankCheck = clif_parse_BankCheck;
clif->pBankOpen = clif_parse_BankOpen;
clif->pBankClose = clif_parse_BankClose;
+ /* Roulette System [Yommy/Hercules] */
+ clif->pRouletteOpen = clif_parse_RouletteOpen;
+ clif->pRouletteInfo = clif_parse_RouletteInfo;
+ clif->pRouletteClose = clif_parse_RouletteClose;
+ clif->pRouletteGenerate = clif_parse_RouletteGenerate;
+ clif->pRouletteRecvItem = clif_parse_RouletteRecvItem;
/* */
clif->pNPCShopClosed = clif_parse_NPCShopClosed;
/* NPC Market */
diff --git a/src/map/clif.h b/src/map/clif.h
index e4de51a83..17fda9a74 100644
--- a/src/map/clif.h
+++ b/src/map/clif.h
@@ -18,8 +18,6 @@
**/
struct item;
struct item_data;
-struct storage_data;
-struct guild_storage;
struct unit_data;
struct map_session_data;
struct homun_data;
@@ -50,6 +48,8 @@ struct skill_cd;
#define clif_disp_onlyself(sd,mes,len) clif->disp_message( &(sd)->bl, (mes), (len), SELF )
#define clif_viewequip_fail( sd ) clif_msg( (sd), 0x54d );
#define HCHSYS_NAME_LENGTH 20
+#define MAX_ROULETTE_LEVEL 7 /** client-defined value **/
+#define MAX_ROULETTE_COLUMNS 9 /** client-defined value **/
/**
* Enumerations
@@ -478,6 +478,35 @@ enum e_trade_item_ok {
TIO_INDROCKS = 0x9,
};
+enum RECV_ROULETTE_ITEM_REQ {
+ RECV_ITEM_SUCCESS = 0x0,
+ RECV_ITEM_FAILED = 0x1,
+ RECV_ITEM_OVERCOUNT = 0x2,
+ RECV_ITEM_OVERWEIGHT = 0x3,
+};
+
+enum RECV_ROULETTE_ITEM_ACK {
+ RECV_ITEM_NORMAL = 0x0,
+ RECV_ITEM_LOSING = 0x1,
+};
+
+enum GENERATE_ROULETTE_ACK {
+ GENERATE_ROULETTE_SUCCESS = 0x0,
+ GENERATE_ROULETTE_FAILED = 0x1,
+ GENERATE_ROULETTE_NO_ENOUGH_POINT = 0x2,
+ GENERATE_ROULETTE_LOSING = 0x3,
+};
+
+enum OPEN_ROULETTE_ACK{
+ OPEN_ROULETTE_SUCCESS = 0x0,
+ OPEN_ROULETTE_FAILED = 0x1,
+};
+
+enum CLOSE_ROULETTE_ACK {
+ CLOSE_ROULETTE_SUCCESS = 0x0,
+ CLOSE_ROULETTE_FAILED = 0x1,
+};
+
/**
* Structures
**/
@@ -554,6 +583,12 @@ struct clif_interface {
struct hCSData **data[CASHSHOP_TAB_MAX];
unsigned int item_count[CASHSHOP_TAB_MAX];
} cs;
+ /* roulette data */
+ struct {
+ int *nameid[MAX_ROULETTE_LEVEL];//nameid
+ int *qty[MAX_ROULETTE_LEVEL];//qty of nameid
+ int items[MAX_ROULETTE_LEVEL];//number of items in the list for each
+ } rd;
/* */
unsigned int cryptKey[3];
/* */
@@ -866,6 +901,7 @@ struct clif_interface {
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);
+ void (*PartyLeaderChanged) (struct map_session_data *sd, int prev_leader_aid, int new_leader_aid);
/* guild-specific */
void (*guild_created) (struct map_session_data *sd,int flag);
void (*guild_belonginfo) (struct map_session_data *sd, struct guild *g);
@@ -1052,6 +1088,9 @@ struct clif_interface {
/* NPC Market */
void (*npc_market_open) (struct map_session_data *sd, struct npc_data *nd);
void (*npc_market_purchase_ack) (struct map_session_data *sd, struct packet_npc_market_purchase *req, unsigned char response);
+ /* */
+ bool (*parse_roulette_db) (void);
+ void (*roulette_generate_ack) (struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID);
/*------------------------
*- Parse Incoming Packet
*------------------------*/
@@ -1279,6 +1318,12 @@ struct clif_interface {
void (*pBankCheck) (int fd, struct map_session_data *sd);
void (*pBankOpen) (int fd, struct map_session_data *sd);
void (*pBankClose) (int fd, struct map_session_data *sd);
+ /* Roulette System [Yommy/Hercules] */
+ void (*pRouletteOpen) (int fd, struct map_session_data *sd);
+ void (*pRouletteInfo) (int fd, struct map_session_data *sd);
+ void (*pRouletteClose) (int fd, struct map_session_data *sd);
+ void (*pRouletteGenerate) (int fd, struct map_session_data *sd);
+ void (*pRouletteRecvItem) (int fd, struct map_session_data *sd);
/* */
void (*pNPCShopClosed) (int fd, struct map_session_data *sd);
/* NPC Market (by Ind after an extensive debugging of the packet, only possible thanks to Yommy <3) */
diff --git a/src/map/guild.c b/src/map/guild.c
index ac24edeab..1d9cf03a9 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -459,6 +459,8 @@ int guild_recv_info(struct guild *sg) {
struct map_session_data *sd;
bool guild_new = false;
struct hChSysCh *aChSysSave = NULL;
+ short *instance_save = NULL;
+ unsigned short instances_save = 0;
nullpo_ret(sg);
@@ -538,10 +540,16 @@ int guild_recv_info(struct guild *sg) {
before=*g;
if( g->channel )
aChSysSave = g->channel;
+ if( g->instance )
+ instance_save = g->instance;
+ if( g->instances )
+ instances_save = g->instances;
}
memcpy(g,sg,sizeof(struct guild));
g->channel = aChSysSave;
+ g->instance = instance_save;
+ g->instances = instances_save;
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);
@@ -928,7 +936,7 @@ void guild_retrieveitembound(int char_id,int aid,int guild_id) {
if(sd){ //Character is online
pc->bound_clear(sd,IBT_GUILD);
} else { //Character is offline, ask char server to do the job
- struct guild_storage *gstor = gstorage->id2storage2(guild_id);
+ struct guild_storage *gstor = idb_get(gstorage->db,guild_id);
if(gstor && gstor->storage_status == 1) { //Someone is in guild storage, close them
struct s_mapiterator* iter = mapit_getallusers();
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
diff --git a/src/map/intif.c b/src/map/intif.c
index fc38e82e3..c20905bcf 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -1098,7 +1098,7 @@ void intif_parse_LoadGuildStorage(int fd)
return;
}
}
- gstor=gstorage->id2storage(guild_id);
+ gstor=gstorage->ensure(guild_id);
if(!gstor) {
ShowWarning("intif_parse_LoadGuildStorage: error guild_id %d not exist\n",guild_id);
return;
@@ -2165,7 +2165,7 @@ void intif_parse_MessageToFD(int fd) {
*------------------------------------------*/
void intif_itembound_req(int char_id,int aid,int guild_id) {
#ifdef GP_BOUND_ITEMS
- struct guild_storage *gstor = gstorage->id2storage2(guild_id);
+ struct guild_storage *gstor = idb_get(gstorage->db,guild_id);
WFIFOHEAD(inter_fd,12);
WFIFOW(inter_fd,0) = 0x3056;
WFIFOL(inter_fd,2) = char_id;
@@ -2183,7 +2183,7 @@ void intif_parse_Itembound_ack(int fd) {
struct guild_storage *gstor;
int guild_id = RFIFOW(fd,6);
- gstor = gstorage->id2storage2(guild_id);
+ gstor = idb_get(gstorage->db,guild_id);
if(gstor)
gstor->lock = 0; //Unlock now that operation is completed
#endif
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 0d3146191..41e0a5348 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -1713,7 +1713,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
if( libconfig->setting_lookup_int(it, "Type", &i32) )
id.type = i32;
else if( !inherit )
- id.type = IT_UNKNOWN;
+ id.type = IT_ETC;
if( libconfig->setting_lookup_int(it, "Buy", &i32) )
id.value_buy = i32;
@@ -2248,6 +2248,10 @@ void do_init_itemdb(bool minimal) {
return;
clif->cashshop_load();
+
+ /** it failed? we disable it **/
+ if( !clif->parse_roulette_db() )
+ battle_config.feature_roulette = 0;
}
void itemdb_defaults(void) {
itemdb = &itemdb_s;
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 198d7a542..8d8cfd7c2 100644
--- a/src/map/itemdb.h
+++ b/src/map/itemdb.h
@@ -41,7 +41,9 @@ enum item_itemid {
ITEMID_YELLOW_POTION = 503,
ITEMID_WHITE_POTION = 504,
ITEMID_BLUE_POTION = 505,
+ ITEMID_APPLE = 512,
ITEMID_HOLY_WATER = 523,
+ ITEMID_PUMPKIN = 535,
ITEMID_RED_SLIM_POTION = 545,
ITEMID_YELLOW_SLIM_POTION = 546,
ITEMID_WHITE_SLIM_POTION = 547,
diff --git a/src/map/log.h b/src/map/log.h
index 6ab142f87..40dbf6761 100644
--- a/src/map/log.h
+++ b/src/map/log.h
@@ -98,7 +98,7 @@ struct log_interface {
char db_ip[32];
int db_port;
char db_id[32];
- char db_pw[32];
+ char db_pw[100];
char db_name[32];
Sql* mysql_handle;
/* */
diff --git a/src/map/map.c b/src/map/map.c
index 14af392b7..5c0f5d65e 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -395,9 +395,11 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
/*==========================================
* Counts specified number of objects on given cell.
+ * flag:
+ * 0x1 - only count standing units
* TODO: merge with bl_getall_area
*------------------------------------------*/
-int map_count_oncell(int16 m, int16 x, int16 y, int type) {
+int map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) {
int bx,by;
struct block_list *bl;
int count = 0;
@@ -410,13 +412,27 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type) {
if (type&~BL_MOB)
for( bl = map->list[m].block[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next )
- if(bl->x == x && bl->y == y && bl->type&type)
- count++;
+ if(bl->x == x && bl->y == y && bl->type&type) {
+ if(flag&1) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if(!ud || ud->walktimer == INVALID_TIMER)
+ count++;
+ } else {
+ count++;
+ }
+ }
if (type&BL_MOB)
for( bl = map->list[m].block_mob[bx+by*map->list[m].bxs] ; bl != NULL ; bl = bl->next )
- if(bl->x == x && bl->y == y)
- count++;
+ if(bl->x == x && bl->y == y) {
+ if(flag&1) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if(!ud || ud->walktimer == INVALID_TIMER)
+ count++;
+ } else {
+ count++;
+ }
+ }
return count;
}
@@ -1379,7 +1395,7 @@ int map_searchrandfreecell(int16 m,int16 *x,int16 *y,int stack) {
if(map->getcell(m,j+*x,i+*y,CELL_CHKNOPASS) && !map->getcell(m,j+*x,i+*y,CELL_CHKICEWALL))
continue;
//Avoid item stacking to prevent against exploits. [Skotlex]
- if(stack && map->count_oncell(m,j+*x,i+*y, BL_ITEM) > stack)
+ if(stack && map->count_oncell(m,j+*x,i+*y, BL_ITEM, 0) > stack)
continue;
free_cells[free_cell][0] = j+*x;
free_cells[free_cell++][1] = i+*y;
@@ -1473,6 +1489,85 @@ int map_search_freecell(struct block_list *src, int16 m, int16 *x,int16 *y, int1
}
/*==========================================
+ * Locates the closest, walkable cell with no blocks of a certain type on it
+ * Returns true on success and sets x and y to cell found.
+ * Otherwise returns false and x and y are not changed.
+ * type: Types of block to count
+ * flag:
+ * 0x1 - only count standing units
+ *------------------------------------------*/
+bool map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag)
+{
+ uint8 dir = 6;
+ int16 tx = *x;
+ int16 ty = *y;
+ int costrange = 10;
+
+ if(!map->count_oncell(m, tx, ty, type, flag))
+ return true; //Current cell is free
+
+ //Algorithm only works up to costrange of 34
+ while(costrange <= 34) {
+ short dx = dirx[dir];
+ short dy = diry[dir];
+
+ //Linear search
+ if(dir%2 == 0 && costrange%MOVE_COST == 0) {
+ tx = *x+dx*(costrange/MOVE_COST);
+ ty = *y+dy*(costrange/MOVE_COST);
+ if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) {
+ *x = tx;
+ *y = ty;
+ return true;
+ }
+ }
+ //Full diagonal search
+ else if(dir%2 == 1 && costrange%MOVE_DIAGONAL_COST == 0) {
+ tx = *x+dx*(costrange/MOVE_DIAGONAL_COST);
+ ty = *y+dy*(costrange/MOVE_DIAGONAL_COST);
+ if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) {
+ *x = tx;
+ *y = ty;
+ return true;
+ }
+ }
+ //One cell diagonal, rest linear (TODO: Find a better algorithm for this)
+ else if(dir%2 == 1 && costrange%MOVE_COST == 4) {
+ tx = *x+dx*((dir%4==3)?(costrange/MOVE_COST):1);
+ ty = *y+dy*((dir%4==1)?(costrange/MOVE_COST):1);
+ if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) {
+ *x = tx;
+ *y = ty;
+ return true;
+ }
+ tx = *x+dx*((dir%4==1)?(costrange/MOVE_COST):1);
+ ty = *y+dy*((dir%4==3)?(costrange/MOVE_COST):1);
+ if(!map->count_oncell(m, tx, ty, type, flag) && map->getcell(m,tx,ty,CELL_CHKPASS)) {
+ *x = tx;
+ *y = ty;
+ return true;
+ }
+ }
+
+ //Get next direction
+ if (dir == 5) {
+ //Diagonal search complete, repeat with higher cost range
+ if(costrange == 14) costrange += 6;
+ else if(costrange == 28 || costrange >= 38) costrange += 2;
+ else costrange += 4;
+ dir = 6;
+ } else if (dir == 4) {
+ //Linear search complete, switch to diagonal directions
+ dir = 7;
+ } else {
+ dir = (dir+2)%8;
+ }
+ }
+
+ return false;
+}
+
+/*==========================================
* Add an item to location (m,x,y)
* Parameters
* @item_data item attributes
@@ -2420,28 +2515,27 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
}
else if( dx >= 0 && dy >=0 )
{ // upper-right
- if( dx*2 <= dy ) dir = 0; // up
- else if( dx > dy*2 ) dir = 6; // right
- else dir = 7; // up-right
+ if( dx*2 < dy || dx == 0 ) dir = 0; // up
+ else if( dx > dy*2+1 || dy == 0 ) dir = 6; // right
+ else dir = 7; // up-right
}
else if( dx >= 0 && dy <= 0 )
{ // lower-right
- if( dx*2 <= -dy ) dir = 4; // down
- else if( dx > -dy*2 ) dir = 6; // right
- else dir = 5; // down-right
+ if( dx*2 < -dy || dx == 0 ) dir = 4; // down
+ else if( dx > -dy*2+1 || dy == 0 ) dir = 6; // right
+ else dir = 5; // down-right
}
else if( dx <= 0 && dy <= 0 )
{ // lower-left
- if( dx*2 >= dy ) dir = 4; // down
- else if( dx < dy*2 ) dir = 2; // left
- else dir = 3; // down-left
+ if( dx*2 > dy || dx == 0 ) dir = 4; // down
+ else if( dx < dy*2-1 || dy == 0 ) dir = 2; // left
+ else dir = 3; // down-left
}
else
{ // upper-left
- if( -dx*2 <= dy ) dir = 0; // up
- else if( -dx > dy*2 ) dir = 2; // left
- else dir = 1; // up-left
-
+ if( -dx*2 < dy || dx == 0 ) dir = 0; // up
+ else if( -dx > dy*2+1 || dy == 0) dir = 2; // left
+ else dir = 1; // up-left
}
return dir;
}
@@ -2587,25 +2681,27 @@ int map_getcellp(struct map_data* m,int16 x,int16 y,cell_chk cellchk) {
return (cell.nochat);
case CELL_CHKICEWALL:
return (cell.icewall);
+ case CELL_CHKNOICEWALL:
+ return (cell.noicewall);
// special checks
case CELL_CHKPASS:
#ifdef CELL_NOSTACK
- if (cell.cell_bl >= battle_config.cell_stack_limit) return 0;
+ if (cell.cell_bl >= battle_config.custom_cell_stack_limit) return 0;
#endif
case CELL_CHKREACH:
return (cell.walkable);
case CELL_CHKNOPASS:
#ifdef CELL_NOSTACK
- if (cell.cell_bl >= battle_config.cell_stack_limit) return 1;
+ if (cell.cell_bl >= battle_config.custom_cell_stack_limit) return 1;
#endif
case CELL_CHKNOREACH:
return (!cell.walkable);
case CELL_CHKSTACK:
#ifdef CELL_NOSTACK
- return (cell.cell_bl >= battle_config.cell_stack_limit);
+ return (cell.cell_bl >= battle_config.custom_cell_stack_limit);
#else
return 0;
#endif
@@ -2646,6 +2742,8 @@ void map_setcell(int16 m, int16 x, int16 y, cell_t cell, bool flag) {
case CELL_NOVENDING: map->list[m].cell[j].novending = flag; break;
case CELL_NOCHAT: map->list[m].cell[j].nochat = flag; break;
case CELL_ICEWALL: map->list[m].cell[j].icewall = flag; break;
+ case CELL_NOICEWALL: map->list[m].cell[j].noicewall = flag; break;
+
default:
ShowWarning("map_setcell: invalid cell type '%d'\n", (int)cell);
break;
@@ -5611,10 +5709,7 @@ int do_init(int argc, char *argv[])
map_load_defaults();
HPM_map_do_init();
- HPM->DataCheck = HPM_map_DataCheck;
- HPM->load_sub = HPM_map_plugin_load_sub;
HPM->symbol_defaults_sub = map_hp_symbols;
- HPM->grabHPDataSub = HPM_map_grabHPData;
for( i = 1; i < argc; i++ ) {
const char* arg = argv[i];
if( strcmp(arg, "--load-plugin") == 0 ) {
@@ -6000,6 +6095,7 @@ void map_defaults(void) {
// search and creation
map->get_new_object_id = map_get_new_object_id;
map->search_freecell = map_search_freecell;
+ map->closest_freecell = map_closest_freecell;
//
map->quit = map_quit;
// npc
diff --git a/src/map/map.h b/src/map/map.h
index dba565cc0..1766220af 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -444,6 +444,7 @@ typedef enum {
CELL_NOVENDING,
CELL_NOCHAT,
CELL_ICEWALL,
+ CELL_NOICEWALL,
} cell_t;
@@ -467,6 +468,7 @@ typedef enum {
CELL_CHKNOVENDING,
CELL_CHKNOCHAT,
CELL_CHKICEWALL,
+ CELL_CHKNOICEWALL,
} cell_chk;
@@ -484,7 +486,8 @@ struct mapcell {
landprotector : 1,
novending : 1,
nochat : 1,
- icewall : 1;
+ icewall : 1,
+ noicewall : 1;
#ifdef CELL_NOSTACK
int cell_bl; //Holds amount of bls in this cell.
@@ -658,13 +661,7 @@ struct map_data {
int jexp; // map experience multiplicator
int bexp; // map experience multiplicator
int nocommand; //Blocks @/# commands for non-gms. [Skotlex]
- /**
- * Ice wall reference counter for bugreport:3574
- * - since there are a thousand mobs out there in a lot of maps checking on,
- * - every targeting for icewall on attack path would just be a waste, so,
- * - this counter allows icewall checking be only run when there is a actual ice wall on the map
- **/
- int icewall_num;
+
// Instance Variables
int instance_id;
int instance_src_map;
@@ -853,7 +850,7 @@ struct map_interface {
int server_port;
char server_ip[32];
char server_id[32];
- char server_pw[32];
+ char server_pw[100];
char server_db[32];
Sql* mysql_handle;
@@ -920,11 +917,12 @@ struct map_interface {
int (*delblock) (struct block_list* bl);
int (*moveblock) (struct block_list *bl, int x1, int y1, int64 tick);
//blocklist nb in one cell
- int (*count_oncell) (int16 m,int16 x,int16 y,int type);
+ int (*count_oncell) (int16 m,int16 x,int16 y,int type,int flag);
struct skill_unit * (*find_skill_unit_oncell) (struct block_list* target,int16 x,int16 y,uint16 skill_id,struct skill_unit* out_unit, int flag);
// search and creation
int (*get_new_object_id) (void);
int (*search_freecell) (struct block_list *src, int16 m, int16 *x, int16 *y, int16 rx, int16 ry, int flag);
+ bool (*closest_freecell) (int16 m, int16 *x, int16 *y, int type, int flag);
//
int (*quit) (struct map_session_data *sd);
// npc
diff --git a/src/map/mob.c b/src/map/mob.c
index ffab804a6..2605b414f 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -52,7 +52,9 @@ struct mob_interface mob_s;
#define IDLE_SKILL_INTERVAL 10 //Active idle skills should be triggered every 1 second (1000/MIN_MOBTHINKTIME)
-#define MOB_LAZYSKILLPERC 0 // Probability for mobs far from players from doing their IDLE skill. (rate of 1000 minute)
+// Probability for mobs far from players from doing their IDLE skill. (rate of 1000 minute)
+// in Aegis, this is 100% for mobs that have been activated by players and none otherwise.
+#define MOB_LAZYSKILLPERC(md) (md->state.spotted?1000:0)
// Move probability for mobs away from players (rate of 1000 minute)
// in Aegis, this is 100% for mobs that have been activated by players and none otherwise.
#define MOB_LAZYMOVEPERC(md) ((md)->state.spotted?1000:0)
@@ -946,7 +948,7 @@ int mob_spawn (struct mob_data *md)
md->state.aggressive = md->status.mode&MD_ANGRY?1:0;
md->state.skillstate = MSS_IDLE;
- md->next_walktime = tick+rnd()%5000+1000;
+ md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME;
md->last_linktime = tick;
md->dmgtick = tick - 5000;
md->last_pcneartime = 0;
@@ -1074,15 +1076,6 @@ int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap)
((*target) == NULL || !check_distance_bl(&md->bl, *target, dist)) &&
battle->check_range(&md->bl,bl,md->db->range2)
) { //Pick closest target?
-
- if( map->list[bl->m].icewall_num &&
- !path->search_long(NULL,bl->m,md->bl.x,md->bl.y,bl->x,bl->y,CELL_CHKICEWALL) ) {
-
- if( !check_distance_bl(&md->bl, bl, status_get_range(&md->bl) ) )
- return 0;
-
- }
-
(*target) = bl;
md->target_id=bl->id;
md->min_chase= dist + md->db->range3;
@@ -1286,22 +1279,23 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) {
md->state.skillstate = MSS_IDLE;
case MSS_IDLE:
// Idle skill.
- if ((md->target_id || !(++md->ud.walk_count%IDLE_SKILL_INTERVAL)) &&
- mob->skill_use(md, tick, -1))
+ if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL) && mob->skill_use(md, tick, -1))
break;
//Random walk.
if (!md->master_id &&
DIFF_TICK(md->next_walktime, tick) <= 0 &&
!mob->randomwalk(md,tick))
//Delay next random walk when this one failed.
- md->next_walktime=tick+rnd()%3000;
+ md->next_walktime = tick+rnd()%1000;
break;
default:
mob_stop_attack(md);
- if (battle_config.mob_ai&0x8)
- mob_stop_walking(md,1); //Immediately stop chasing.
+ mob_stop_walking(md,1); //Stop chasing.
md->state.skillstate = MSS_IDLE;
- md->next_walktime=tick+rnd()%3000+3000;
+ if(battle_config.mob_ai&0x8) //Walk instantly after dropping target
+ md->next_walktime = tick+rnd()%1000;
+ else
+ md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME;
break;
}
if (md->target_id) {
@@ -1309,6 +1303,10 @@ int mob_unlocktarget(struct mob_data *md, int64 tick) {
md->ud.target_to = 0;
unit->set_target(&md->ud, 0);
}
+ if(map->count_oncell(md->bl.m, md->bl.x, md->bl.y, BL_CHAR|BL_NPC, 1) > battle_config.official_cell_stack_limit) {
+ unit->walktoxy(&md->bl, md->bl.x, md->bl.y, 8);
+ }
+
return 0;
}
/*==========================================
@@ -1328,6 +1326,7 @@ int mob_randomwalk(struct mob_data *md, int64 tick) {
d =12-md->move_fail_count;
if(d<5) d=5;
+ if(d>7) d=7;
for(i=0;i<retrycount;i++){ // Search of a movable place
int r=rnd();
x=r%(d*2+1)-d;
@@ -1335,7 +1334,7 @@ int mob_randomwalk(struct mob_data *md, int64 tick) {
x+=md->bl.x;
y+=md->bl.y;
- if((map->getcell(md->bl.m,x,y,CELL_CHKPASS)) && unit->walktoxy(&md->bl,x,y,1)){
+ if(((x != md->bl.x) || (y != md->bl.y)) && map->getcell(md->bl.m,x,y,CELL_CHKPASS) && unit->walktoxy(&md->bl,x,y,8)){
break;
}
}
@@ -1358,7 +1357,7 @@ int mob_randomwalk(struct mob_data *md, int64 tick) {
}
md->state.skillstate=MSS_WALK;
md->move_fail_count=0;
- md->next_walktime = tick+rnd()%3000+3000+c;
+ md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME+c;
return 1;
}
@@ -1404,9 +1403,6 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
if (md->ud.skilltimer != INVALID_TIMER)
return false;
- if(md->ud.walktimer != INVALID_TIMER && md->ud.walkpath.path_pos <= 3)
- return false;
-
// Abnormalities
if(( md->sc.opt1 > 0 && md->sc.opt1 != OPT1_STONEWAIT && md->sc.opt1 != OPT1_BURNING && md->sc.opt1 != OPT1_CRYSTALIZE )
|| md->sc.data[SC_DEEP_SLEEP] || md->sc.data[SC_BLADESTOP] || md->sc.data[SC__MANHOLE] || md->sc.data[SC_CURSEDCIRCLE_TARGET]) {
@@ -1434,10 +1430,13 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
|| ((TBL_PC*)tbl)->invincible_timer != INVALID_TIMER)
)
) {
- //Unlock current target.
+ //No valid target
if (mob->warpchase(md, tbl))
return true; //Chasing this target.
- mob->unlocktarget(md, tick-(battle_config.mob_ai&0x8?3000:0)); //Immediately do random walk.
+ if(md->ud.walktimer != INVALID_TIMER && (!can_move || md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh)
+ && (tbl || md->ud.walkpath.path_pos == 0))
+ return true; //Walk at least "mob_chase_refresh" cells before dropping the target unless target is non-existent
+ mob_unlocktarget(md, tick); //Unlock target
tbl = NULL;
}
}
@@ -1448,12 +1447,14 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
if( md->attacked_id == md->target_id )
{ //Rude attacked check.
if( !battle->check_range(&md->bl, tbl, md->status.rhw.range)
- && ( //Can't attack back and can't reach back.
+ && ( //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_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
- || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target.
- || !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH)
+ || md->sc.data[SC_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
+ || md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
+ || md->walktoxy_fail_count > 0)
)
+ || !mob->can_reach(md, tbl, md->min_chase, MSS_RUSH)
+ )
&& md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
&& !mob->skill_use(md, tick, MSC_RUDEATTACKED) // If can't rude Attack
&& can_move && unit->escape(&md->bl, tbl, rnd()%10 +1)) // Attempt escape
@@ -1471,10 +1472,12 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
|| (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 ...
&& ( // 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_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
- || md->sc.data[SC__MANHOLE])) // Not yet confirmed if boss will teleport once it can't reach target.
- || !mob->can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
+ (!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_WUGBITE] || md->sc.data[SC_VACUUM_EXTREME] || md->sc.data[SC_THORNS_TRAP]
+ || md->sc.data[SC__MANHOLE] // Not yet confirmed if boss will teleport once it can't reach target.
+ || md->walktoxy_fail_count > 0)
+ )
+ || !mob->can_reach(md, abl, dist+md->db->range3, MSS_RUSH)
)
)
) {
@@ -1547,7 +1550,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
}
}
- //This handles triggering idle walk/skill.
+ //This handles triggering idle/walk skill.
mob->unlocktarget(md, tick);
return true;
}
@@ -1604,48 +1607,56 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
mob->unlocktarget (md,tick);
return true;
}
+
//Attempt to attack.
//At this point we know the target is attackable, we just gotta check if the range matches.
- if (md->ud.target == tbl->id && md->ud.attacktimer != INVALID_TIMER) //Already locked.
+ if (battle->check_range(&md->bl, tbl, md->status.rhw.range) && !(md->sc.option&OPTION_HIDE))
+ { //Target within range and able to use normal attack, engage
+ if (md->ud.target != tbl->id || md->ud.attacktimer == INVALID_TIMER)
+ { //Only attack if no more attack delay left
+ if(tbl->type == BL_PC)
+ mob->log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus)
+
+ if( !(mode&MD_RANDOMTARGET) )
+ unit->attack(&md->bl,tbl->id,1);
+ else { // Attack once and find a new random target
+ int search_size = (view_range < md->status.rhw.range) ? view_range : md->status.rhw.range;
+ unit->attack(&md->bl,tbl->id, 0);
+ if ((tbl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size))) {
+ md->target_id = tbl->id;
+ md->min_chase = md->db->range3;
+ }
+ }
+ }
return true;
+ }
- if (battle->check_range (&md->bl, tbl, md->status.rhw.range))
- { //Target within range, engage
+ //Monsters in berserk state, unable to use normal attacks, will always attempt a skill
+ if(md->ud.walktimer == INVALID_TIMER && (md->state.skillstate == MSS_BERSERK || md->state.skillstate == MSS_ANGRY)) {
+ if (DIFF_TICK(md->ud.canmove_tick, tick) <= MIN_MOBTHINKTIME && DIFF_TICK(md->ud.canact_tick, tick) < -MIN_MOBTHINKTIME*IDLE_SKILL_INTERVAL)
+ { //Only use skill if able to walk on next tick and not used a skill the last second
+ mob->skill_use(md, tick, -1);
+ }
+ }
- if(tbl->type == BL_PC)
- mob->log_damage(md, tbl, 0); //Log interaction (counts as 'attacker' for the exp bonus)
+ //Target still in attack range, no need to chase the target
+ if(battle->check_range(&md->bl, tbl, md->status.rhw.range))
+ return true;
- if(!(mode&MD_RANDOMTARGET))
- unit->attack(&md->bl,tbl->id,1);
- else { // Attack once and find new random target
- int search_size = (view_range < md->status.rhw.range) ? view_range : md->status.rhw.range;
- unit->attack(&md->bl,tbl->id,0);
- tbl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md), search_size);
- // If no target was found, keep atacking the old one
- if( tbl ) {
- md->target_id = tbl->id;
- md->min_chase = md->db->range3;
- }
- }
+ //Only update target cell / drop target after having moved at least "mob_chase_refresh" cells
+ if(md->ud.walktimer != INVALID_TIMER && (!can_move || md->ud.walkpath.path_pos <= battle_config.mob_chase_refresh))
return true;
- }
//Out of range...
- if (!(mode&MD_CANMOVE))
- { //Can't chase. Attempt an idle skill before unlocking.
- md->state.skillstate = MSS_IDLE;
- if (!mob->skill_use(md, tick, -1))
+ if (!(mode&MD_CANMOVE) || (!can_move && DIFF_TICK(tick, md->ud.canmove_tick) > 0))
+ { //Can't chase. Immobile and trapped mobs should unlock target and use an idle skill.
+ if (md->ud.attacktimer == INVALID_TIMER)
+ { //Only unlock target if no more attack delay left
+ //This handles triggering idle/walk skill.
mob->unlocktarget(md,tick);
+ }
return true;
- }
-
- if (!can_move)
- { //Stuck. Attempt an idle skill
- md->state.skillstate = MSS_IDLE;
- if (!(++md->ud.walk_count%IDLE_SKILL_INTERVAL))
- mob->skill_use(md, tick, -1);
- return true;
- }
+ }
if (md->ud.walktimer != INVALID_TIMER && md->ud.target == tbl->id &&
(
@@ -1655,6 +1666,7 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
return true;
//Follow up if possible.
+ //Hint: Chase skills are handled in the walktobl routine
if(!mob->can_reach(md, tbl, md->min_chase, MSS_RUSH) ||
!unit->walktobl(&md->bl, tbl, md->status.rhw.range, 2))
mob->unlocktarget(md,tick);
@@ -1735,20 +1747,17 @@ int mob_ai_sub_lazy(struct mob_data *md, va_list args) {
}
if( DIFF_TICK(md->next_walktime,tick) < 0 && (status_get_mode(&md->bl)&MD_CANMOVE) && unit->can_move(&md->bl) ) {
- if( map->list[md->bl.m].users > 0 )
- {
- if( rnd()%1000 < MOB_LAZYMOVEPERC(md) )
- mob->randomwalk(md, tick);
- else
- if( rnd()%1000 < MOB_LAZYSKILLPERC ) //Chance to do a mob's idle skill.
- mob->skill_use(md, tick, -1);
- }
- else
- {
- if( rnd()%1000 < MOB_LAZYMOVEPERC(md) )
- mob->randomwalk(md, tick);
- }
+ if( rnd()%1000 < MOB_LAZYMOVEPERC(md) )
+ mob_randomwalk(md, tick);
+ }
+ else if( md->ud.walktimer == INVALID_TIMER )
+ {
+ //Because it is not unset when the mob finishes walking.
+ md->state.skillstate = MSS_IDLE;
+ if( rnd()%1000 < MOB_LAZYSKILLPERC(md) ) //Chance to do a mob's idle skill.
+ mob->skill_use(md, tick, -1);
}
+
return 0;
}
@@ -2641,7 +2650,7 @@ void mob_revive(struct mob_data *md, unsigned int hp)
int64 tick = timer->gettick();
md->state.skillstate = MSS_IDLE;
md->last_thinktime = tick;
- md->next_walktime = tick+rnd()%50+5000;
+ md->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME;
md->last_linktime = tick;
md->last_pcneartime = 0;
memset(md->dmglog, 0, sizeof(md->dmglog)); // Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris]
@@ -3711,6 +3720,10 @@ bool mob_parse_dbrow(char** str) {
if (mstatus->dex < 1) mstatus->dex = 1;
if (mstatus->luk < 1) mstatus->luk = 1;
+ //Tests showed that chase range is effectively 2 cells larger than expected [Playtester]
+ if (db->range3 > 0)
+ db->range3 += 2;
+
db->range2 = atoi(str[20]);
db->range3 = atoi(str[21]);
if (battle_config.view_range_rate != 100) {
diff --git a/src/map/mob.h b/src/map/mob.h
index 728f3d81c..f3937c0d1 100644
--- a/src/map/mob.h
+++ b/src/map/mob.h
@@ -16,7 +16,7 @@
// Change this to increase the table size in your mob_db to accommodate a larger mob database.
// Be sure to note that IDs 4001 to 4048 are reserved for advanced/baby/expanded classes.
// Notice that the last 1000 entries are used for player clones, so always set this to desired value +1000
-#define MAX_MOB_DB 4000
+#define MAX_MOB_DB 5000
//The number of drops all mobs have and the max drop-slot that the steal skill will attempt to steal from.
#define MAX_MOB_DROP 10
@@ -27,6 +27,8 @@
#define MIN_MOBTHINKTIME 100
//Min time before mobs do a check to call nearby friends for help (or for slaves to support their master)
#define MIN_MOBLINKTIME 1000
+//Min time between random walks
+#define MIN_RANDOMWALKTIME 4000
//Distance that slaves should keep from their master.
#define MOB_SLAVEDISTANCE 2
@@ -169,6 +171,7 @@ struct mob_data {
short move_fail_count;
short lootitem_count;
short min_chase;
+ unsigned char walktoxy_fail_count; //Pathfinding succeeds but the actual walking failed (e.g. Icewall lock)
int deletetimer;
int master_id,master_dist;
diff --git a/src/map/npc.c b/src/map/npc.c
index a33db6b99..7378ac470 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -1818,11 +1818,11 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) {
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)
+ if (itemdb_type(nameid) == IT_PETEGG) {
pet->create_egg(sd, nameid);
- else {
+ } else {
+ struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = nameid;
item_tmp.identify = 1;
@@ -1933,7 +1933,6 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st
for( i = 0; i < list_size; ++i ) {
int nameid = p->list[i].ITID;
int amount = p->list[i].qty;
- struct item item_tmp;
j = npc_market_qty[i];
@@ -1944,9 +1943,10 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st
npc->market_tosql(nd,j);
- if (itemdb_type(nameid) == IT_PETEGG)
+ if (itemdb_type(nameid) == IT_PETEGG) {
pet->create_egg(sd, nameid);
- else {
+ } else {
+ struct item item_tmp;
memset(&item_tmp,0,sizeof(item_tmp));
item_tmp.nameid = nameid;
item_tmp.identify = 1;
@@ -3324,8 +3324,8 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
struct event_data* ev = (struct event_data*)strdb_get(npc->ev_db, eventname);
struct npc_data *nd;
struct script_state *st;
- int i = 0, j = 0, k = 0;
- char *temp;
+ int i = 0, nargs = 0;
+ size_t len;
nullpo_ret(sd);
@@ -3353,27 +3353,29 @@ int npc_do_atcmd_event(struct map_session_data* sd, const char* command, const c
st = script->alloc_state(ev->nd->u.scr.script, ev->pos, sd->bl.id, ev->nd->bl.id);
script->setd_sub(st, NULL, ".@atcmd_command$", 0, (void *)command, NULL);
- // split atcmd parameters based on spaces
- temp = (char*)aMalloc(strlen(message) + 1);
-
- 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' ) {
- script->setd_sub( st, NULL, ".@atcmd_parameters$", j++, (void *)temp, NULL );
+ len = strlen(message);
+ if (len) {
+ char *temp, *p;
+ p = temp = aStrdup(message);
+ // Sanity check - Skip leading spaces (shouldn't happen)
+ while (i <= len && temp[i] == ' ') {
+ p++;
+ i++;
+ }
+ // split atcmd parameters based on spaces
+ while (i <= len) {
+ if (temp[i] != ' ' && temp[i] != '\0') {
+ i++;
+ continue;
}
- } else {
- temp[k] = message[i];
- k++;
+ temp[i] = '\0';
+ script->setd_sub(st, NULL, ".@atcmd_parameters$", nargs++, (void *)p, NULL);
+ i++;
+ p = temp + i;
}
+ aFree(temp);
}
-
- script->setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)h64BPTRSIZE(j), NULL);
- aFree(temp);
+ script->setd_sub(st, NULL, ".@atcmd_numparameters", 0, (void *)h64BPTRSIZE(nargs), NULL);
script->run_main(st);
return 0;
@@ -4179,9 +4181,6 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
if( strcmp(w1,"function") == 0 ) {
p = npc->parse_function(w1, w2, w3, w4, p, buffer, filepath, &success);
} else {
-#ifdef ENABLE_CASE_CHECK
- if( strcasecmp(w1, "function") == 0 ) DeprecationWarning("npc_parsesrcfile", w1, "function", filepath, strline(buffer, p-buffer)); // TODO
-#endif // ENABLE_CASE_CHECK
p = npc->parse_script(w1,w2,w3,w4, p, buffer, filepath,runOnInit?NPO_ONINIT:NPO_NONE, &success);
}
}
@@ -4206,22 +4205,6 @@ int npc_parsesrcfile(const char* filepath, bool runOnInit) {
}
else
{
-#ifdef ENABLE_CASE_CHECK
- if( strcasecmp(w2, "warp") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "warp", filepath, strline(buffer, p-buffer)); } // TODO
- else if( strcasecmp(w2,"shop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "shop", filepath, strline(buffer, p-buffer)); } // TODO
- else if( strcasecmp(w2,"cashshop") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "cashshop", filepath, strline(buffer, p-buffer)); } // TODO
- else if( strcasecmp(w2, "script") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "script", filepath, strline(buffer, p-buffer)); } // TODO
- else if( strcasecmp(w2,"trader") == 0 ) DeprecationWarning("npc_parsesrcfile", w2, "trader", filepath, strline(buffer, p-buffer)) // TODO
- else if( strncasecmp(w2, "duplicate", 9) == 0 ) {
- char temp[10];
- safestrncpy(temp, w2, 10);
- DeprecationWarning("npc_parsesrcfile", temp, "duplicate", filepath, strline(buffer, p-buffer)); // TODO
- }
- else if( strcasecmp(w2,"monster") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "monster", filepath, strline(buffer, p-buffer)); } // TODO:
- else if( strcasecmp(w2,"boss_monster") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "boss_monster", filepath, strline(buffer, p-buffer)); } // TODO
- else if( strcasecmp(w2, "mapflag") == 0 ) { DeprecationWarning("npc_parsesrcfile", w2, "mapflag", filepath, strline(buffer, p-buffer)); } // TODO
- else
-#endif // ENABLE_CASE_CHECK
ShowError("npc_parsesrcfile: Unable to parse, probably a missing or extra TAB in file '%s', line '%d'. Skipping line...\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,p-buffer), w1, w2, w3, w4);
p = strchr(p,'\n');// skip and continue
success = EXIT_FAILURE;
@@ -4293,7 +4276,7 @@ void npc_read_event_script(void)
script_event[i].event_count++;
#ifdef ENABLE_CASE_CHECK
} else if( p && strcasecmp(name, p) == 0 ) {
- DeprecationWarning2("npc_read_event_script", p, name, config[i].event_name); // TODO
+ DeprecationCaseWarning("npc_read_event_script", p, name, config[i].event_name); // TODO
#endif // ENABLE_CASE_CHECK
}
}
diff --git a/src/map/packets.h b/src/map/packets.h
index 810f341d4..3240a97a1 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -2767,6 +2767,121 @@ packet(0x020d,-1);
packet(0x09DF,7);
#endif
+// 2014-10-22bRagexe - YomRawr
+#if PACKETVER >= 20141022
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x08AD,5,clif->pChangeDir,2,4);
+ packet(0x094E,6,clif->pTakeItem,2);
+ packet(0x087D,6,clif->pDropItem,2,4);
+ packet(0x0878,8,clif->pMoveToKafra,2,4);
+ packet(0x08AA,8,clif->pMoveFromKafra,2,4);
+ packet(0x023B,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(0x0835,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0940,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0955,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x092B,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x093B,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0896,26,clif->pPartyInvite2,2);
+ // packet(0x08AB,4); // CZ_GANGSI_RANK
+ packet(0x091A,26,clif->pFriendsListAdd,2);
+ packet(0x0899,5,clif->pHomMenu,2,4);
+ packet(0x0438,36,clif->pStoragePassword,0);
+#endif
+
+// 2014-10-16aRagexe - YomRawr
+#if PACKETVER >= 20141016
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x0967,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(0x022D,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(0x0838,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0835,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0365,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x0363,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x086E,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0802,26,clif->pPartyInvite2,2);
+ // packet(0x0922,4); // CZ_GANGSI_RANK
+ packet(0x094B,26,clif->pFriendsListAdd,2);
+ packet(0x0364,5,clif->pHomMenu,2,4);
+ packet(0x0936,36,clif->pStoragePassword,0);
+ packet(0x09DF,7);
+ packet(0x0a00,269);
+#endif
+
+// 2014-10-22bRagexe - YomRawr
+#if PACKETVER >= 20141022
+ packet(0x0369,7,clif->pActionRequest,2,6);
+ packet(0x083C,10,clif->pUseSkillToId,2,4,6);
+ packet(0x0437,5,clif->pWalkToXY,2);
+ packet(0x035F,6,clif->pTickSend,2);
+ packet(0x08AD,5,clif->pChangeDir,2,4);
+ packet(0x094E,6,clif->pTakeItem,2);
+ packet(0x087D,6,clif->pDropItem,2,4);
+ packet(0x0878,8,clif->pMoveToKafra,2,4);
+ packet(0x08AA,8,clif->pMoveFromKafra,2,4);
+ packet(0x023B,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(0x0835,12,clif->pSearchStoreInfoListItemClick,2,6,10);
+ packet(0x0940,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x0819,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0811,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x0360,6,clif->pReqClickBuyingStore,2);
+ packet(0x0817,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0815,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ packet(0x0955,18,clif->pPartyBookingRegisterReq,2,4);
+ // packet(0x092B,8); // CZ_JOIN_BATTLE_FIELD
+ packet(0x0281,-1,clif->pItemListWindowSelected,2,4,8);
+ packet(0x093B,19,clif->pWantToConnection,2,6,10,14,18);
+ packet(0x0896,26,clif->pPartyInvite2,2);
+ // packet(0x08AB,4); // CZ_GANGSI_RANK
+ packet(0x091A,26,clif->pFriendsListAdd,2);
+ packet(0x0899,5,clif->pHomMenu,2,4);
+ packet(0x0438,36,clif->pStoragePassword,0);
+#endif
+
+/* Roulette System [Yommy/Hercules] */
+#if PACKETVER >= 20141016
+ packet(0x0A19,2,clif->pRouletteOpen,0); // HEADER_CZ_REQ_OPEN_ROULETTE
+ packet(0x0A1A,23); // HEADER_ZC_ACK_OPEN_ROULETTE
+ packet(0x0A1B,2,clif->pRouletteInfo,0); // HEADER_CZ_REQ_ROULETTE_INFO
+ packet(0x0A1C,-1); // HEADER_ZC_ACK_ROULEITTE_INFO
+ packet(0x0A1D,2,clif->pRouletteClose,0); // HEADER_CZ_REQ_CLOSE_ROULETTE
+ packet(0x0A1E,3); // HEADER_ZC_ACK_CLOSE_ROULETTE
+ packet(0x0A1F,2,clif->pRouletteGenerate,0); // HEADER_CZ_REQ_GENERATE_ROULETTE
+ packet(0x0A20,21); // HEADER_ZC_ACK_GENERATE_ROULETTE
+ packet(0x0A21,3,clif->pRouletteRecvItem,2); // HEADER_CZ_RECV_ROULETTE_ITEM
+ packet(0x0A22,5); // HEADER_ZC_RECV_ROULETTE_ITEM
+#endif
+
/* PacketKeys: http://hercules.ws/board/topic/1105-hercules-wpe-free-june-14th-patch/ */
#if PACKETVER >= 20110817
packetKeys(0x053D5CED,0x3DED6DED,0x6DED6DED); /* Thanks to Shakto */
@@ -2998,6 +3113,18 @@ packet(0x020d,-1);
packetKeys(0x04810281,0x42814281,0x42814281); /* Themon */
#endif
+#if PACKETVER >= 20141022
+ packetKeys(0x290551EA,0x2B952C75,0x2D67669B); /* YomRawr */
+#endif
+
+#if PACKETVER >= 20141016
+ packetKeys(0x2DFF467C,0x444B37EE,0x2C1B634F); /* YomRawr */
+#endif
+
+#if PACKETVER >= 20141022
+ packetKeys(0x290551EA,0x2B952C75,0x2D67669B); /* YomRawr */
+#endif
+
#if defined(OBFUSCATIONKEY1) && defined(OBFUSCATIONKEY2) && defined(OBFUSCATIONKEY3)
packetKeys(OBFUSCATIONKEY1,OBFUSCATIONKEY2,OBFUSCATIONKEY3);
#endif
diff --git a/src/map/packets_struct.h b/src/map/packets_struct.h
index b32baf53a..1c6deab96 100644
--- a/src/map/packets_struct.h
+++ b/src/map/packets_struct.h
@@ -77,8 +77,10 @@ enum packet_headers {
#endif
#if PACKETVER < 20080102
authokType = 0x73,
-#else
+#elif PACKETVER < 20141022
authokType = 0x2eb,
+#else
+ authokType = 0xa18,
#endif
script_clearType = 0x8d6,
package_item_announceType = 0x7fd,
@@ -209,6 +211,10 @@ enum packet_headers {
#else
wisendType = 0x98,
#endif
+ partyleaderchangedType = 0x7fc,
+ rouletteinfoackType = 0xa1c,
+ roulettgenerateackType = 0xA20,
+ roulettercvitemackType = 0xA22,
};
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
@@ -297,6 +303,9 @@ struct packet_authok {
#if PACKETVER >= 20080102
short font;
#endif
+#if PACKETVER >= 20141022
+ unsigned char sex;
+#endif
} __attribute__((packed));
struct packet_monster_hp {
@@ -761,6 +770,58 @@ struct packet_banking_withdraw_ack {
int Balance;
} __attribute__((packed));
+/* Roulette System [Yommy/Hercules] */
+struct packet_roulette_open_ack {
+ short PacketType;
+ char Result;
+ int Serial;
+ char Step;
+ char Idx;
+ short AdditionItemID;
+ int GoldPoint;
+ int SilverPoint;
+ int BronzePoint;
+} __attribute__((packed));
+
+struct packet_roulette_info_ack {
+ short PacketType;
+ short PacketLength;
+ unsigned int RouletteSerial;
+ struct {
+ unsigned short Row;
+ unsigned short Position;
+ unsigned short ItemId;
+ unsigned short Count;
+ } ItemInfo[42];
+} __attribute__((packed));
+
+struct packet_roulette_close_ack {
+ short PacketType;
+ unsigned char Result;
+} __attribute__((packed));
+
+struct packet_roulette_generate_ack {
+ short PacketType;
+ unsigned char Result;
+ unsigned short Step;
+ unsigned short Idx;
+ unsigned short AdditionItemID;
+ int RemainGold;
+ int RemainSilver;
+ int RemainBronze;
+} __attribute__((packed));
+
+struct packet_roulette_itemrecv_req {
+ short PacketType;
+ unsigned char Condition;
+} __attribute__((packed));
+
+struct packet_roulette_itemrecv_ack {
+ short PacketType;
+ unsigned char Result;
+ unsigned short AdditionItemID;
+} __attribute__((packed));
+
struct packet_itemlist_normal {
short PacketType;
short PacketLength;
@@ -959,6 +1020,13 @@ struct packet_wis_end {
} __attribute__((packed));
+struct packet_party_leader_changed {
+ short PacketType;
+ unsigned int prev_leader_aid;
+ unsigned int new_leader_aid;
+} __attribute__((packed));
+
+
#if !defined(sun) && (!defined(__NETBSD__) || __NetBSD_Version__ >= 600000000) // NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
#pragma pack(pop)
#endif // not NetBSD < 6 / Solaris
diff --git a/src/map/party.c b/src/map/party.c
index 7cf340edb..f4a5c870a 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -686,12 +686,10 @@ 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->message(p->data[mi].sd->fd, msg_txt(284));
-
p->party.member[tmi].leader = 1;
- if (p->data[tmi].sd->fd)
- clif->message(p->data[tmi].sd->fd, msg_txt(285));
+
+ /** update members **/
+ clif->PartyLeaderChanged(p->data[mi].sd, p->data[mi].sd->status.account_id, p->data[tmi].sd->status.account_id);
//Update info.
intif->party_leaderchange(p->party.party_id,p->party.member[tmi].account_id,p->party.member[tmi].char_id);
diff --git a/src/map/path.c b/src/map/path.c
index 5a9ddf9c7..9aeb108fa 100644
--- a/src/map/path.c
+++ b/src/map/path.c
@@ -10,6 +10,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <math.h>
#include "map.h"
#include "../common/cbasetypes.h"
@@ -128,9 +129,6 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
spd->x[0] = x0;
spd->y[0] = y0;
- if (md->getcellp(md,x1,y1,cell))
- return false;
-
if (dx > abs(dy)) {
weight = dx;
spd->ry = 1;
@@ -141,8 +139,6 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
while (x0 != x1 || y0 != y1)
{
- if (md->getcellp(md,x0,y0,cell))
- return false;
wx += dx;
wy += dy;
if (wx >= weight) {
@@ -162,6 +158,8 @@ bool path_search_long(struct shootpath_data *spd,int16 m,int16 x0,int16 y0,int16
spd->y[spd->len] = y0;
spd->len++;
}
+ if (md->getcellp(md,x0,y0,cell))
+ return false;
}
return true;
@@ -176,7 +174,7 @@ static void heap_push_node(struct node_heap *heap, struct path_node *node)
{
#ifndef __clang_analyzer__ // TODO: Figure out why clang's static analyzer doesn't like this
BHEAP_ENSURE(*heap, 1, 256);
- BHEAP_PUSH(*heap, node, NODE_MINTOPCMP, swap_ptr);
+ BHEAP_PUSH2(*heap, node, NODE_MINTOPCMP, swap_ptr);
#endif // __clang_analyzer__
}
@@ -189,8 +187,7 @@ static int heap_update_node(struct node_heap *heap, struct path_node *node)
ShowError("heap_update_node: node not found\n");
return 1;
}
- BHEAP_POPINDEX(*heap, i, NODE_MINTOPCMP, swap_ptr);
- BHEAP_PUSH(*heap, node, NODE_MINTOPCMP, swap_ptr);
+ BHEAP_UPDATE(*heap, i, NODE_MINTOPCMP, swap_ptr);
return 0;
}
@@ -251,12 +248,8 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
return false;
md = &map->list[m];
-#ifdef CELL_NOSTACK
//Do not check starting cell as that would get you stuck.
- if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys)
-#else
if (x0 < 0 || x0 >= md->xs || y0 < 0 || y0 >= md->ys /*|| md->getcellp(md,x0,y0,cell)*/)
-#endif
return false;
// Check destination cell
@@ -304,7 +297,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
// A* (A-star) pathfinding
// We always use A* for finding walkpaths because it is what game client uses.
// Easy pathfinding cuts corners of non-walkable cells, but client always walks around it.
-
+
BHEAP_STRUCT_VAR(node_heap, open_set); // 'Open' set
// FIXME: This array is too small to ensure all paths shorter than MAX_WALKPATH
@@ -327,8 +320,8 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
tp[i].flag = SET_OPEN;
heap_push_node(&open_set, &tp[i]); // Put start node to 'open' set
- for(;;)
- {
+
+ for(;;) {
int e = 0; // error flag
// Saves allowed directions for the current cell. Diagonal directions
@@ -347,7 +340,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
}
current = BHEAP_PEEK(open_set); // Look for the lowest f_cost node in the 'open' set
- BHEAP_POP(open_set, NODE_MINTOPCMP, swap_ptr); // Remove it from 'open' set
+ BHEAP_POP2(open_set, NODE_MINTOPCMP, swap_ptr); // Remove it from 'open' set
x = current->x;
y = current->y;
@@ -367,24 +360,22 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
#define chk_dir(d) ((allowed_dirs & (d)) == (d))
// Process neighbors of current node
- // TODO: Processing order affects chosen path if there is more than one path with same cost.
- // In few cases path found by server will be different than path found by game client.
- if (chk_dir(DIR_SOUTH))
- e += add_path(&open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4
- if (chk_dir(DIR_SOUTH|DIR_WEST) && !md->getcellp(md, x-1, y-1, cell))
- e += add_path(&open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3
- if (chk_dir(DIR_WEST))
- e += add_path(&open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2
- if (chk_dir(DIR_NORTH|DIR_WEST) && !md->getcellp(md, x-1, y+1, cell))
- e += add_path(&open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1
- if (chk_dir(DIR_NORTH))
- e += add_path(&open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0
- if (chk_dir(DIR_NORTH|DIR_EAST) && !md->getcellp(md, x+1, y+1, cell))
- e += add_path(&open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7
- if (chk_dir(DIR_EAST))
- e += add_path(&open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6
if (chk_dir(DIR_SOUTH|DIR_EAST) && !md->getcellp(md, x+1, y-1, cell))
e += add_path(&open_set, tp, x+1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y-1, x1, y1)); // (x+1, y-1) 5
+ if (chk_dir(DIR_EAST))
+ e += add_path(&open_set, tp, x+1, y, g_cost + MOVE_COST, current, heuristic(x+1, y, x1, y1)); // (x+1, y) 6
+ if (chk_dir(DIR_NORTH|DIR_EAST) && !md->getcellp(md, x+1, y+1, cell))
+ e += add_path(&open_set, tp, x+1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x+1, y+1, x1, y1)); // (x+1, y+1) 7
+ if (chk_dir(DIR_NORTH))
+ e += add_path(&open_set, tp, x, y+1, g_cost + MOVE_COST, current, heuristic(x, y+1, x1, y1)); // (x, y+1) 0
+ if (chk_dir(DIR_NORTH|DIR_WEST) && !md->getcellp(md, x-1, y+1, cell))
+ e += add_path(&open_set, tp, x-1, y+1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y+1, x1, y1)); // (x-1, y+1) 1
+ if (chk_dir(DIR_WEST))
+ e += add_path(&open_set, tp, x-1, y, g_cost + MOVE_COST, current, heuristic(x-1, y, x1, y1)); // (x-1, y) 2
+ if (chk_dir(DIR_SOUTH|DIR_WEST) && !md->getcellp(md, x-1, y-1, cell))
+ e += add_path(&open_set, tp, x-1, y-1, g_cost + MOVE_DIAGONAL_COST, current, heuristic(x-1, y-1, x1, y1)); // (x-1, y-1) 3
+ if (chk_dir(DIR_SOUTH))
+ e += add_path(&open_set, tp, x, y-1, g_cost + MOVE_COST, current, heuristic(x, y-1, x1, y1)); // (x, y-1) 4
#undef chk_dir
if (e) {
BHEAP_CLEAR(open_set);
@@ -413,7 +404,7 @@ bool path_search(struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x
//Distance functions, taken from http://www.flipcode.com/articles/article_fastdistance.shtml
-int check_distance(int dx, int dy, int distance)
+bool check_distance(int dx, int dy, int distance)
{
#ifdef CIRCULAR_AREA
//In this case, we just do a square comparison. Add 1 tile grace for diagonal range checks.
@@ -453,6 +444,42 @@ unsigned int distance(int dx, int dy)
return (dx<dy?dy:dx);
#endif
}
+
+/**
+ * The client uses a circular distance instead of the square one. The circular distance
+ * is only used by units sending their attack commands via the client (not monsters).
+ * @param dx: Horizontal distance
+ * @param dy: Vertical distance
+ * @param distance: Distance to check against
+ * @return Within distance(1); Not within distance(0);
+ */
+bool check_distance_client(int dx, int dy, int distance)
+{
+ if(distance < 0) distance = 0;
+
+ return (path->distance_client(dx,dy) <= distance);
+}
+
+/**
+ * The client uses a circular distance instead of the square one. The circular distance
+ * is only used by units sending their attack commands via the client (not monsters).
+ * @param dx: Horizontal distance
+ * @param dy: Vertical distance
+ * @return Circular distance
+ */
+int distance_client(int dx, int dy)
+{
+ double temp_dist = sqrt((double)(dx*dx + dy*dy));
+
+ //Bonus factor used by client
+ //This affects even horizontal/vertical lines so they are one cell longer than expected
+ temp_dist -= 0.0625;
+
+ if(temp_dist < 0) temp_dist = 0;
+
+ return ((int)temp_dist);
+}
+
void path_defaults(void) {
path = &path_s;
@@ -461,4 +488,6 @@ void path_defaults(void) {
path->search = path_search;
path->check_distance = check_distance;
path->distance = distance;
+ path->check_distance_client = check_distance_client;
+ path->distance_client = distance_client;
}
diff --git a/src/map/path.h b/src/map/path.h
index 8d02e6558..4b71f2189 100644
--- a/src/map/path.h
+++ b/src/map/path.h
@@ -32,6 +32,14 @@ struct shootpath_data {
#define distance_blxy(bl, x1, y1) (path->distance((bl)->x - (x1), (bl)->y - (y1)))
#define distance_xy(x0, y0, x1, y1) (path->distance((x0) - (x1), (y0) - (y1)))
+#define check_distance_client_bl(bl1, bl2, distance) (path->check_distance_client((bl1)->x - (bl2)->x, (bl1)->y - (bl2)->y, distance))
+#define check_distance_client_blxy(bl, x1, y1, distance) (path->check_distance_client((bl)->x-(x1), (bl)->y-(y1), distance))
+#define check_distance_client_xy(x0, y0, x1, y1, distance) (path->check_distance_client((x0)-(x1), (y0)-(y1), distance))
+
+#define distance_client_bl(bl1, bl2) (path->distance_client((bl1)->x - (bl2)->x, (bl1)->y - (bl2)->y))
+#define distance_client_blxy(bl, x1, y1) (path->distance_client((bl)->x-(x1), (bl)->y-(y1)))
+#define distance_client_xy(x0, y0, x1, y1) (path->distance_client((x0)-(x1), (y0)-(y1)))
+
struct path_interface {
// calculates destination cell for knockback
int (*blownpos) (int16 m, int16 x0, int16 y0, int16 dx, int16 dy, int count);
@@ -39,8 +47,10 @@ struct path_interface {
bool (*search) (struct walkpath_data *wpd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, int flag, cell_chk cell);
// tries to find a shootable path
bool (*search_long) (struct shootpath_data *spd, int16 m, int16 x0, int16 y0, int16 x1, int16 y1, cell_chk cell);
- int (*check_distance) (int dx, int dy, int distance);
+ bool (*check_distance) (int dx, int dy, int distance);
unsigned int (*distance) (int dx, int dy);
+ bool (*check_distance_client) (int dx, int dy, int distance);
+ int (*distance_client) (int dx, int dy);
};
struct path_interface *path;
diff --git a/src/map/pc.c b/src/map/pc.c
index 5fc4e3ddf..1dc032f7c 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -1320,7 +1320,7 @@ int pc_reg_received(struct map_session_data *sd)
clif->pLoadEndAck(sd->fd, sd);
}
- if( sd->sc.option & OPTION_INVISIBLE ) {
+ if (pc_isinvisible(sd)) {
sd->vd.class_ = INVISIBLE_CLASS;
clif->message(sd->fd, msg_txt(11)); // Invisible: On
// decrement the number of pvp players on the map
@@ -1729,7 +1729,7 @@ int pc_disguise(struct map_session_data *sd, int class_) {
if (class_ >= 0 && sd->disguise == class_)
return 0;
- if(sd->sc.option&OPTION_INVISIBLE) { //Character is invisible. Stealth class-change. [Skotlex]
+ if (pc_isinvisible(sd)) { //Character is invisible. Stealth class-change. [Skotlex]
sd->disguise = class_; //viewdata is set on uncloaking.
return 2;
}
@@ -3102,11 +3102,11 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
}
if(sd->skillfixcastrate[i].id == type2)
- sd->skillfixcastrate[i].val += val;
+ sd->skillfixcastrate[i].val -= val;
else {
sd->skillfixcastrate[i].id = type2;
- sd->skillfixcastrate[i].val = val;
+ sd->skillfixcastrate[i].val -= val;
}
break;
@@ -4474,7 +4474,7 @@ int pc_useitem(struct map_session_data *sd,int n) {
} else {// not yet used item (all slots are initially empty)
sd->item_delay[i].nameid = nameid;
}
- if( !(nameid == ITEMID_REINS_OF_MOUNT && sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR)) )
+ if (!(nameid == ITEMID_REINS_OF_MOUNT && pc_hasmount(sd)))
sd->item_delay[i].tick = tick + sd->inventory_data[n]->delay;
} else {// should not happen
ShowError("pc_useitem: Exceeded item delay array capacity! (nameid=%d, char_id=%d)\n", nameid, sd->status.char_id);
@@ -4731,7 +4731,7 @@ void pc_bound_clear(struct map_session_data *sd, enum e_item_bound_type type) {
ShowError("Helllo! You reached pc_bound_clear for IBT_ACCOUNT, unfortunately no scenario was expected for this!\n");
break;
case IBT_GUILD: {
- struct guild_storage *gstor = gstorage->id2storage(sd->status.guild_id);
+ struct guild_storage *gstor = idb_get(gstorage->db,sd->status.guild_id);
for( i = 0; i < MAX_INVENTORY; i++ ){
if(sd->status.inventory[i].bound == type) {
@@ -7639,6 +7639,10 @@ int pc_itemheal(struct map_session_data *sd,int itemid, int hp,int sp)
// Recovery Potion
if( sd->sc.data[SC_HEALPLUS] )
hp += (int)(hp * sd->sc.data[SC_HEALPLUS]->val1/100.);
+
+ // 2014 Halloween Event : Pumpkin Bonus
+ if ( sd->sc.data[SC_MTF_PUMPKIN] && itemid == ITEMID_PUMPKIN )
+ hp += (int)(hp * sd->sc.data[SC_MTF_PUMPKIN]->val1/100);
}
if(sp) {
bonus = 100 + (sd->battle_status.int_<<1)
@@ -8149,48 +8153,111 @@ int pc_setcart(struct map_session_data *sd,int type) {
return 0;
}
-/*==========================================
- * Give player a falcon
- *------------------------------------------*/
-int pc_setfalcon(TBL_PC* sd, int flag)
+/* FIXME: These setter methods are inconsistent in their class/skill checks.
+ They should be changed so that they all either do or skip the checks.*/
+
+/**
+ * Gives/removes a falcon.
+ *
+ * The target player needs the required skills in order to obtain a falcon.
+ *
+ * @param sd Target player.
+ * @param flag New state.
+ **/
+void pc_setfalcon(TBL_PC* sd, bool flag)
{
- if( flag ){
- if( pc->checkskill(sd,HT_FALCON)>0 ) // add falcon if he have the skill
+ if (flag) {
+ if (pc->checkskill(sd,HT_FALCON) > 0) // add falcon if he have the skill
pc->setoption(sd,sd->sc.option|OPTION_FALCON);
- } else if( pc_isfalcon(sd) ){
+ } else if (pc_isfalcon(sd)) {
pc->setoption(sd,sd->sc.option&~OPTION_FALCON); // remove falcon
}
-
- return 0;
}
-/*==========================================
- * Set player riding
- *------------------------------------------*/
-int pc_setriding(TBL_PC* sd, int flag)
+/**
+ * Mounts/dismounts a Peco or Gryphon.
+ *
+ * The target player needs the required skills in order to mount a peco.
+ *
+ * @param sd Target player.
+ * @param flag New state.
+ **/
+void pc_setridingpeco(TBL_PC* sd, bool flag)
{
- if( flag ){
- if( pc->checkskill(sd,KN_RIDING) > 0 ) // add peco
+ if (flag) {
+ if (pc->checkskill(sd, KN_RIDING))
pc->setoption(sd, sd->sc.option|OPTION_RIDING);
- } else if( pc_isriding(sd) ){
- pc->setoption(sd, sd->sc.option&~OPTION_RIDING);
+ } else if (pc_isridingpeco(sd)) {
+ pc->setoption(sd, sd->sc.option&~OPTION_RIDING);
}
-
- return 0;
}
/**
- * Gives player a mado
- * @param flag 1 Set mado
+ * Gives/removes a Mado Gear.
+ *
+ * The target player needs to be the correct class in order to obtain a mado gear.
+ *
+ * @param sd Target player.
+ * @param flag New state.
**/
-void pc_setmadogear( struct map_session_data *sd, int flag ) {
- if( flag ) {
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC )
+void pc_setmadogear(struct map_session_data *sd, bool flag)
+{
+ if (flag) {
+ if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC)
pc->setoption(sd, sd->sc.option|OPTION_MADOGEAR);
- } else if( pc_ismadogear(sd) )
+ } else if (pc_ismadogear(sd)) {
pc->setoption(sd, sd->sc.option&~OPTION_MADOGEAR);
+ }
+}
- return;
+/**
+ * Mounts/dismounts a dragon.
+ *
+ * The target player needs the required skills in order to mount a dragon.
+ *
+ * @param sd Target player.
+ * @param type New state. This must be a valid OPTION_DRAGON* or 0.
+ **/
+void pc_setridingdragon(TBL_PC* sd, unsigned int type)
+{
+ if (type&OPTION_DRAGON) {
+ // Ensure only one dragon is set at a time.
+ if (type&OPTION_DRAGON1)
+ type = OPTION_DRAGON1;
+ else if (type&OPTION_DRAGON2)
+ type = OPTION_DRAGON2;
+ else if (type&OPTION_DRAGON3)
+ type = OPTION_DRAGON3;
+ else if (type&OPTION_DRAGON4)
+ type = OPTION_DRAGON4;
+ else if (type&OPTION_DRAGON5)
+ type = OPTION_DRAGON5;
+ else
+ type = OPTION_DRAGON1;
+
+ if (pc->checkskill(sd, RK_DRAGONTRAINING))
+ pc->setoption(sd, (sd->sc.option&~OPTION_DRAGON)|type);
+ } else if (pc_isridingdragon(sd)) {
+ pc->setoption(sd,sd->sc.option&~OPTION_DRAGON); // remove dragon
+ }
+}
+
+/**
+ * Mounts/dismounts a wug.
+ *
+ * The target player needs the required skills in order to mount a wug.
+ *
+ * @param sd Target player.
+ * @param flag New state.
+ **/
+void pc_setridingwug(TBL_PC* sd, bool flag)
+{
+ if (flag) {
+ if (pc->checkskill(sd, RA_WUGRIDER) > 0)
+ pc->setoption(sd,sd->sc.option|OPTION_WUGRIDER);
+ } else if (pc_isridingwug(sd)) {
+ pc->setoption(sd,sd->sc.option&~OPTION_WUGRIDER); // remove wug
+ }
}
/**
@@ -9116,8 +9183,15 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
//OnUnEquip script [Skotlex]
if (sd->inventory_data[n]) {
- if (sd->inventory_data[n]->unequip_script)
- script->run(sd->inventory_data[n]->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
+ if (sd->inventory_data[n]->unequip_script) {
+ if ( battle_config.unequip_restricted_equipment & 1 ) {
+ ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, i, map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid);
+ if ( i == map->list[sd->bl.m].zone->disabled_items_count )
+ script->run(sd->inventory_data[n]->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
+ }
+ else
+ script->run(sd->inventory_data[n]->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
+ }
if(itemdb_isspecial(sd->status.inventory[n].card[0]))
; //No cards
else {
@@ -9127,8 +9201,16 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
continue;
if ( ( data = itemdb->exists(sd->status.inventory[n].card[i]) ) != NULL ) {
- if( data->unequip_script )
- script->run(data->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
+ if ( data->unequip_script ) {
+ if ( battle_config.unequip_restricted_equipment & 2 ) {
+ int j;
+ ARR_FIND(0, map->list[sd->bl.m].zone->disabled_items_count, j, map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[n].card[i]);
+ if ( j == map->list[sd->bl.m].zone->disabled_items_count )
+ script->run(data->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
+ }
+ else
+ script->run(data->unequip_script,0,sd->bl.id,npc->fake_nd->bl.id);
+ }
}
}
@@ -9203,7 +9285,7 @@ int pc_checkitem(struct map_session_data *sd)
}
if (sd->guild) {
- struct guild_storage *guild_storage = gstorage->id2storage2(sd->guild->guild_id);
+ struct guild_storage *guild_storage = idb_get(gstorage->db,sd->guild->guild_id);
if (guild_storage) {
for( i = 0; i < MAX_GUILD_STORAGE; i++ ) {
id = guild_storage->items[i].nameid;
@@ -9284,8 +9366,8 @@ int pc_calc_pvprank_sub(struct block_list *bl,va_list ap)
sd1=(struct map_session_data *)bl;
sd2=va_arg(ap,struct map_session_data *);
- if( sd1->sc.option&OPTION_INVISIBLE || sd2->sc.option&OPTION_INVISIBLE )
- {// cannot register pvp rank for hidden GMs
+ if (pc_isinvisible(sd1) ||pc_isinvisible(sd2)) {
+ // cannot register pvp rank for hidden GMs
return 0;
}
@@ -9319,8 +9401,8 @@ int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
sd->pvp_timer = INVALID_TIMER;
- if( sd->sc.option&OPTION_INVISIBLE )
- {// do not calculate the pvp rank for a hidden GM
+ if (pc_isinvisible(sd)) {
+ // do not calculate the pvp rank for a hidden GM
return 0;
}
@@ -10958,8 +11040,10 @@ void pc_defaults(void) {
pc->setoption = pc_setoption;
pc->setcart = pc_setcart;
pc->setfalcon = pc_setfalcon;
- pc->setriding = pc_setriding;
+ pc->setridingpeco = pc_setridingpeco;
pc->setmadogear = pc_setmadogear;
+ pc->setridingdragon = pc_setridingdragon;
+ pc->setridingwug = pc_setridingwug;
pc->changelook = pc_changelook;
pc->equiplookall = pc_equiplookall;
diff --git a/src/map/pc.h b/src/map/pc.h
index c36704b4f..e613feec5 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -543,6 +543,13 @@ struct map_session_data {
bool vars_ok;
bool vars_dirty;
+ struct {
+ short stage;
+ short prizeIdx;
+ short prizeStage;
+ bool claimPrize;
+ } roulette;
+
// temporary debugging of bug #3504
const char* delunit_prevfile;
int delunit_prevline;
@@ -589,19 +596,20 @@ struct map_session_data {
#endif
#define pc_isfalcon(sd) ( (sd)->sc.option&OPTION_FALCON )
-#define pc_isriding(sd) ( (sd)->sc.option&OPTION_RIDING )
#define pc_isinvisible(sd) ( (sd)->sc.option&OPTION_INVISIBLE )
#define pc_is50overweight(sd) ( (sd)->weight*100 >= (sd)->max_weight*battle->bc->natural_heal_weight_rate )
#define pc_is90overweight(sd) ( (sd)->weight*10 >= (sd)->max_weight*9 )
#define pc_maxparameter(sd) ( (((sd)->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO || ((sd)->class_&MAPID_UPPERMASK) == MAPID_REBELLION || ((sd)->class_&MAPID_THIRDMASK) == MAPID_SUPER_NOVICE_E) ? battle->bc->max_extended_parameter : (sd)->class_&JOBL_THIRD ? ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_third_parameter : battle->bc->max_third_parameter) : ((sd)->class_&JOBL_BABY ? battle->bc->max_baby_parameter : battle->bc->max_parameter) )
-/**
- * Ranger
- **/
+/// Generic check for mounts
+#define pc_hasmount(sd) ( (sd)->sc.option&(OPTION_RIDING|OPTION_WUGRIDER|OPTION_DRAGON|OPTION_MADOGEAR) )
+/// Knight classes Peco / Gryphon
+#define pc_isridingpeco(sd) ( (sd)->sc.option&(OPTION_RIDING) )
+/// Ranger Warg
#define pc_iswug(sd) ( (sd)->sc.option&OPTION_WUG )
#define pc_isridingwug(sd) ( (sd)->sc.option&OPTION_WUGRIDER )
-// Mechanic Magic Gear
+/// Mechanic Magic Gear
#define pc_ismadogear(sd) ( (sd)->sc.option&OPTION_MADOGEAR )
-// Rune Knight Dragon
+/// Rune Knight Dragon
#define pc_isridingdragon(sd) ( (sd)->sc.option&OPTION_DRAGON )
#define pc_stop_walking(sd, type) (unit->stop_walking(&(sd)->bl, (type)))
@@ -897,9 +905,11 @@ struct pc_interface {
int (*jobchange) (struct map_session_data *sd,int job, int upper);
int (*setoption) (struct map_session_data *sd,int type);
int (*setcart) (struct map_session_data* sd, int type);
- int (*setfalcon) (struct map_session_data* sd, int flag);
- int (*setriding) (struct map_session_data* sd, int flag);
- void (*setmadogear) (struct map_session_data* sd, int flag);
+ void (*setfalcon) (struct map_session_data *sd, bool flag);
+ void (*setridingpeco) (struct map_session_data *sd, bool flag);
+ void (*setmadogear) (struct map_session_data *sd, bool flag);
+ void (*setridingdragon) (struct map_session_data *sd, unsigned int type);
+ void (*setridingwug) (struct map_session_data *sd, bool flag);
int (*changelook) (struct map_session_data *sd,int type,int val);
int (*equiplookall) (struct map_session_data *sd);
diff --git a/src/map/pet.c b/src/map/pet.c
index 9275a6de5..d90727b97 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -821,7 +821,7 @@ int pet_randomwalk(struct pet_data *pd, int64 tick) {
else
c+=pd->status.speed;
}
- pd->next_walktime = tick+rnd()%3000+3000+c;
+ pd->next_walktime = tick+rnd()%1000+MIN_RANDOMWALKTIME+c;
return 1;
}
diff --git a/src/map/script.c b/src/map/script.c
index f46ee78fe..5e368e0ad 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -526,7 +526,7 @@ int script_add_str(const char* p)
}
}
if( existingentry ) {
- DeprecationWarning2("script_add_str", p, existingentry, script->parser_current_file); // TODO
+ DeprecationCaseWarning("script_add_str", p, existingentry, script->parser_current_file); // TODO
}
#endif // ENABLE_CASE_CHECK
@@ -772,6 +772,8 @@ const char* parse_callfunc(const char* p, int require_paren, int is_custom)
script->addl(func);
script->addc(C_ARG);
arg = script->buildin[script->str_data[func].val];
+ if (script->str_data[func].deprecated)
+ DeprecationWarning(p);
if( !arg ) arg = &null_arg; // Use a dummy, null string
} else if( script->str_data[func].type == C_USERFUNC || script->str_data[func].type == C_USERFUNC_POS ) {
// script defined function
@@ -1349,7 +1351,7 @@ const char* parse_curly_close(const char* p)
char label[256];
int l;
// Remove temporary variables
- sprintf(label,"set $@__SW%x_VAL,0;",script->syntax.curly[pos].index);
+ sprintf(label,"__setr $@__SW%x_VAL,0;",script->syntax.curly[pos].index);
script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
script->parse_line(label);
script->syntax.curly_count--;
@@ -1431,10 +1433,6 @@ const char* parse_syntax(const char* p)
// Closing decision if, for , while
p = script->parse_syntax_close(p + 1);
return p;
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 5 && strncasecmp(p, "break", 5) == 0 ) {
- disp_deprecation_message("parse_syntax", "break", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
break;
case 'c':
@@ -1506,7 +1504,7 @@ const char* parse_syntax(const char* p)
disp_error_message("parse_syntax: dup 'case'",p);
linkdb_insert(&script->syntax.curly[pos].case_label, (void*)h64BPTRSIZE(v), (void*)1);
- sprintf(label,"set $@__SW%x_VAL,0;",script->syntax.curly[pos].index);
+ sprintf(label,"__setr $@__SW%x_VAL,0;",script->syntax.curly[pos].index);
script->syntax.curly[script->syntax.curly_count++].type = TYPE_NULL;
script->parse_line(label);
@@ -1545,12 +1543,6 @@ const char* parse_syntax(const char* p)
//Closing decision if, for , while
p = script->parse_syntax_close(p + 1);
return p;
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 4 && strncasecmp(p, "case", 4) == 0 ) {
- disp_deprecation_message("parse_syntax", "case", p); // TODO
- } else if( p2 - p == 8 && strncasecmp(p, "continue", 8) == 0 ) {
- disp_deprecation_message("parse_syntax", "continue", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
break;
case 'd':
@@ -1604,12 +1596,6 @@ const char* parse_syntax(const char* p)
script->set_label(l,script->pos,p);
script->syntax.curly_count++;
return p;
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 7 && strncasecmp(p, "default", 7) == 0 ) {
- disp_deprecation_message("parse_syntax", "default", p); // TODO
- } else if( p2 - p == 2 && strncasecmp(p, "do", 2) == 0 ) {
- disp_deprecation_message("parse_syntax", "do", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
break;
case 'f':
@@ -1647,7 +1633,7 @@ const char* parse_syntax(const char* p)
} else {
// Skip to the end point if the condition is false
sprintf(label,"__FR%x_FIN",script->syntax.curly[pos].index);
- script->addl(script->add_str("jump_zero"));
+ script->addl(script->add_str("__jump_zero"));
script->addc(C_ARG);
p=script->parse_expr(p);
p=script->skip_space(p);
@@ -1749,12 +1735,6 @@ const char* parse_syntax(const char* p)
{
disp_error_message("expect ';' or '{' at function syntax",p);
}
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 3 && strncasecmp(p, "for", 3) == 0 ) {
- disp_deprecation_message("parse_syntax", "for", p); // TODO
- } else if( p2 - p == 8 && strncasecmp(p, "function", 8) == 0 ) {
- disp_deprecation_message("parse_syntax", "function", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
break;
case 'i':
@@ -1772,17 +1752,13 @@ const char* parse_syntax(const char* p)
script->syntax.curly[script->syntax.curly_count].flag = 0;
sprintf(label,"__IF%x_%x",script->syntax.curly[script->syntax.curly_count].index,script->syntax.curly[script->syntax.curly_count].count);
script->syntax.curly_count++;
- script->addl(script->add_str("jump_zero"));
+ script->addl(script->add_str("__jump_zero"));
script->addc(C_ARG);
p=script->parse_expr(p);
p=script->skip_space(p);
script->addl(script->add_str(label));
script->addc(C_FUNC);
return p;
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 2 && strncasecmp(p, "if", 2) == 0 ) {
- disp_deprecation_message("parse_syntax", "if", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
break;
case 's':
@@ -1800,7 +1776,7 @@ const char* parse_syntax(const char* p)
script->syntax.curly[script->syntax.curly_count].flag = 0;
sprintf(label,"$@__SW%x_VAL",script->syntax.curly[script->syntax.curly_count].index);
script->syntax.curly_count++;
- script->addl(script->add_str("set"));
+ script->addl(script->add_str("__setr"));
script->addc(C_ARG);
script->addl(script->add_str(label));
p=script->parse_expr(p);
@@ -1810,10 +1786,6 @@ const char* parse_syntax(const char* p)
}
script->addc(C_FUNC);
return p + 1;
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 6 && strncasecmp(p, "switch", 6) == 0 ) {
- disp_deprecation_message("parse_syntax", "switch", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
break;
case 'w':
@@ -1837,17 +1809,13 @@ const char* parse_syntax(const char* p)
// Skip to the end point if the condition is false
sprintf(label,"__WL%x_FIN",script->syntax.curly[script->syntax.curly_count].index);
script->syntax.curly_count++;
- script->addl(script->add_str("jump_zero"));
+ script->addl(script->add_str("__jump_zero"));
script->addc(C_ARG);
p=script->parse_expr(p);
p=script->skip_space(p);
script->addl(script->add_str(label));
script->addc(C_FUNC);
return p;
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 5 && strncasecmp(p, "while", 5) == 0 ) {
- disp_deprecation_message("parse_syntax", "while", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
break;
}
@@ -1909,7 +1877,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
disp_error_message("need '('",p);
}
sprintf(label,"__IF%x_%x",script->syntax.curly[pos].index,script->syntax.curly[pos].count);
- script->addl(script->add_str("jump_zero"));
+ script->addl(script->add_str("__jump_zero"));
script->addc(C_ARG);
p=script->parse_expr(p);
p=script->skip_space(p);
@@ -1917,10 +1885,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
script->addc(C_FUNC);
*flag = 0;
return p;
-#ifdef ENABLE_CASE_CHECK
- } else if( p2 - p == 2 && strncasecmp(p, "if", 2) == 0 ) {
- disp_deprecation_message("parse_syntax", "if", p); // TODO
-#endif // ENABLE_CASE_CHECK
} else {
// else
if(!script->syntax.curly[pos].flag) {
@@ -1929,10 +1893,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
return p;
}
}
-#ifdef ENABLE_CASE_CHECK
- } else if( !script->syntax.curly[pos].flag && p2 - p == 4 && strncasecmp(p, "else", 4) == 0 ) {
- disp_deprecation_message("parse_syntax", "else", p); // TODO
-#endif // ENABLE_CASE_CHECK
}
// Close if
script->syntax.curly_count--;
@@ -1959,9 +1919,6 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
p = script->skip_space(p);
p2 = script->skip_word(p);
if( p2 - p != 5 || strncmp(p, "while", 5) != 0 ) {
-#ifdef ENABLE_CASE_CHECK
- if( p2 - p == 5 && strncasecmp(p, "while", 5) == 0 ) disp_deprecation_message("parse_syntax", "while", p); // TODO
-#endif // ENABLE_CASE_CHECK
disp_error_message("parse_syntax: need 'while'",p);
}
@@ -1974,7 +1931,7 @@ const char* parse_syntax_close_sub(const char* p,int* flag)
script->parse_nextline(false, p);
sprintf(label,"__DO%x_FIN",script->syntax.curly[pos].index);
- script->addl(script->add_str("jump_zero"));
+ script->addl(script->add_str("__jump_zero"));
script->addc(C_ARG);
p=script->parse_expr(p);
p=script->skip_space(p);
@@ -5681,7 +5638,7 @@ BUILDIN(copyarray);
/// The value is converted to the type of the variable.
///
/// set(<variable>,<value>) -> <variable>
-BUILDIN(setr) {
+BUILDIN(__setr) {
TBL_PC* sd = NULL;
struct script_data* data;
//struct script_data* datavalue;
@@ -5691,7 +5648,7 @@ BUILDIN(setr) {
data = script_getdata(st,2);
//datavalue = script_getdata(st,3);
- if( !data_isreference(data) || reference_toconstant(data) ) {
+ if (!data_isreference(data) || reference_toconstant(data)) {
ShowError("script:set: not a variable\n");
script->reportdata(script_getdata(st,2));
st->state = END;
@@ -5702,9 +5659,9 @@ BUILDIN(setr) {
name = reference_getname(data);
prefix = *name;
- if( not_server_variable(prefix) ) {
+ if (not_server_variable(prefix)) {
sd = script->rid2sd(st);
- if( sd == NULL ) {
+ if (sd == NULL) {
ShowError("script:set: no player attached for player variable '%s'\n", name);
return true;
}
@@ -5712,19 +5669,19 @@ BUILDIN(setr) {
#if 0
// TODO: see de43fa0f73be01080bd11c08adbfb7c158324c81
- if( data_isreference(datavalue) ) {
+ if (data_isreference(datavalue)) {
// the value being referenced is a variable
const char* namevalue = reference_getname(datavalue);
- if( !not_array_variable(*namevalue) ) {
+ if (!not_array_variable(*namevalue)) {
// array variable being copied into another array variable
- if( sd == NULL && not_server_variable(*namevalue) && !(sd = script->rid2sd(st)) ) {
+ 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 true;
}
- if( is_string_variable(namevalue) != is_string_variable(name) ) {
+ 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 true;
@@ -5739,9 +5696,9 @@ BUILDIN(setr) {
}
#endif
- if( script_hasdata(st, 4) ) {
+ if (script_hasdata(st, 4)) {
// Optional argument used by post-increment/post-decrement constructs to return the previous value
- if( is_string_variable(name) ) {
+ if (is_string_variable(name)) {
script_pushstrcopy(st, script_getstr(st, 4));
} else {
script_pushint(st, script_getnum(st, 4));
@@ -5751,7 +5708,7 @@ BUILDIN(setr) {
script_pushcopy(st,2);
}
- if( is_string_variable(name) )
+ if (is_string_variable(name))
script->set_reg(st,sd,num,name,(void*)script_getstr(st,3),script_getref(st,2));
else
script->set_reg(st,sd,num,name,(void*)h64BPTRSIZE(script_getnum(st,3)),script_getref(st,2));
@@ -7013,28 +6970,25 @@ BUILDIN(delitem) {
TBL_PC *sd;
struct item it;
- if( script_hasdata(st,4) )
- {
+ if (script_hasdata(st,4)) {
int account_id = script_getnum(st,4);
sd = map->id2sd(account_id); // <account id>
- if( sd == NULL )
- {
+ if (sd == NULL) {
ShowError("script:delitem: player not found (AID=%d).\n", account_id);
st->state = END;
return false;
}
- }
- else
- {
+ } else {
sd = script->rid2sd(st);// attached player
- if( sd == NULL )
+ if (sd == NULL)
return true;
}
- if( script_isstringtype(st, 2) ) {
+ memset(&it, 0, sizeof(it));
+ if (script_isstringtype(st, 2)) {
const char* item_name = script_getstr(st, 2);
struct item_data* id = itemdb->search_name(item_name);
- if( id == NULL ) {
+ if (id == NULL) {
ShowError("script:delitem: unknown item \"%s\".\n", item_name);
st->state = END;
return false;
@@ -7042,8 +6996,7 @@ BUILDIN(delitem) {
it.nameid = id->nameid;// "<item name>"
} else {
it.nameid = script_getnum(st, 2);// <item id>
- if( !itemdb->exists( it.nameid ) )
- {
+ if (!itemdb->exists(it.nameid)) {
ShowError("script:delitem: unknown item \"%d\".\n", it.nameid);
st->state = END;
return false;
@@ -7074,26 +7027,25 @@ BUILDIN(delitem2) {
TBL_PC *sd;
struct item it;
- if( script_hasdata(st,11) ) {
+ if (script_hasdata(st,11)) {
int account_id = script_getnum(st,11);
sd = map->id2sd(account_id); // <account id>
- if( sd == NULL ) {
+ if (sd == NULL) {
ShowError("script:delitem2: player not found (AID=%d).\n", account_id);
st->state = END;
return false;
}
- }
- else
- {
+ } else {
sd = script->rid2sd(st);// attached player
if( sd == NULL )
return true;
}
- if( script_isstringtype(st, 2) ) {
+ memset(&it, 0, sizeof(it));
+ if (script_isstringtype(st, 2)) {
const char* item_name = script_getstr(st, 2);
struct item_data* id = itemdb->search_name(item_name);
- if( id == NULL ) {
+ if (id == NULL) {
ShowError("script:delitem2: unknown item \"%s\".\n", item_name);
st->state = END;
return false;
@@ -7658,6 +7610,29 @@ BUILDIN(getbrokenid)
}
/*==========================================
+ * getbrokencount
+ *------------------------------------------*/
+BUILDIN(getbrokencount)
+{
+ int i, counter = 0;
+ TBL_PC *sd;
+
+ sd = script->rid2sd(st);
+
+ if (sd == NULL)
+ return true;
+
+ for (i = 0; i < MAX_INVENTORY; i++) {
+ if (sd->status.inventory[i].attribute)
+ counter++;
+ }
+
+ script_pushint(st, counter);
+
+ return true;
+}
+
+/*==========================================
* repair [Valaris]
*------------------------------------------*/
BUILDIN(repair)
@@ -8612,10 +8587,10 @@ BUILDIN(checkfalcon)
TBL_PC* sd;
sd = script->rid2sd(st);
- if( sd == NULL )
+ if (sd == NULL)
return true;// no player attached, report source
- if( pc_isfalcon(sd) )
+ if (pc_isfalcon(sd))
script_pushint(st, 1);
else
script_pushint(st, 0);
@@ -8630,15 +8605,15 @@ BUILDIN(checkfalcon)
/// setfalcon;
BUILDIN(setfalcon)
{
- int flag = 1;
+ bool flag = true;
TBL_PC* sd;
sd = script->rid2sd(st);
- if( sd == NULL )
+ if (sd == NULL)
return true;// no player attached, report source
- if( script_hasdata(st,2) )
- flag = script_getnum(st,2);
+ if (script_hasdata(st,2))
+ flag = script_getnum(st,2) ? true : false;
pc->setfalcon(sd, flag);
@@ -8655,10 +8630,10 @@ BUILDIN(checkriding)
TBL_PC* sd;
sd = script->rid2sd(st);
- if( sd == NULL )
- return true;// no player attached, report source
+ if (sd == NULL)
+ return true; // no player attached, report source
- if( pc_isriding(sd) || pc_isridingwug(sd) || pc_isridingdragon(sd) )
+ if (pc_hasmount(sd))
script_pushint(st, 1);
else
script_pushint(st, 0);
@@ -8677,12 +8652,143 @@ BUILDIN(setriding)
TBL_PC* sd;
sd = script->rid2sd(st);
- if( sd == NULL )
+
+ if (sd == NULL)
return true;// no player attached, report source
- if( script_hasdata(st,2) )
+ if (script_hasdata(st,2))
flag = script_getnum(st,2);
- pc->setriding(sd, flag);
+ pc->setridingpeco(sd, flag ? true : false);
+
+ return true;
+}
+
+enum setmount_type {
+ SETMOUNT_TYPE_AUTODETECT = -1,
+ SETMOUNT_TYPE_NONE = 0,
+ SETMOUNT_TYPE_PECO = 1,
+ SETMOUNT_TYPE_WUG = 2,
+ SETMOUNT_TYPE_MADO = 3,
+ SETMOUNT_TYPE_DRAGON_GREEN = 4,
+ SETMOUNT_TYPE_DRAGON_BROWN = 5,
+ SETMOUNT_TYPE_DRAGON_GRAY = 6,
+ SETMOUNT_TYPE_DRAGON_BLUE = 7,
+ SETMOUNT_TYPE_DRAGON_RED = 8,
+ SETMOUNT_TYPE_MAX,
+ SETMOUNT_TYPE_DRAGON = SETMOUNT_TYPE_DRAGON_GREEN,
+};
+
+/**
+ * Checks if the player is riding a combat mount.
+ *
+ * Returns 0 if the player isn't riding, and non-zero if it is.
+ * The exact returned values are the same used as flag in setmount, except for
+ * dragons, where SETMOUNT_TYPE_DRAGON is returned, regardless of color.
+ */
+BUILDIN(checkmount)
+{
+ TBL_PC* sd;
+
+ sd = script->rid2sd(st);
+ if (sd == NULL)
+ return true; // no player attached, report source
+
+ if (!pc_hasmount(sd)) {
+ script_pushint(st, SETMOUNT_TYPE_NONE);
+ } else if (pc_isridingpeco(sd)) {
+ script_pushint(st, SETMOUNT_TYPE_PECO);
+ } else if (pc_isridingwug(sd)) {
+ script_pushint(st, SETMOUNT_TYPE_WUG);
+ } else if (pc_ismadogear(sd)) {
+ script_pushint(st, SETMOUNT_TYPE_MADO);
+ } else { // if (pc_isridingdragon(sd))
+ script_pushint(st, SETMOUNT_TYPE_DRAGON);
+ }
+
+ return true;
+}
+
+/**
+ * Mounts or dismounts a combat mount.
+ *
+ * setmount <flag>;
+ * setmount;
+ *
+ * Accepted values for flag:
+ * MOUNT_NONE - dismount
+ * MOUNT_PECO - Peco Peco / Grand Peco / Gryphon (depending on the class)
+ * MOUNT_WUG - Wug (Rider)
+ * MOUNT_MADO - Mado Gear
+ * MOUNT_DRAGON - Dragon (default color)
+ * MOUNT_DRAGON_GREEN - Green Dragon
+ * MOUNT_DRAGON_BROWN - Brown Dragon
+ * MOUNT_DRAGON_GRAY - Gray Dragon
+ * MOUNT_DRAGON_BLUE - Blue Dragon
+ * MOUNT_DRAGON_RED - Red Dragon
+ *
+ * If an invalid value or no flag is specified, the appropriate mount is
+ * auto-detected. As a result of this, there is no need to specify a flag at
+ * all, unless it is a dragon color other than green.
+ */
+BUILDIN(setmount)
+{
+ int flag = SETMOUNT_TYPE_AUTODETECT;
+ TBL_PC* sd;
+
+ sd = script->rid2sd(st);
+
+ if (sd == NULL)
+ return true;// no player attached, report source
+
+ if (script_hasdata(st,2))
+ flag = script_getnum(st,2);
+
+ // Color variants for Rune Knight dragon mounts.
+ if (flag != SETMOUNT_TYPE_NONE) {
+ if (flag < SETMOUNT_TYPE_AUTODETECT || flag >= SETMOUNT_TYPE_MAX) {
+ ShowWarning("script_setmount: Unknown flag %d specified. Using auto-detected value.\n", flag);
+ flag = SETMOUNT_TYPE_AUTODETECT;
+ }
+ // Sanity checks and auto-detection
+ if ((sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT) {
+ if (pc->checkskill(sd, RK_DRAGONTRAINING)) {
+ // Rune Knight (Dragon)
+ unsigned int option;
+ option = ( flag == SETMOUNT_TYPE_DRAGON_GREEN ? OPTION_DRAGON1 :
+ flag == SETMOUNT_TYPE_DRAGON_BROWN ? OPTION_DRAGON2 :
+ flag == SETMOUNT_TYPE_DRAGON_GRAY ? OPTION_DRAGON3 :
+ flag == SETMOUNT_TYPE_DRAGON_RED ? OPTION_DRAGON4 :
+ flag == SETMOUNT_TYPE_DRAGON_RED ? OPTION_DRAGON5 :
+ OPTION_DRAGON1); // default value
+ pc->setridingdragon(sd, option);
+ }
+ } else if ((sd->class_&MAPID_THIRDMASK) == MAPID_RANGER) {
+ // Ranger (Warg)
+ if (pc->checkskill(sd, RA_WUGRIDER))
+ pc->setridingwug(sd, true);
+ } else if ((sd->class_&MAPID_THIRDMASK) == MAPID_MECHANIC) {
+ // Mechanic (Mado Gear)
+ if (pc->checkskill(sd, NC_MADOLICENCE))
+ pc->setmadogear(sd, true);
+ } else {
+ // Knight / Crusader (Peco Peco)
+ if (pc->checkskill(sd, KN_RIDING))
+ pc->setridingpeco(sd, true);
+ }
+ } else if (pc_hasmount(sd)) {
+ if (pc_isridingdragon(sd)) {
+ pc->setridingdragon(sd, 0);
+ }
+ if (pc_isridingwug(sd)) {
+ pc->setridingwug(sd, false);
+ }
+ if (pc_ismadogear(sd)) {
+ pc->setmadogear(sd, false);
+ }
+ if (pc_isridingpeco(sd)) {
+ pc->setridingpeco(sd, false);
+ }
+ }
return true;
}
@@ -8734,15 +8840,15 @@ BUILDIN(checkmadogear)
/// setmadogear;
BUILDIN(setmadogear)
{
- int flag = 1;
+ bool flag = true;
TBL_PC* sd;
sd = script->rid2sd(st);
- if( sd == NULL )
+ if (sd == NULL)
return true;// no player attached, report source
- if( script_hasdata(st,2) )
- flag = script_getnum(st,2);
+ if (script_hasdata(st,2))
+ flag = script_getnum(st,2) ? true : false;
pc->setmadogear(sd, flag);
return true;
@@ -13094,14 +13200,14 @@ BUILDIN(checkequipedcard)
return true;
}
-BUILDIN(jump_zero)
+BUILDIN(__jump_zero)
{
int sel;
sel=script_getnum(st,2);
- if(!sel) {
+ if (!sel) {
int pos;
- if( !data_islabel(script_getdata(st,3)) ) {
- ShowError("script: jump_zero: not label !\n");
+ if (!data_islabel(script_getdata(st,3))) {
+ ShowError("script: jump_zero: not a label !\n");
st->state=END;
return false;
}
@@ -14499,7 +14605,7 @@ BUILDIN(replacestr)
}
if(script_hasdata(st, 6)) {
- if (!script_isinttype(st, 5) || (count = script_getnum(st, 6) == 0)) {
+ if (!script_isinttype(st, 6) || (count = script_getnum(st, 6)) == 0) {
ShowError("script:replacestr: Invalid count value. Expected int.\n");
st->state = END;
return false;
@@ -14729,6 +14835,36 @@ BUILDIN(distance)
// <--- [zBuffer] List of mathematics commands
+BUILDIN(min)
+{
+ int i, min;
+
+ min = script_getnum(st, 2);
+ for (i = 3; script_hasdata(st, i); i++) {
+ int next = script_getnum(st, i);
+ if (next < min)
+ min = next;
+ }
+ script_pushint(st, min);
+
+ return true;
+}
+
+BUILDIN(max)
+{
+ int i, max;
+
+ max = script_getnum(st, 2);
+ for (i = 3; script_hasdata(st, i); i++) {
+ int next = script_getnum(st, i);
+ if (next > max)
+ max = next;
+ }
+ script_pushint(st, max);
+
+ return true;
+}
+
BUILDIN(md5)
{
const char *tmpstr;
@@ -15658,8 +15794,6 @@ BUILDIN(unittalk) {
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->message(((TBL_PC*)bl)->fd, StrBuf->Value(&sbuf));
StrBuf->Destroy(&sbuf);
}
@@ -16283,21 +16417,45 @@ BUILDIN(setquest) {
BUILDIN(erasequest) {
struct map_session_data *sd = script->rid2sd(st);
+ int quest_id;
if( sd == NULL )
return false;
- quest->delete(sd, script_getnum(st, 2));
+ if (script_hasdata(st, 3)) {
+ if (script_getnum(st, 3) < script_getnum(st, 2)) {
+ ShowError("buildin_erasequest: The second quest id must be greater than the id of the first.\n");
+ return false;
+ }
+ for (quest_id = script_getnum(st, 2); quest_id < script_getnum(st, 3); quest_id++) {
+ quest->delete(sd, quest_id);
+ }
+ } else {
+ quest->delete(sd, script_getnum(st, 2));
+ }
+
return true;
}
BUILDIN(completequest) {
struct map_session_data *sd = script->rid2sd(st);
+ int quest_id;
if( sd == NULL )
return false;
- quest->update_status(sd, script_getnum(st, 2), Q_COMPLETE);
+ if (script_hasdata(st, 3)) {
+ if (script_getnum(st, 3) < script_getnum(st, 2)) {
+ ShowError("buildin_completequest: The second quest id must be greater than the id of the first.\n");
+ return false;
+ }
+ for (quest_id = script_getnum(st, 2); quest_id < script_getnum(st, 3); quest_id++) {
+ quest->update_status(sd, quest_id, Q_COMPLETE);
+ }
+ } else {
+ quest->update_status(sd, script_getnum(st, 2), Q_COMPLETE);
+ }
+
return true;
}
@@ -16311,6 +16469,8 @@ BUILDIN(changequest) {
return true;
}
+// Deprecated
+// Please use questprogress instead.
BUILDIN(checkquest) {
struct map_session_data *sd = script->rid2sd(st);
enum quest_check_type type = HAVEQUEST;
@@ -16326,6 +16486,50 @@ BUILDIN(checkquest) {
return true;
}
+BUILDIN(questactive) {
+ struct map_session_data *sd = script->rid2sd(st);
+ int quest_progress = 0;
+
+ if (sd == NULL)
+ return false;
+
+ if (quest->check(sd, script_getnum(st, 2), HAVEQUEST) == Q_ACTIVE)
+ script_pushint(st, 1);
+ else
+ script_pushint(st, 0);
+
+ script_pushint(st, quest_progress);
+
+ return true;
+}
+
+BUILDIN(questprogress) {
+ struct map_session_data *sd = script->rid2sd(st);
+ enum quest_check_type type = HAVEQUEST;
+ int quest_progress = 0;
+
+ if (sd == NULL)
+ return false;
+
+ if (script_hasdata(st, 3))
+ type = (enum quest_check_type)script_getnum(st, 3);
+
+ quest_progress = quest->check(sd, script_getnum(st, 2), type);
+
+ // "Fix" returned quest state value to make more sense.
+ // 0 = Not Started, 1 = In Progress, 2 = Completed.
+ if (quest_progress == -1) // Not found
+ quest_progress = 0;
+ else if (quest_progress == 0 || quest_progress == 1)
+ quest_progress = 1;
+ else
+ quest_progress = 2;
+
+ script_pushint(st, quest_progress);
+
+ return true;
+}
+
BUILDIN(showevent) {
TBL_PC *sd = script->rid2sd(st);
struct npc_data *nd = map->id2nd(st->oid);
@@ -17271,9 +17475,10 @@ BUILDIN(setdragon) {
}
/**
- * ismounting() returns 1 if mounting a new mount or 0 otherwise
+ * hascashmount() returns 1 if mounting a cash mount or 0 otherwise
**/
-BUILDIN(ismounting) {
+BUILDIN(hascashmount)
+{
TBL_PC* sd;
if( (sd = script->rid2sd(st)) == NULL )
return true;
@@ -17285,20 +17490,22 @@ BUILDIN(ismounting) {
}
/**
- * setmounting() returns 1 on success or 0 otherwise
- * - Toggles new mounts on a player when he can mount
- * - 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
+ * setcashmount() returns 1 on success or 0 otherwise
+ *
+ * - Toggles cash mounts on a player when he can mount
+ * - Will fail if the player is already riding a standard mount e.g. dragon, peco, wug, mado, etc.
+ * - Will unmount the player is he is already mounting a cash mount
**/
-BUILDIN(setmounting) {
+BUILDIN(setcashmount)
+{
TBL_PC* sd;
- if( (sd = script->rid2sd(st)) == NULL )
+ if ((sd = script->rid2sd(st)) == NULL)
return true;
- if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) {
+ if (pc_hasmount(sd)) {
clif->msgtable(sd->fd, 0X78b);
script_pushint(st,0);//can't mount with one of these
} else {
- if( sd->sc.data[SC_ALL_RIDING] )
+ if (sd->sc.data[SC_ALL_RIDING])
status_change_end(&sd->bl, SC_ALL_RIDING, INVALID_TIMER);
else
sc_start(NULL,&sd->bl, SC_ALL_RIDING, 100, 0, -1);
@@ -17306,6 +17513,7 @@ BUILDIN(setmounting) {
}
return true;
}
+
/**
* Retrieves quantity of arguments provided to callfunc/callsub.
* getargcount() -> amount of arguments received in a function
@@ -17788,6 +17996,7 @@ BUILDIN(montransform) {
struct block_list* bl;
char msg[CHAT_SIZE_MAX];
int mob_id, val1, val2, val3, val4;
+ val1 = val2 = val3 = val4 = 0;
if( (bl = map->id2bl(st->rid)) == NULL )
return true;
@@ -17807,12 +18016,17 @@ BUILDIN(montransform) {
}
tick = script_getnum(st, 3);
- type = (sc_type)script_getnum(st, 4);
- val1 = val2 = val3 = val4 = 0;
- if( !(type > SC_NONE && type < SC_MAX) ) {
- ShowWarning("buildin_montransform: Unsupported status change id %d\n", type);
- return false;
+ if (script_hasdata(st, 4))
+ type = (sc_type)script_getnum(st, 4);
+ else
+ type = SC_NONE;
+
+ if (script_hasdata(st, 4)) {
+ if( !(type > SC_NONE && type < SC_MAX) ) {
+ ShowWarning("buildin_montransform: Unsupported status change id %d\n", type);
+ return false;
+ }
}
if (script_hasdata(st, 5))
@@ -17848,8 +18062,11 @@ BUILDIN(montransform) {
clif->ShowScript(&sd->bl, msg);
status_change_end(bl, SC_MONSTER_TRANSFORM, INVALID_TIMER); // Clear previous
sc_start2(NULL, bl, SC_MONSTER_TRANSFORM, 100, mob_id, type, tick);
- sc_start4(NULL, bl, type, 100, val1, val2, val3, val4, tick);
+
+ if (script_hasdata(st, 4))
+ sc_start4(NULL, bl, type, 100, val1, val2, val3, val4, tick);
}
+
return true;
}
@@ -18739,7 +18956,7 @@ bool script_add_builtin(const struct script_function *buildin, bool override) {
script->buildin[offset] = NULL;
} else {
// Adding new function
- if( strcmp(buildin->name, "setr") == 0 ) script->buildin_set_ref = n;
+ if( strcmp(buildin->name, "__setr") == 0 ) script->buildin_set_ref = n;
else if( strcmp(buildin->name, "callsub") == 0 ) script->buildin_callsub_ref = n;
else if( strcmp(buildin->name, "callfunc") == 0 ) script->buildin_callfunc_ref = n;
else if( strcmp(buildin->name, "getelementofarray") == 0 ) script->buildin_getelementofarray_ref = n;
@@ -18755,6 +18972,7 @@ bool script_add_builtin(const struct script_function *buildin, bool override) {
}
script->str_data[n].func = buildin->func;
+ script->str_data[n].deprecated = (buildin->deprecated ? 1 : 0);
/* we only store the arguments, its the only thing used out of this */
if( slen ) {
@@ -18772,13 +18990,20 @@ bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)
buildin.name = name;
buildin.arg = args;
buildin.func = func;
+ buildin.deprecated = false;
return script->add_builtin(&buildin, true);
}
-#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args }
-#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args }
+#define BUILDIN_DEF(x,args) { buildin_ ## x , #x , args, false }
+#define BUILDIN_DEF2(x,x2,args) { buildin_ ## x , x2 , args, false }
+#define BUILDIN_DEF_DEPRECATED(x,args) { buildin_ ## x , #x , args, true }
+#define BUILDIN_DEF2_DEPRECATED(x,x2,args) { buildin_ ## x , x2 , args, true }
void script_parse_builtin(void) {
struct script_function BUILDIN[] = {
+ /* Commands for internal use by the script engine */
+ BUILDIN_DEF(__jump_zero,"il"),
+ BUILDIN_DEF(__setr,"rv?"),
+
// NPC interaction
BUILDIN_DEF(mes,"s*"),
BUILDIN_DEF(next,""),
@@ -18803,8 +19028,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(warpguild,"siii"), // [Fredzilla]
BUILDIN_DEF(setlook,"ii"),
BUILDIN_DEF(changelook,"ii"), // Simulates but don't Store it
- BUILDIN_DEF2(setr,"set","rv"),
- BUILDIN_DEF(setr,"rv?"), // Not meant to be used directly, required for var++/var--
+ BUILDIN_DEF2(__setr,"set","rv"),
BUILDIN_DEF(setarray,"rv*"),
BUILDIN_DEF(cleararray,"rvi"),
BUILDIN_DEF(copyarray,"rri"),
@@ -18846,6 +19070,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getequipid,"i"),
BUILDIN_DEF(getequipname,"i"),
BUILDIN_DEF(getbrokenid,"i"), // [Valaris]
+ BUILDIN_DEF(getbrokencount,""),
BUILDIN_DEF(repair,"i"), // [Valaris]
BUILDIN_DEF(repairall,""),
BUILDIN_DEF(getequipisequiped,"i"),
@@ -18882,12 +19107,14 @@ void script_parse_builtin(void) {
BUILDIN_DEF(checkcart,""),
BUILDIN_DEF(setfalcon,"?"),
BUILDIN_DEF(checkfalcon,""),
- BUILDIN_DEF(setriding,"?"),
- BUILDIN_DEF(checkriding,""),
+ BUILDIN_DEF_DEPRECATED(setriding,"?"), // Deprecated 2014-10-30 [Haru]
+ BUILDIN_DEF_DEPRECATED(checkriding,""), // Deprecated 2014-10-30 [Haru]
+ BUILDIN_DEF(setmount,"?"),
+ BUILDIN_DEF(checkmount,""),
BUILDIN_DEF(checkwug,""),
- BUILDIN_DEF(checkmadogear,""),
- BUILDIN_DEF(setmadogear,"?"),
- BUILDIN_DEF2(savepoint,"save","sii"),
+ BUILDIN_DEF_DEPRECATED(checkmadogear,""), // Deprecated 2014-10-30 [Haru]
+ BUILDIN_DEF_DEPRECATED(setmadogear,"?"), // Deprecated 2014-10-30 [Haru]
+ BUILDIN_DEF2_DEPRECATED(savepoint,"save","sii"), // Deprecated 2014-11-02 [Haru]
BUILDIN_DEF(savepoint,"sii"),
BUILDIN_DEF(gettimetick,"i"),
BUILDIN_DEF(gettime,"i"),
@@ -18905,7 +19132,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(clone,"siisi????"),
BUILDIN_DEF(doevent,"s"),
BUILDIN_DEF(donpcevent,"s"),
- BUILDIN_DEF(cmdothernpc,"ss"),
+ BUILDIN_DEF_DEPRECATED(cmdothernpc,"ss"), // Deprecated 2014-11-02 [Haru]
BUILDIN_DEF(addtimer,"is"),
BUILDIN_DEF(deltimer,"s"),
BUILDIN_DEF(addtimercount,"si"),
@@ -18949,8 +19176,8 @@ void script_parse_builtin(void) {
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_DEF2_DEPRECATED(enablewaitingroomevent,"enablearena",""), // Deprecated 2014-11-02 [Haru]
+ BUILDIN_DEF2_DEPRECATED(disablewaitingroomevent,"disablearena",""), // Deprecated 2014-11-02 [Haru]
BUILDIN_DEF(getwaitingroomstate,"i?"),
BUILDIN_DEF(warpwaitingpc,"sii?"),
BUILDIN_DEF(attachrid,"i"),
@@ -19005,7 +19232,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(petskillbonus,"iiii"), // [Valaris]
BUILDIN_DEF(petrecovery,"ii"), // [Valaris]
BUILDIN_DEF(petloot,"i"), // [Valaris]
- BUILDIN_DEF(petheal,"iiii"), // [Valaris]
+ BUILDIN_DEF_DEPRECATED(petheal,"iiii"), // Deprecated 2014-10-27 [Haru]
BUILDIN_DEF(petskillattack,"viii"), // [Skotlex]
BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris]
BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex]
@@ -19055,7 +19282,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(gethominfo,"i"),
BUILDIN_DEF(getmercinfo,"i?"),
BUILDIN_DEF(checkequipedcard,"i"),
- BUILDIN_DEF(jump_zero,"il"), //for future jA script compatibility
+ BUILDIN_DEF2_DEPRECATED(__jump_zero,"jump_zero","il"), // Deprecated 2014-10-27 [Haru]
BUILDIN_DEF(globalmes,"s?"), //end jA addition
BUILDIN_DEF(unequip,"i"), // unequip command [Spectre]
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
@@ -19086,6 +19313,8 @@ void script_parse_builtin(void) {
BUILDIN_DEF(pow,"ii"),
BUILDIN_DEF(distance,"iiii"),
// <--- [zBuffer] List of mathematics commands
+ BUILDIN_DEF(min, "i*"),
+ BUILDIN_DEF(max, "i*"),
BUILDIN_DEF(md5,"s"),
// [zBuffer] List of dynamic var commands --->
BUILDIN_DEF(getd,"s"),
@@ -19207,10 +19436,10 @@ void script_parse_builtin(void) {
* 3rd-related
**/
BUILDIN_DEF(makerune,"i"),
- BUILDIN_DEF(checkdragon,""),//[Ind]
- BUILDIN_DEF(setdragon,"?"),//[Ind]
- BUILDIN_DEF(ismounting,""),//[Ind]
- BUILDIN_DEF(setmounting,""),//[Ind]
+ BUILDIN_DEF_DEPRECATED(checkdragon,""), // Deprecated 2014-10-30 [Haru]
+ BUILDIN_DEF_DEPRECATED(setdragon,"?"), // Deprecated 2014-10-30 [Haru]
+ BUILDIN_DEF(hascashmount,""),//[Ind]
+ BUILDIN_DEF(setcashmount,""),//[Ind]
BUILDIN_DEF(checkre,"i"),
/**
* rAthena and beyond!
@@ -19243,9 +19472,11 @@ void script_parse_builtin(void) {
//Quest Log System [Inkfish]
BUILDIN_DEF(questinfo, "ii??"),
BUILDIN_DEF(setquest, "i"),
- BUILDIN_DEF(erasequest, "i"),
- BUILDIN_DEF(completequest, "i"),
- BUILDIN_DEF(checkquest, "i?"),
+ BUILDIN_DEF(erasequest, "i?"),
+ BUILDIN_DEF(completequest, "i?"),
+ BUILDIN_DEF_DEPRECATED(checkquest, "i?"), // Deprecated 2014-10-28 [Haru]
+ BUILDIN_DEF(questprogress, "i?"),
+ BUILDIN_DEF(questactive, "i"),
BUILDIN_DEF(changequest, "ii"),
BUILDIN_DEF(showevent, "i?"),
@@ -19269,7 +19500,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(stand, "?"),
BUILDIN_DEF(issit, "?"),
- BUILDIN_DEF(montransform, "vii????"), // Monster Transform [malufett/Hercules]
+ BUILDIN_DEF(montransform, "vi?????"), // Monster Transform [malufett/Hercules]
/* New BG Commands [Hercules] */
BUILDIN_DEF(bg_create_team,"sii"),
diff --git a/src/map/script.h b/src/map/script.h
index 48abf1487..1a46ba02b 100644
--- a/src/map/script.h
+++ b/src/map/script.h
@@ -26,9 +26,9 @@ struct eri;
// TODO: Remove temporary code
#define ENABLE_CASE_CHECK
#define get_script_source(source) ((source) ? (source) : "Unknown (Possibly source or variables stored in database")
-#define DeprecationWarning(func, bad, good, file, line) ShowError("%s: use of deprecated keyword '%s' (use '%s' instead) in file '%s', line '%d'.\n", (func), (bad), (good), get_script_source(file), (line));
-#define DeprecationWarning2(func, bad, good, where) ShowError("%s: detected possible use of wrong case in a script. Found '%s', probably meant to be '%s' (in '%s').\n", (func), (bad), (good), get_script_source(where));
-#define disp_deprecation_message(func, good, p) disp_warning_message(func": use of deprecated keyword (use '"good"' instead).", (p));
+#define DeprecationCaseWarning(func, bad, good, where) ShowError("%s: detected possible use of wrong case in a script. Found '%s', probably meant to be '%s' (in '%s').\n", (func), (bad), (good), get_script_source(where))
+
+#define DeprecationWarning(p) disp_warning_message("This command is deprecated and it will be removed in a future update. Please see the script documentation for an alternative.\n", (p))
#define NUM_WHISPER_VAR 10
@@ -433,6 +433,7 @@ struct script_function {
bool (*func)(struct script_state *st);
char *name;
char *arg;
+ bool deprecated;
};
// String buffer structures.
@@ -445,6 +446,7 @@ struct str_data_struct {
bool (*func)(struct script_state *st);
int val;
int next;
+ uint8 deprecated : 1;
};
struct script_label_entry {
diff --git a/src/map/skill.c b/src/map/skill.c
index 4ab0ca1c7..d3c00a75b 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -2123,6 +2123,7 @@ int skill_magic_reflect(struct block_list* src, struct block_list* bl, int type)
* packet shouldn't display a skill animation)
* flag&0x2000 is used to signal that the skill_lv should be passed as -1 to the
* client (causes player characters to not scream skill name)
+ * flag&0x4000 - Return 0 if damage was reflected
*-------------------------------------------------------------------------*/
int skill_attack(int attack_type, struct block_list* src, struct block_list *dsrc, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int64 tick, int flag) {
struct Damage dmg;
@@ -2459,6 +2460,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case EL_HURRICANE_ATK:
case EL_TYPOON_MIS:
case EL_TYPOON_MIS_ATK:
+ case GN_CRAZYWEED_ATK:
case KO_BAKURETSU:
case NC_MAGMA_ERUPTION:
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id,-1,5);
@@ -2469,9 +2471,6 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case SC_FEINTBOMB:
dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,1,skill_id,skill_lv,5);
break;
- case GN_CRAZYWEED_ATK:
- dmg.dmotion = clif->skill_damage(src,bl,tick,dmg.amotion,dmg.dmotion,damage,dmg.div_,skill_id, -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;
@@ -2544,7 +2543,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
break;
case WM_SEVERE_RAINSTORM_MELEE:
copy_skill = WM_SEVERE_RAINSTORM;
- break;
+ break;
case GN_CRAZYWEED_ATK:
copy_skill = GN_CRAZYWEED;
break;
@@ -2796,6 +2795,9 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
map->freeblock_unlock();
+ if ((flag&0x4000) && rmdamage == 1)
+ return 0; //Should return 0 when damage was reflected
+
return (int)cap_value(damage,INT_MIN,INT_MAX);
}
@@ -3301,6 +3303,11 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
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);
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);
+ }
// fall through ...
case WL_EARTHSTRAIN:
skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,(skl->type<<16)|skl->flag);
@@ -3310,14 +3317,6 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
map->foreachinpath(skill->attack_area,src->m,src->x,src->y,skl->x,skl->y,4,2,BL_CHAR,
skill->get_type(skl->skill_id),src,src,skl->skill_id,skl->skill_lv,tick,skl->flag,BCT_ENEMY);
break;
- case GN_CRAZYWEED:
- if( skl->type >= 0 ) {
- int x = skl->type>>16, y = skl->type&0xFFFF;
- if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
- skill->castend_pos2(src, x, y, GN_CRAZYWEED_ATK, skl->skill_lv, tick, skl->flag);
- } else if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
- skill->castend_pos2(src, skl->x, skl->y, GN_CRAZYWEED_ATK, skl->skill_lv, tick, skl->flag);
- break;
}
}
} while (0);
@@ -3564,7 +3563,6 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case SR_GENTLETOUCH_QUIET:
case WM_SEVERE_RAINSTORM_MELEE:
case WM_GREAT_ECHO:
- case GN_CRAZYWEED_ATK:
case GN_SLINGITEM_RANGEMELEEATK:
case KO_JYUMONJIKIRI:
case KO_SETSUDAN:
@@ -3808,11 +3806,15 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
// 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;
+ struct status_change *tsc = status->get_sc(bl);
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)) || flag&SD_ANIMATION )
sflag |= SD_ANIMATION; // original target gets no animation (as well as all NPC skills)
+ if ( tsc && tsc->data[SC_HOVERING] && ( skill_id == SR_WINDMILL || skill_id == LG_MOONSLASHER ) )
+ break;
+
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);
@@ -6626,9 +6628,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
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);
+ d += 1000 * ( skill_lv * 15 + ( sstatus->dex - tstatus->dex ) );
else
- d += skill_lv * 30 + (sstatus->dex - tstatus->dex) / 2;
+ d += 1000 * ( skill_lv * 30 + ( sstatus->dex - tstatus->dex ) / 2 );
}else
d = skill->get_time(skill_id,skill_lv) + (sstatus->dex - tstatus->dex)*500;
@@ -6949,7 +6951,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
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)) {
+ if(!map->count_oncell(src->m,x,y,BL_PC|BL_NPC|BL_MOB,0) && map->getcell(src->m,x,y,CELL_CHKREACH)) {
clif->slide(src,x,y);
unit->movepos(src, x, y, 1, 0);
}
@@ -8326,7 +8328,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( flag&1 || (splash = skill->get_splash(skill_id, skill_lv)) < 1 ) {
int i;
//As of the behavior in official server Clearance is just a super version of Dispell skill. [Jobbie]
- if( bl->type != BL_MOB && battle->check_target(src,bl,BCT_PARTY) <= 0 ) // Only affect mob or party.
+ if( bl->type != BL_MOB && battle->check_target(src,bl,BCT_PARTY) <= 0 && sd ) // Only affect mob, party or self.
break;
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -8538,9 +8540,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case NC_SELFDESTRUCTION:
- if( sd ) {
- if( pc_ismadogear(sd) )
- pc->setmadogear(sd, 0);
+ if (sd) {
+ if (pc_ismadogear(sd))
+ pc->setmadogear(sd, false);
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);
@@ -8932,10 +8934,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
break;
case SR_GENTLETOUCH_CHANGE:
- case SR_GENTLETOUCH_REVITALIZE:
clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start2(src,bl,type,100,skill_lv,bl->id,skill->get_time(skill_id,skill_lv)));
break;
+ case SR_GENTLETOUCH_REVITALIZE:
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,
+ sc_start2(src,bl,type,100,skill_lv,status_get_vit(src),skill->get_time(skill_id,skill_lv)));
+ break;
case SR_FLASHCOMBO:
{
const int combo[] = {
@@ -9446,17 +9451,16 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case KO_KYOUGAKU:
- {
- int rate = max(5, (45 + 5 * skill_lv - status_get_int(bl) / 10));
- if( sd && !map_flag_gvg2(src->m) ){
- clif->skill_fail(sd, skill_id, USESKILL_FAIL_SIZE, 0);
- break;
- }
- if( dstsd && tsc && !tsc->data[type] && rand()%100 < rate ){
- clif->skill_nodamage(src, bl, skill_id, skill_lv,
- sc_start(src, 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);
+ if (!map_flag_vs(src->m) || !dstsd) {
+ if (sd) clif->skill_fail(sd, skill_id, USESKILL_FAIL_SIZE, 0);
+ break;
+ } else {
+ int time;
+ int rate = 45+ 5*skill_lv - status_get_int(bl)/10;
+ if (rate < 5) rate = 5;
+
+ time = skill->get_time(skill_id, skill_lv) - 1000*status_get_int(bl)/20;
+ sc_start(src,bl, type, rate, skill_lv, time);
}
break;
@@ -10077,7 +10081,6 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case MG_THUNDERSTORM:
case AL_PNEUMA:
- case WZ_ICEWALL:
case WZ_FIREPILLAR:
case WZ_QUAGMIRE:
case WZ_VERMILION:
@@ -10186,6 +10189,11 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
sc_start(src,src,SC_NO_SWITCH_EQUIP,100,0,skill->get_time(skill_id,skill_lv));
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
break;
+ case WZ_ICEWALL:
+ flag |= 1;
+ if( skill->unitsetting(src,skill_id,skill_lv,x,y,0) )
+ map->list[src->m].setcell(src->m, x, y, CELL_NOICEWALL, true);
+ break;
case RG_GRAFFITI: /* Graffiti [Valaris] */
skill->clear_unitgroup(src);
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
@@ -10380,7 +10388,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
// Plant Cultivation [Celest]
case CR_CULTIVATION:
if (sd) {
- if( map->count_oncell(src->m,x,y,BL_CHAR) > 0 ) {
+ if( map->count_oncell(src->m,x,y,BL_CHAR,0) > 0 ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 1;
}
@@ -10599,33 +10607,17 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case GN_CRAZYWEED:
{
int area = skill->get_splash(skill_id, skill_lv);
- short tmpx = 0, tmpy = 0, x1 = 0, y1 = 0;
for( r = 0; r < 3 + (skill_lv>>1); r++ ) {
// Creates a random Cell in the Splash Area
- tmpx = x - area + rnd()%(area * 2 + 1);
- tmpy = y - area + rnd()%(area * 2 + 1);
-
- if( r > 0 )
- skill->addtimerskill(src,tick+r*250,0,tmpx,tmpy,GN_CRAZYWEED,skill_lv,(x1<<16)|y1,flag);
+ int tmpx = x - area + rnd()%(area * 2 + 1);
+ int tmpy = y - area + rnd()%(area * 2 + 1);
- x1 = tmpx;
- y1 = tmpy;
+ skill_addtimerskill(src,tick+r*250,0,tmpx,tmpy,GN_CRAZYWEED_ATK,skill_lv,-1,0);
}
-
- skill->addtimerskill(src,tick+r*250,0,tmpx,tmpy,GN_CRAZYWEED,skill_lv,-1,flag);
}
break;
- case GN_CRAZYWEED_ATK: {
- int dummy = 1;
- //Enable if any unique animation gets added to this skill ID in the future. [Rytech]
- //clif_skill_poseffect(src,skillid,skilllv,x,y,tick);
- r = skill->get_splash(skill_id, skill_lv);
- map->foreachinarea(skill->cell_overlap, src->m, x-r, y-r, x+r, y+r, BL_SKILL, skill_id, &dummy, src);
- map->foreachinarea(skill->area_sub, src->m, x-r, y-r, x+r, y+r, BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id);
- }
- break;
case GN_FIRE_EXPANSION: {
int i;
struct unit_data *ud = unit->bl2ud(src);
@@ -10801,28 +10793,6 @@ bool skill_dance_switch(struct skill_unit* su, int flag) {
return true;
}
-/**
- * Upon Ice Wall cast it checks all nearby mobs to find any who may be blocked by the IW
- **/
-int skill_icewall_block(struct block_list *bl,va_list ap) {
- struct block_list *target = NULL;
- struct mob_data *md = ((TBL_MOB*)bl);
-
- nullpo_ret(bl);
- nullpo_ret(md);
- if( !md->target_id || ( target = map->id2bl(md->target_id) ) == NULL )
- return 0;
-
- if( path->search_long(NULL,bl->m,bl->x,bl->y,target->x,target->y,CELL_CHKICEWALL) )
- return 0;
-
- if( !check_distance_bl(bl, target, status_get_range(bl) ) ) {
- mob->unlocktarget(md,timer->gettick());
- mob_stop_walking(md,1);
- }
-
- return 0;
-}
/*==========================================
* Initializes and sets a ground skill.
* flag&1 is used to determine when the skill 'morphs' (Warp portal becomes active, or Fire Pillar becomes active)
@@ -11032,11 +11002,11 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
val1 += pc->checkskill(sd,BA_MUSICALLESSON);
break;
case DC_SERVICEFORYOU:
- val1 = 15+skill_lv+(st->int_/10); // MaxSP percent increase TO-DO: this INT bonus value is guessed
+ val1 = 15+skill_lv+(st->int_/10); // MaxSP percent increase
val2 = 20+3*skill_lv+(st->int_/10); // SP cost reduction
if(sd){
- val1 += (pc->checkskill(sd,DC_DANCINGLESSON) + 1) / 2;
- val2 += (pc->checkskill(sd,DC_DANCINGLESSON) + 1) / 2;
+ val1 += pc->checkskill(sd,DC_DANCINGLESSON) / 2;
+ val2 += pc->checkskill(sd,DC_DANCINGLESSON) / 2;
}
break;
case BA_ASSASSINCROSS:
@@ -11322,9 +11292,6 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
//success, unit created.
switch( skill_id ) {
- case WZ_ICEWALL:
- map->foreachinrange(skill->icewall_block, src, AREA_SIZE, BL_MOB);
- break;
case NJ_TATAMIGAESHI: //Store number of tiles.
group->val1 = group->alive_count;
break;
@@ -11363,6 +11330,9 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (sc && sc->data[SC_VACUUM_EXTREME] && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR))
status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER);
+ if ( sc && sc->data[SC_HOVERING] && ( sg->skill_id == SO_VACUUM_EXTREME || sg->skill_id == SO_ELECTRICWALK || sg->skill_id == SO_FIREWALK || sg->skill_id == WZ_QUAGMIRE ) )
+ return 0;
+
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.
@@ -11583,9 +11553,6 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
tsc = status->get_sc(bl);
ssc = status->get_sc(ss); // Status Effects for Unit caster.
- if ( tsc && tsc->data[SC_HOVERING] )
- return 0; //Under hovering characters are immune to trap and ground target skills.
-
// Maestro or Wanderer is unaffected by traps of trappers he or she charmed [SuperHulk]
if ( ssc && ssc->data[SC_SIREN] && ssc->data[SC_SIREN]->val2 == bl->id && (skill->get_inf2(sg->skill_id)&INF2_TRAP) )
return 0;
@@ -11594,6 +11561,15 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
type = status->skill2sc(sg->skill_id);
skill_id = sg->skill_id;
+ if ( tsc && tsc->data[SC_HOVERING] ) {
+ switch ( skill_id ) {
+ case HT_SKIDTRAP: case HT_LANDMINE: case HT_ANKLESNARE: case HT_FLASHER: case HT_SHOCKWAVE:
+ case HT_SANDMAN: case HT_FREEZINGTRAP: case HT_BLASTMINE: case HT_CLAYMORETRAP: case HW_GRAVITATION:
+ case SA_DELUGE: case SA_VOLCANO: case SA_VIOLENTGALE: case NJ_SUITON:
+ return 0;
+ }
+ }
+
if (sg->interval == -1) {
switch (sg->unit_id) {
case UNT_ANKLESNARE: //These happen when a trap is splash-triggered by multiple targets on the same cell.
@@ -11615,7 +11591,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
ts->tick = tick+sg->interval;
if ((skill_id==CR_GRANDCROSS || skill_id==NPC_GRANDDARKNESS) && !battle_config.gx_allhit)
- ts->tick += sg->interval*(map->count_oncell(bl->m,bl->x,bl->y,BL_CHAR)-1);
+ ts->tick += sg->interval*(map->count_oncell(bl->m,bl->x,bl->y,BL_CHAR,0)-1);
}
switch (sg->unit_id) {
@@ -12197,9 +12173,11 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
sg->limit -= 100 * tstatus->str/20;
sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit);
- if (unit->movepos(bl, sg->val1, sg->val2, 0, 0)) {
- clif->slide(bl, sg->val1, sg->val2);
- clif->fixpos(bl);
+ if ( !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !is_boss(bl) ) {
+ if (unit->movepos(bl, sg->val1, sg->val2, 0, 0)) {
+ clif->slide(bl, sg->val1, sg->val2);
+ clif->fixpos(bl);
+ }
}
}
break;
@@ -13199,17 +13177,6 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
}
break;
- /**
- * Keeping as a note:
- * Bug Report #17 provides a link to a sep-2011 changelog that shows this requirement was removed
- **/
- //case AB_LAUDAAGNUS:
- //case AB_LAUDARAMUS:
- // if( !sd->status.party_id ) {
- // clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- // return 0;
- // }
- // break;
case AB_ADORAMUS:
/**
@@ -13326,20 +13293,17 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
break;
case LG_RAYOFGENESIS:
+ case LG_HESPERUSLIT:
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);
return 0;
- } else if( skill->check_pc_partner(sd,skill_id,&skill_lv,skill->get_range(skill_id,skill_lv),0) < 1 )
+ }
+ if( sc->data[SC_BANDING] &&
+ sc->data[SC_BANDING]->val2 < (skill_id == LG_RAYOFGENESIS ? 2 : 3) )
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);
- return 0;
- }
- break;
case SR_FALLENEMPIRE:
if( sc && sc->data[SC_COMBOATTACK] ) {
if( sc->data[SC_COMBOATTACK]->val1 == SR_DRAGONCOMBO )
@@ -13397,6 +13361,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
break;
+ case NC_HOVERING:
+ if (( sd->equip_index[EQI_ACC_L] >= 0 && sd->status.inventory[sd->equip_index[EQI_ACC_L]].nameid == ITEMID_HOVERING_BOOSTER ) ||
+ ( sd->equip_index[EQI_ACC_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_ACC_R]].nameid == ITEMID_HOVERING_BOOSTER ));
+ else {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ return 0;
+ }
+ break;
case SO_FIREWALK:
case SO_ELECTRICWALK: // Can't be casted until you've walked all cells.
if( sc && sc->data[SC_PROPERTYWALK] &&
@@ -13468,7 +13440,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
break;
case ST_RIDING:
- if(!pc_isriding(sd) && !pc_isridingdragon(sd)) {
+ if (!pc_isridingpeco(sd) && !pc_isridingdragon(sd)) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -13583,7 +13555,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
case ST_PECO:
- if(!pc_isriding(sd)) {
+ if (!pc_isridingpeco(sd)) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -14336,9 +14308,8 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
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
+ fixcast_r = sd->skillfixcastrate[i].val;
break;
}
}
@@ -15000,7 +14971,7 @@ int skill_frostjoke_scream(struct block_list *bl, va_list ap) {
return 0;
if (bl->type == BL_PC) {
struct map_session_data *sd = (struct map_session_data *)bl;
- if ( sd && sd->sc.option&(OPTION_INVISIBLE|OPTION_MADOGEAR) )
+ if (sd && (pc_isinvisible(sd) || pc_ismadogear(sd)))
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]
@@ -15282,9 +15253,10 @@ int skill_cell_overlap(struct block_list *bl, va_list ap) {
break;
}
break;
+ case WZ_ICEWALL:
case HP_BASILICA:
- if (su->group->skill_id == HP_BASILICA) {
- //Basilica can't be placed on top of itself to avoid map-cell stacking problems. [Skotlex]
+ if (su->group->skill_id == skill_id) {
+ //These can't be placed on top of themselves (duration can't be refreshed)
(*alive) = 0;
return 1;
}
@@ -15602,7 +15574,6 @@ struct skill_unit *skill_initunit (struct skill_unit_group *group, int idx, int
map->setgatcell(su->bl.m,su->bl.x,su->bl.y,5);
clif->changemapcell(0,su->bl.m,su->bl.x,su->bl.y,5,AREA);
skill->unitsetmapcell(su,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,true);
- map->list[su->bl.m].icewall_num++;
break;
case SA_LANDPROTECTOR:
skill->unitsetmapcell(su,SA_LANDPROTECTOR,group->skill_lv,CELL_LANDPROTECTOR,true);
@@ -15651,10 +15622,10 @@ int skill_delunit (struct skill_unit* su) {
}
break;
case WZ_ICEWALL:
+ map->list[su->bl.m].setcell(su->bl.m, su->bl.x, su->bl.y, CELL_NOICEWALL, false);
map->setgatcell(su->bl.m,su->bl.x,su->bl.y,su->val2);
clif->changemapcell(0,su->bl.m,su->bl.x,su->bl.y,su->val2,ALL_SAMEMAP); // hack to avoid clientside cell bug
skill->unitsetmapcell(su,WZ_ICEWALL,group->skill_lv,CELL_ICEWALL,false);
- map->list[su->bl.m].icewall_num--;
// AS_CLOAKING in low levels requires a wall to be cast, thus it needs to be
// checked again when a wall disapears! issue:8182 [Panikon]
map->foreachinarea(skill->check_cloaking_end, su->bl.m,
@@ -15802,7 +15773,7 @@ int skill_delunitgroup(struct skill_unit_group *group, const char* file, int lin
return 0;
}
- if( !status->isdead(src) && ((TBL_PC*)src)->state.warping && !((TBL_PC*)src)->state.changemap ) {
+ if( src->type == BL_PC && !status->isdead(src) && ((TBL_PC*)src)->state.warping && !((TBL_PC*)src)->state.changemap ) {
switch( group->skill_id ) {
case BA_DISSONANCE:
case BA_POEMBRAGI:
@@ -17525,12 +17496,12 @@ int skill_blockpc_start_(struct map_session_data *sd, uint16 skill_id, int tick)
} else {
int i;
- for(i = 0; i < MAX_SKILL_TREE; i++) {
+ for(i = 0; i < cd->cursor; i++) {
if( cd->entry[i] && cd->entry[i]->skidx == idx )
break;
}
- if( i != MAX_SKILL_TREE ) {/* duplicate, update necessary */
+ if( i != cd->cursor ) {/* duplicate, update necessary */
cd->entry[i]->duration = tick;
#if PACKETVER >= 20120604
cd->entry[i]->total = tick;
@@ -18600,7 +18571,7 @@ int do_init_skill(bool minimal) {
skill->unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
skill->timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE|ERS_OPT_FLEX_CHUNK);
skill->cd_ers = ers_new(sizeof(struct skill_cd),"skill.c::skill_cd_ers",ERS_OPT_CLEAR|ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
- skill->cd_entry_ers = ers_new(sizeof(struct skill_cd_entry),"skill.c::skill_cd_entry_ers",ERS_OPT_CLEAR|ERS_OPT_FLEX_CHUNK);
+ skill->cd_entry_ers = ers_new(sizeof(struct skill_cd_entry),"skill.c::skill_cd_entry_ers",ERS_OPT_CLEAR|ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK);
ers_chunk_size(skill->cd_ers, 25);
ers_chunk_size(skill->cd_entry_ers, 100);
@@ -18806,7 +18777,6 @@ void skill_defaults(void) {
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;
diff --git a/src/map/skill.h b/src/map/skill.h
index 6373d9275..4ec742bd0 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -1984,7 +1984,6 @@ struct skill_interface {
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, int64 tick);
bool (*dance_switch) (struct skill_unit* su, int flag);
int (*check_condition_char_sub) (struct block_list *bl, va_list ap);
diff --git a/src/map/status.c b/src/map/status.c
index a8a0f066d..66f7db3fa 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -643,7 +643,7 @@ void initChangeTables(void) {
set_sc( SR_RAISINGDRAGON , SC_RAISINGDRAGON , SI_RAISINGDRAGON , SCB_REGEN|SCB_MAXHP|SCB_MAXSP );
set_sc( SR_GENTLETOUCH_ENERGYGAIN, SC_GENTLETOUCH_ENERGYGAIN , SI_GENTLETOUCH_ENERGYGAIN, SCB_NONE );
set_sc( SR_GENTLETOUCH_CHANGE , SC_GENTLETOUCH_CHANGE , SI_GENTLETOUCH_CHANGE , SCB_ASPD|SCB_MDEF|SCB_MAXHP );
- set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_REGEN );
+ set_sc( SR_GENTLETOUCH_REVITALIZE, SC_GENTLETOUCH_REVITALIZE , SI_GENTLETOUCH_REVITALIZE, SCB_MAXHP|SCB_DEF2|SCB_REGEN );
set_sc( SR_FLASHCOMBO , SC_FLASHCOMBO , SI_FLASHCOMBO , SCB_WATK );
/**
* Wanderer / Minstrel
@@ -935,13 +935,16 @@ void initChangeTables(void) {
status->ChangeFlagTable[SC_INCHITRATE] |= SCB_HIT;
status->ChangeFlagTable[SC_INCFLEE] |= SCB_FLEE;
status->ChangeFlagTable[SC_INCFLEERATE] |= SCB_FLEE;
+ status->ChangeFlagTable[SC_MTF_HITFLEE] |= SCB_HIT|SCB_FLEE;
status->ChangeFlagTable[SC_CRITICALPERCENT] |= SCB_CRI;
status->ChangeFlagTable[SC_INCASPDRATE] |= SCB_ASPD;
status->ChangeFlagTable[SC_PLUSAVOIDVALUE] |= SCB_FLEE2;
status->ChangeFlagTable[SC_INCMHPRATE] |= SCB_MAXHP;
status->ChangeFlagTable[SC_INCMSPRATE] |= SCB_MAXSP;
status->ChangeFlagTable[SC_INCMHP] |= SCB_MAXHP;
+ status->ChangeFlagTable[SC_MTF_MHP] |= SCB_MAXHP;
status->ChangeFlagTable[SC_INCMSP] |= SCB_MAXSP;
+ status->ChangeFlagTable[SC_MTF_MSP] |= SCB_MAXSP;
status->ChangeFlagTable[SC_INCATKRATE] |= SCB_BATK|SCB_WATK;
status->ChangeFlagTable[SC_INCMATKRATE] |= SCB_MATK;
status->ChangeFlagTable[SC_INCDEFRATE] |= SCB_DEF;
@@ -1795,9 +1798,9 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
//If targeting, cloak+hide protect you, otherwise only hiding does.
hide_flag = flag?OPTION_HIDE:(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK);
- // There is no NF for ground skills, but every earth type skill out there
- // affects hidding except Stone Curse
- if( skill->get_ele(skill_id,1) == ELE_EARTH && skill_id != MG_STONECURSE)
+ // Applies even if the target hides
+ if ((skill->get_ele(skill_id,1) == ELE_EARTH && skill_id != MG_STONECURSE) // Ground type
+ || (flag&1 && skill->get_nk(skill_id)&NK_NO_DAMAGE && skill_id != ALL_RESURRECTION)) // Buff/debuff skills started before hiding
hide_flag &= ~OPTION_HIDE;
switch( target->type ) {
@@ -1809,7 +1812,6 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 0;
if( tsc ) {
if (tsc->option&hide_flag && !is_boss &&
- !(flag&1 && skill->get_nk(skill_id)&NK_NO_DAMAGE) && // Buff/debuff skills that started casting before hiding still applies
((sd->special_state.perfect_hiding || !is_detect) ||
(tsc->data[SC_CLOAKINGEXCEED] && is_detect)))
return 0;
@@ -2485,13 +2487,14 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
bstatus->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM;
- if (battle_config.character_size && (pc_isriding(sd) || pc_isridingdragon(sd)) ) { //[Lupus]
+ if (battle_config.character_size && (pc_isridingpeco(sd) || pc_isridingdragon(sd))) { //[Lupus]
if (sd->class_&JOBL_BABY) {
if (battle_config.character_size&SZ_BIG)
bstatus->size++;
- } else
+ } else {
if(battle_config.character_size&SZ_MEDIUM)
bstatus->size++;
+ }
}
bstatus->aspd_rate = 1000;
bstatus->ele_lv = 1;
@@ -2780,9 +2783,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->left_weapon.atkmods[1] = status->atkmods[1][sd->weapontype2];
sd->left_weapon.atkmods[2] = status->atkmods[2][sd->weapontype2];
- if( (pc_isriding(sd) || pc_isridingdragon(sd)) &&
- (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR))
- { //When Riding with spear, damage modifier to mid-class becomes
+ if ((pc_isridingpeco(sd) || pc_isridingdragon(sd))
+ && (sd->status.weapon==W_1HSPEAR || sd->status.weapon==W_2HSPEAR)
+ ) {
+ //When Riding with spear, damage modifier to mid-class becomes
//same as versus large size.
sd->right_weapon.atkmods[1] = sd->right_weapon.atkmods[2];
sd->left_weapon.atkmods[1] = sd->left_weapon.atkmods[2];
@@ -3062,9 +3066,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
bstatus->aspd_rate -= ((skill_lv+1)/2) * 10;
- if(pc_isriding(sd))
+ if (pc_isridingpeco(sd))
bstatus->aspd_rate += 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
- else if(pc_isridingdragon(sd))
+ else if (pc_isridingdragon(sd))
bstatus->aspd_rate += 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
#else // needs more info
if((skill_lv=pc->checkskill(sd,SA_ADVANCEDBOOK))>0 && sd->status.weapon == W_BOOK)
@@ -3074,9 +3078,9 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
if((skill_lv=pc->checkskill(sd,GS_SINGLEACTION))>0 &&
(sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE))
bstatus->aspd_rate += ((skill_lv+1)/2) * 10;
- if(pc_isriding(sd))
+ if (pc_isridingpeco(sd))
bstatus->aspd_rate -= 500-100*pc->checkskill(sd,KN_CAVALIERMASTERY);
- else if(pc_isridingdragon(sd))
+ else if (pc_isridingdragon(sd))
bstatus->aspd_rate -= 250-50*pc->checkskill(sd,RK_DRAGONTRAINING);
#endif
bstatus->adelay = 2*bstatus->amotion;
@@ -3094,7 +3098,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
// Weight
if((skill_lv=pc->checkskill(sd,MC_INCCARRY))>0)
sd->max_weight += 2000*skill_lv;
- if(pc_isriding(sd) && pc->checkskill(sd,KN_RIDING)>0)
+ if (pc_isridingpeco(sd) && pc->checkskill(sd,KN_RIDING) > 0)
sd->max_weight += 10000;
else if(pc_isridingdragon(sd))
sd->max_weight += 5000+2000*pc->checkskill(sd,RK_DRAGONTRAINING);
@@ -3603,8 +3607,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
regen->flag&=~sce->val4; //Remove regen as specified by val4
}
if(sc->data[SC_GENTLETOUCH_REVITALIZE]) {
- regen->hp = cap_value(regen->hp*sc->data[SC_GENTLETOUCH_REVITALIZE]->val3/100, 1, SHRT_MAX);
- regen->state.walk= 1;
+ regen->hp += regen->hp * ( 30 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val1 + 50 ) / 100;
}
if ((sc->data[SC_FIRE_INSIGNIA] && sc->data[SC_FIRE_INSIGNIA]->val1 == 1) //if insignia lvl 1
|| (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 1)
@@ -4232,7 +4235,7 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_STOMACHACHE])
str -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_KYOUGAKU])
- str -= sc->data[SC_KYOUGAKU]->val2;
+ str -= sc->data[SC_KYOUGAKU]->val3;
if(sc->data[SC_FULL_THROTTLE])
str += str * 20 / 100;
@@ -4287,7 +4290,7 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_STOMACHACHE])
agi -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_KYOUGAKU])
- agi -= sc->data[SC_KYOUGAKU]->val2;
+ agi -= sc->data[SC_KYOUGAKU]->val3;
if(sc->data[SC_MARSHOFABYSS])
agi -= agi * sc->data[SC_MARSHOFABYSS]->val2 / 100;
@@ -4335,7 +4338,7 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_STOMACHACHE])
vit -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_KYOUGAKU])
- vit -= sc->data[SC_KYOUGAKU]->val2;
+ vit -= sc->data[SC_KYOUGAKU]->val3;
if(sc->data[SC_NOEQUIPARMOR])
vit -= vit * sc->data[SC_NOEQUIPARMOR]->val2/100;
@@ -4393,7 +4396,7 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_STOMACHACHE])
int_ -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_KYOUGAKU])
- int_ -= sc->data[SC_KYOUGAKU]->val2;
+ int_ -= sc->data[SC_KYOUGAKU]->val3;
if(bl->type != BL_PC){
if(sc->data[SC_NOEQUIPHELM])
@@ -4455,7 +4458,7 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_STOMACHACHE])
dex -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_KYOUGAKU])
- dex -= sc->data[SC_KYOUGAKU]->val2;
+ dex -= sc->data[SC_KYOUGAKU]->val3;
if(sc->data[SC_MARSHOFABYSS])
dex -= dex * sc->data[SC_MARSHOFABYSS]->val2 / 100;
@@ -4503,7 +4506,7 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_STOMACHACHE])
luk -= sc->data[SC_STOMACHACHE]->val1;
if(sc->data[SC_KYOUGAKU])
- luk -= sc->data[SC_KYOUGAKU]->val2;
+ luk -= sc->data[SC_KYOUGAKU]->val3;
if(sc->data[SC_LAUDARAMUS])
luk += 4 + sc->data[SC_LAUDARAMUS]->val1;
@@ -4712,6 +4715,8 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc,
if( !viewable ){
/* some statuses that are hidden in the status window */
+ if (sc->data[SC_MINDBREAKER])
+ matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
return (unsigned short)cap_value(matk,0,USHRT_MAX);
}
@@ -4736,8 +4741,6 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc,
if (sc->data[SC_IZAYOI])
matk += 25 * sc->data[SC_IZAYOI]->val1;
#endif
- if (sc->data[SC_MINDBREAKER])
- matk += matk * sc->data[SC_MINDBREAKER]->val2/100;
if( sc->data[SC_ZANGETSU] )
matk += sc->data[SC_ZANGETSU]->val3;
if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4)
@@ -4804,6 +4807,8 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in
if(sc->data[SC_INCHIT])
hit += sc->data[SC_INCHIT]->val1;
+ if(sc->data[SC_MTF_HITFLEE])
+ hit += sc->data[SC_MTF_HITFLEE]->val1;
if(sc->data[SC_FOOD_BASICHIT])
hit += sc->data[SC_FOOD_BASICHIT]->val1;
if(sc->data[SC_TRUESIGHT])
@@ -4855,6 +4860,8 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
if(sc->data[SC_INCFLEE])
flee += sc->data[SC_INCFLEE]->val1;
+ if(sc->data[SC_MTF_HITFLEE])
+ flee += sc->data[SC_MTF_HITFLEE]->val2;
if(sc->data[SC_FOOD_BASICAVOIDANCE])
flee += sc->data[SC_FOOD_BASICAVOIDANCE]->val1;
if(sc->data[SC_WHISTLE])
@@ -4955,8 +4962,6 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
def -= def * 50 / 100;
if( sc->data[SC_NEUTRALBARRIER] )
def += def * (10 + 5*sc->data[SC_NEUTRALBARRIER]->val1) / 100;
- if( sc && sc->data[SC_GENTLETOUCH_REVITALIZE] && sc->data[SC_GENTLETOUCH_REVITALIZE]->val4 )
- def += 2 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val4;
if( sc->data[SC_FORCEOFVANGUARD] )
def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100;
if(sc->data[SC_DEFSET])
@@ -5060,6 +5065,8 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
#endif
if( sc && sc->data[SC_CAMOUFLAGE] )
def2 -= def2 * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100;
+ if(sc->data[SC_GENTLETOUCH_REVITALIZE])
+ def2 += sc->data[SC_GENTLETOUCH_REVITALIZE]->val2;
if(sc->data[SC_DEFSET])
return sc->data[SC_DEFSET]->val1;
#ifdef RENEWAL
@@ -5232,16 +5239,16 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
{
int val = 0;
- if( sc->data[SC_FUSION] )
+ if(sc->data[SC_FUSION]) {
val = 25;
- else if( sd ) {
- if( pc_isriding(sd) || sd->sc.option&(OPTION_DRAGON) || sd->sc.data[SC_ALL_RIDING] )
+ } else if (sd) {
+ if (pc_isridingpeco(sd) || pc_isridingdragon(sd) || sd->sc.data[SC_ALL_RIDING])
val = 25;//Same bonus
- else if( pc_isridingwug(sd) )
+ else if (pc_isridingwug(sd))
val = 15 + 5 * pc->checkskill(sd, RA_WUGRIDER);
- else if( pc_ismadogear(sd) ) {
+ else if (pc_ismadogear(sd)) {
val = (- 10 * (5 - pc->checkskill(sd,NC_MADOLICENCE)));
- if( sc->data[SC_ACCELERATION] )
+ if (sc->data[SC_ACCELERATION])
val += 25;
}
}
@@ -5699,6 +5706,8 @@ unsigned int status_calc_maxhp(struct block_list *bl, struct status_change *sc,
maxhp += maxhp * sc->data[SC_INCMHPRATE]->val1/100;
if(sc->data[SC_INCMHP])
maxhp += (sc->data[SC_INCMHP]->val1);
+ if(sc->data[SC_MTF_MHP])
+ maxhp += (sc->data[SC_MTF_MHP]->val1);
if(sc->data[SC_APPLEIDUN])
maxhp += maxhp * sc->data[SC_APPLEIDUN]->val2/100;
if(sc->data[SC_DELUGE])
@@ -5766,6 +5775,8 @@ unsigned int status_calc_maxsp(struct block_list *bl, struct status_change *sc,
maxsp += maxsp * sc->data[SC_INCMSPRATE]->val1/100;
if(sc->data[SC_INCMSP])
maxsp += (sc->data[SC_INCMSP]->val1);
+ if(sc->data[SC_MTF_MSP])
+ maxsp += (sc->data[SC_MTF_MSP]->val1);
if(sc->data[SC_SERVICEFORYOU])
maxsp += maxsp * sc->data[SC_SERVICEFORYOU]->val2/100;
if(sc->data[SC_MER_SP])
@@ -6014,7 +6025,9 @@ int status_get_party_id(struct block_list *bl) {
return ((TBL_MER*)bl)->master->status.party_id;
break;
case BL_SKILL:
- return ((TBL_SKILL*)bl)->group->party_id;
+ if (((TBL_SKILL*)bl)->group)
+ return ((TBL_SKILL*)bl)->group->party_id;
+ break;
case BL_ELEM:
if (((TBL_ELEM*)bl)->master)
return ((TBL_ELEM*)bl)->master->status.party_id;
@@ -6057,7 +6070,9 @@ int status_get_guild_id(struct block_list *bl) {
return ((TBL_NPC*)bl)->u.scr.guild_id;
break;
case BL_SKILL:
- return ((TBL_SKILL*)bl)->group->guild_id;
+ if (((TBL_SKILL*)bl)->group)
+ return ((TBL_SKILL*)bl)->group->guild_id;
+ break;
case BL_ELEM:
if (((TBL_ELEM*)bl)->master)
return ((TBL_ELEM*)bl)->master->status.guild_id;
@@ -6179,7 +6194,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
{
TBL_PC* sd = (TBL_PC*)bl;
if (pcdb_checkid(class_)) {
- if (sd->sc.option&OPTION_RIDING) {
+ if (pc_isridingpeco(sd)) {
switch (class_) { //Adapt class to a Mounted one.
case JOB_KNIGHT:
class_ = JOB_KNIGHT2;
@@ -6559,9 +6574,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_SIREN:
tick_def2 = (status->get_lv(bl) * 100) + ((bl->type == BL_PC)?((TBL_PC*)bl)->status.job_level : 0);
break;
- case SC_KYOUGAKU:
- tick_def2 = st->int_ * 50;
- break;
case SC_NEEDLE_OF_PARALYZE:
tick_def2 = (st->vit + st->luk) * 50;
break;
@@ -6876,7 +6888,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
)
return 0;
case SC_VACUUM_EXTREME:
- if(sc->data[SC_HALLUCINATIONWALK] || sc->data[SC_HOVERING])
+ if(sc->data[SC_HALLUCINATIONWALK])
return 0;
break;
case SC_STONE:
@@ -7885,8 +7897,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_RUWACH:
case SC_WZ_SIGHTBLASTER:
val3 = skill->get_splash(val2, val1); //Val2 should bring the skill-id.
- val2 = tick/250;
- tick_time = 10; // [GodLesZ] tick time
+ val2 = tick/20;
+ tick_time = 20; // [GodLesZ] tick time
break;
//Permanent effects.
@@ -8585,14 +8597,22 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val2 = 20 + 10 * val1; //ASPD. Need to confirm if Movement Speed reduction is the same. [Jobbie]
val3 = 20 * val1; //HIT
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,HOM_ST_REST);
- if( sd->md ) mercenary->delete(sd->md,3);
+ if (pc_isridingpeco(sd))
+ pc->setridingpeco(sd, false);
+ if (pc_isridingdragon(sd))
+ pc->setridingdragon(sd, 0);
+ if (pc_iswug(sd))
+ pc->setoption(sd, sd->sc.option&~OPTION_WUG);
+ if (pc_isridingwug(sd))
+ pc->setridingwug(sd, false);
+ if (pc_isfalcon(sd))
+ pc->setfalcon(sd, false);
+ if (sd->status.pet_id > 0)
+ pet->menu(sd, 3);
+ if (homun_alive(sd->hd))
+ homun->vaporize(sd,HOM_ST_REST);
+ if (sd->md)
+ mercenary->delete(sd->md,3);
}
break;
case SC__LAZINESS:
@@ -8689,8 +8709,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if ( !val3 )
val3 = 50;
if( sd ) {
- if( pc_isriding(sd) ) pc->setriding(sd, 0);
- if( pc_isridingdragon(sd) ) pc->setoption(sd, sd->sc.option&~OPTION_DRAGON);
+ if (pc_isridingpeco(sd))
+ pc->setridingpeco(sd, false);
+ if (pc_isridingdragon(sd))
+ pc->setridingdragon(sd, false);
}
}
break;
@@ -8786,18 +8808,16 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
struct block_list * src2;
val3 = st->agi * val1 / 60; // ASPD increase: [(Target AGI x Skill Level) / 60] %
if( (src2 = map->id2bl(val2)) ){
- val4 = ( 200/status_get_int(src2)?status_get_int(src2):1 ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
+ val4 = ( 200/(status_get_int(src2)?status_get_int(src2):1) ) * val1;// MDEF decrease: MDEF [(200 / Caster INT) x Skill Level]
val2 = ( status_get_dex(src2)/4 + status_get_str(src2)/2 ) * val1 / 5; // ATK increase: ATK [{(Caster DEX / 4) + (Caster STR / 2)} x Skill Level / 5]
}
}
break;
case SC_GENTLETOUCH_REVITALIZE:
- {// take note there is no vit,aspd,speed increase as skill desc says. [malufett]
- struct block_list * src2;
- val3 = val1 * 30 + 150; // Natural HP recovery increase: [(Skill Level x 30) + 50] %
- if( (src2 = map->id2bl(val2)) ) // the stat def is not shown in the status window and it is process differently
- val4 = ( status_get_vit(src2)/4 ) * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level]
- }
+ if(val2 < 0)
+ val2 = 0;
+ else
+ val2 = val2 / 4 * val1; // STAT DEF increase: [(Caster VIT / 4) x Skill Level]
break;
case SC_PYROTECHNIC_OPTION:
val2 = 60;
@@ -8910,9 +8930,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val4 = tick / 10000;
tick_time = 10000; // [GodLesZ] tick time
break;
- case SC_KYOUGAKU:
- val2 = 2*val1 + rand()%(3 * val1);
- clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise
+ case SC_KYOUGAKU: {
+ int min = val1*2;
+ int max = val1*3;
+ val3 = rnd()%(max-min)+min;
+ val2 = val1;
+ val1 = 1002; // Monster ID
+ }
break;
case SC_KAGEMUSYA:
val3 = val1 * 2;
@@ -9059,9 +9083,6 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_KAAHI:
val4 = INVALID_TIMER;
break;
- case SC_KYOUGAKU:
- clif->status_change(bl, SI_ACTIVE_MONSTER_TRANSFORM, 1, 0, 1002, 0, 0); // Poring in disguise
- break;
}
}
@@ -9182,6 +9203,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_WATER_BARRIER:
val_flag |= 1|2|4;
break;
+ case SC_KYOUGAKU:
+ val_flag |= 1;
+ break;
case SC_CASH_PLUSEXP:
case SC_CASH_PLUSONLYJOBEXP:
case SC_MONSTER_TRANSFORM:
@@ -9240,7 +9264,6 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_CURSEDCIRCLE_TARGET:
case SC_FEAR:
case SC_MEIKYOUSISUI:
- case SC_KYOUGAKU:
case SC_NEEDLE_OF_PARALYZE:
case SC_DEATHBOUND:
unit->stop_walking(bl,1);
@@ -10133,9 +10156,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
}
}
break;
- case SC_KYOUGAKU:
- clif->sc_end(&sd->bl,sd->bl.id,AREA,SI_ACTIVE_MONSTER_TRANSFORM);
- break;
case SC_CLAIRVOYANCE:
calc_flag = SCB_ALL;/* required for overlapping */
break;
@@ -10516,14 +10536,17 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_SIGHT:
case SC_RUWACH:
case SC_WZ_SIGHTBLASTER:
- if(type == SC_WZ_SIGHTBLASTER)
+ if(type == SC_WZ_SIGHTBLASTER) {
+ //Restore trap immunity
+ if(sce->val4%2)
+ sce->val4--;
map->foreachinrange(status->change_timer_sub, bl, sce->val3, BL_CHAR|BL_SKILL, bl, sce, type, tick);
- else
+ } else
map->foreachinrange(status->change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick);
if( --(sce->val2)>0 ){
- sce->val4 += 250; // use for Shadow Form 2 seconds checking.
- sc_timer_next(250+tick, status->change_timer, bl->id, data);
+ sce->val4 += 20; // use for Shadow Form 2 seconds checking.
+ sc_timer_next(20+tick, status->change_timer, bl->id, data);
return 0;
}
break;
@@ -11318,10 +11341,13 @@ int status_change_timer_sub(struct block_list* bl, va_list ap) {
if (battle->check_target( src, bl, BCT_ENEMY ) > 0
&& status->check_skilluse(src, bl, WZ_SIGHTBLASTER, 2)
) {
- 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.
+ struct skill_unit *su = (struct skill_unit *)bl;
+ if (sce && skill->attack(BF_MAGIC,src,src,bl,WZ_SIGHTBLASTER,sce->val1,tick,0x4000)
+ && (!su || !su->group || !(skill->get_inf2(su->group->skill_id)&INF2_TRAP))) { // The hit is not counted if it's against a trap
+ sce->val2 = 0; // This signals it to end.
+ } else if ((bl->type&BL_SKILL) && sce && sce->val4%2 == 0) {
+ //Remove trap immunity temporarily so it triggers if you still stand on it
+ sce->val4++;
}
}
break;
@@ -11368,7 +11394,7 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
if( !(flag&1) ){
if( max > min )
- max = min + rnd()%(max - min);
+ max = min + rnd()%(max - min + 1);
else
max = min;
}
diff --git a/src/map/status.h b/src/map/status.h
index 623ba7eb3..e96894e9f 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -730,7 +730,7 @@ typedef enum sc_type {
SC__FEINTBOMB_MASTER,
SC_FALLENEMPIRE,
- SC_FLASHCOMBO,
+ SC_FLASHCOMBO, // 580
//Vellum Weapon reductions
SC_DEFSET,
@@ -738,6 +738,12 @@ typedef enum sc_type {
SC_NO_SWITCH_EQUIP,
+ // 2014 Halloween Event
+ SC_MTF_MHP,
+ SC_MTF_MSP,
+ SC_MTF_PUMPKIN,
+ SC_MTF_HITFLEE,
+
SC_MAX, //Automatically updated max, used in for's to check we are within bounds.
} sc_type;
diff --git a/src/map/storage.c b/src/map/storage.c
index 217f14a3a..523f64cc8 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -351,7 +351,7 @@ DBData create_guildstorage(DBKey key, va_list args)
return DB->ptr2data(gs);
}
-struct guild_storage *guild2storage(int guild_id)
+struct guild_storage *guild2storage_ensure(int guild_id)
{
struct guild_storage *gs = NULL;
if(guild->search(guild_id) != NULL)
@@ -359,11 +359,6 @@ struct guild_storage *guild2storage(int guild_id)
return gs;
}
-//For just locating a storage without creating one. [Skotlex]
-struct guild_storage *guild2storage2(int guild_id) {
- return (struct guild_storage*)idb_get(gstorage->db,guild_id);
-}
-
int guild_storage_delete(int guild_id) {
idb_remove(gstorage->db,guild_id);
return 0;
@@ -393,7 +388,7 @@ int storage_guild_storageopen(struct map_session_data* sd)
return 1;
}
- if((gstor = gstorage->id2storage2(sd->status.guild_id)) == NULL) {
+ if((gstor = idb_get(gstorage->db,sd->status.guild_id)) == NULL) {
intif->request_guild_storage(sd->status.account_id,sd->status.guild_id);
return 0;
}
@@ -511,7 +506,7 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=gstorage->id2storage2(sd->status.guild_id));
+ nullpo_ret(stor=idb_get(gstorage->db,sd->status.guild_id));
if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE )
return 0;
@@ -551,7 +546,7 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
int flag;
nullpo_ret(sd);
- nullpo_ret(stor=guild2storage2(sd->status.guild_id));
+ nullpo_ret(stor=idb_get(gstorage->db,sd->status.guild_id));
if(!stor->storage_status)
return 0;
@@ -591,7 +586,7 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=guild2storage2(sd->status.guild_id));
+ nullpo_ret(stor=idb_get(gstorage->db,sd->status.guild_id));
if( !stor->storage_status || stor->storage_amount > MAX_GUILD_STORAGE )
return 0;
@@ -623,7 +618,7 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=guild2storage2(sd->status.guild_id));
+ nullpo_ret(stor=idb_get(gstorage->db,sd->status.guild_id));
if(!stor->storage_status)
return 0;
@@ -651,7 +646,7 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
*------------------------------------------*/
int storage_guild_storagesave(int account_id, int guild_id, int flag)
{
- struct guild_storage *stor = guild2storage2(guild_id);
+ struct guild_storage *stor = idb_get(gstorage->db,guild_id);
if(stor)
{
@@ -674,7 +669,7 @@ int storage_guild_storagesaved(int guild_id)
{
struct guild_storage *stor;
- if((stor=gstorage->id2storage2(guild_id)) != NULL) {
+ if((stor=idb_get(gstorage->db,guild_id)) != NULL) {
if (stor->dirty && stor->storage_status == 0)
{ //Storage has been correctly saved.
stor->dirty = 0;
@@ -689,7 +684,7 @@ int storage_guild_storageclose(struct map_session_data* sd) {
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=gstorage->id2storage2(sd->status.guild_id));
+ nullpo_ret(stor=idb_get(gstorage->db,sd->status.guild_id));
clif->storageclose(sd);
if (stor->storage_status) {
@@ -708,7 +703,7 @@ int storage_guild_storage_quit(struct map_session_data* sd, int flag) {
struct guild_storage *stor;
nullpo_ret(sd);
- nullpo_ret(stor=gstorage->id2storage2(sd->status.guild_id));
+ nullpo_ret(stor=idb_get(gstorage->db,sd->status.guild_id));
if(flag) {
//Only during a guild break flag is 1 (don't save storage)
@@ -765,8 +760,7 @@ void gstorage_defaults(void) {
gstorage->init = do_init_gstorage;
gstorage->final = do_final_gstorage;
/* */
- gstorage->id2storage = guild2storage;
- gstorage->id2storage2 = guild2storage2;
+ gstorage->ensure = guild2storage_ensure;
gstorage->delete = guild_storage_delete;
gstorage->open = storage_guild_storageopen;
gstorage->additem = guild_storage_additem;
diff --git a/src/map/storage.h b/src/map/storage.h
index 186f21263..fcf9a52e4 100644
--- a/src/map/storage.h
+++ b/src/map/storage.h
@@ -34,8 +34,7 @@ struct storage_interface *storage;
struct guild_storage_interface {
struct DBMap* db; // int guild_id -> struct guild_storage*
/* */
- struct guild_storage *(*id2storage) (int guild_id);
- struct guild_storage *(*id2storage2) (int guild_id);
+ struct guild_storage *(*ensure) (int guild_id);
/* */
void (*init) (bool minimal);
void (*final) (void);
diff --git a/src/map/unit.c b/src/map/unit.c
index 1f81e0d2f..044d7a43c 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -95,6 +95,8 @@ int unit_walktoxy_sub(struct block_list *bl)
ud = unit->bl2ud(bl);
if(ud == NULL) return 0;
+ memset(&wpd, 0, sizeof(wpd));
+
if( !path->search(&wpd,bl->m,bl->x,bl->y,ud->to_x,ud->to_y,ud->state.walk_easy,CELL_CHKNOPASS) )
return 0;
@@ -106,11 +108,11 @@ int unit_walktoxy_sub(struct block_list *bl)
uint8 dir;
//Trim the last part of the path to account for range,
//but always move at least one cell when requested to move.
- for (i = ud->chaserange*10; i > 0 && ud->walkpath.path_len>1;) {
+ for (i = (ud->chaserange*10)-10; i > 0 && ud->walkpath.path_len>1;) {
ud->walkpath.path_len--;
dir = ud->walkpath.path[ud->walkpath.path_len];
if(dir&1)
- i -= MOVE_DIAGONAL_COST;
+ i -= MOVE_COST*20; //When chasing, units will target a diamond-shaped area in range [Playtester]
else
i -= MOVE_COST;
ud->to_x -= dirx[dir];
@@ -137,9 +139,79 @@ int unit_walktoxy_sub(struct block_list *bl)
return 1;
}
+/**
+ * Triggered on full step if stepaction is true and executes remembered action.
+ * @param tid: Timer ID
+ * @param tick: Unused
+ * @param id: ID of bl to do the action
+ * @param data: Not used
+ * @return 1: Success 0: Fail (No valid bl)
+ */
+int unit_step_timer(int tid, int64 tick, int id, intptr_t data)
+{
+ struct block_list *bl;
+ struct unit_data *ud;
+ int target_id;
+
+ bl = map->id2bl(id);
+
+ if (!bl || bl->prev == NULL)
+ return 0;
+
+ ud = unit_bl2ud(bl);
+
+ if(!ud)
+ return 0;
+
+ if(ud->steptimer != tid) {
+ ShowError("unit_step_timer mismatch %d != %d\n",ud->steptimer,tid);
+ return 0;
+ }
+
+ ud->steptimer = INVALID_TIMER;
+
+ if(!ud->stepaction)
+ return 0;
+
+ //Set to false here because if an error occurs, it should not be executed again
+ ud->stepaction = false;
+
+ if(!ud->target_to)
+ return 0;
+
+ //Flush target_to as it might contain map coordinates which should not be used by other functions
+ target_id = ud->target_to;
+ ud->target_to = 0;
+
+ //If stepaction is set then we remembered a client request that should be executed on the next step
+ //Execute request now if target is in attack range
+ if(ud->stepskill_id && skill->get_inf(ud->stepskill_id) & INF_GROUND_SKILL) {
+ //Execute ground skill
+ struct map_data *md = &map->list[bl->m];
+ unit->skilluse_pos(bl, target_id%md->xs, target_id/md->xs, ud->stepskill_id, ud->stepskill_lv);
+ } else {
+ //If a player has target_id set and target is in range, attempt attack
+ struct block_list *tbl = map->id2bl(target_id);
+ if (!tbl || !status->check_visibility(bl, tbl)) {
+ return 0;
+ }
+ if(ud->stepskill_id == 0) {
+ //Execute normal attack
+ unit->attack(bl, tbl->id, (ud->state.attack_continue) + 2);
+ } else {
+ //Execute non-ground skill
+ unit->skilluse_id(bl, tbl->id, ud->stepskill_id, ud->stepskill_lv);
+ }
+ }
+
+ return 1;
+}
+
+
int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
int i;
int x,y,dx,dy;
+ unsigned char icewall_walk_block;
uint8 dir;
struct block_list *bl;
struct map_session_data *sd;
@@ -178,9 +250,34 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
dx = dirx[(int)dir];
dy = diry[(int)dir];
- if(map->getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS))
+ //Get icewall walk block depending on boss mode (players can't be trapped)
+ if(md && md->status.mode&MD_BOSS)
+ icewall_walk_block = battle_config.boss_icewall_walk_block;
+ else if(md)
+ icewall_walk_block = battle_config.mob_icewall_walk_block;
+ else
+ icewall_walk_block = 0;
+
+ //Monsters will walk into an icewall from the west and south if they already started walking
+ if(map->getcell(bl->m,x+dx,y+dy,CELL_CHKNOPASS)
+ && (icewall_walk_block == 0 || !map->getcell(bl->m,x+dx,y+dy,CELL_CHKICEWALL) || dx < 0 || dy < 0))
return unit->walktoxy_sub(bl);
+ //Monsters can only leave icewalls to the west and south
+ //But if movement fails more than icewall_walk_block times, they can ignore this rule
+ if(md && md->walktoxy_fail_count < icewall_walk_block && map->getcell(bl->m,x,y,CELL_CHKICEWALL) && (dx > 0 || dy > 0)) {
+ //Needs to be done here so that rudeattack skills are invoked
+ md->walktoxy_fail_count++;
+ clif->fixpos(bl);
+ //Monsters in this situation first use a chase skill, then unlock target and then use an idle skill
+ if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
+ mob->skill_use(md, tick, -1);
+ mob->unlocktarget(md, tick);
+ if (!(++ud->walk_count%WALK_SKILL_INTERVAL))
+ mob->skill_use(md, tick, -1);
+ return 0;
+ }
+
//Refresh view for all those we lose sight
map->foreachinmovearea(clif->outsight, bl, AREA_SIZE, dx, dy, sd?BL_ALL:BL_PC, bl);
@@ -231,6 +328,8 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
sd->hd->masterteleport_timer = 0;
}
} else if (md) {
+ //Movement was successful, reset walktoxy_fail_count
+ md->walktoxy_fail_count = 0;
if( map->getcell(bl->m,x,y,CELL_CHKNPC) ) {
if( npc->touch_areanpc2(md) ) return 0; // Warped
} else
@@ -240,9 +339,11 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
//But avoid triggering on stop-walk calls.
if(tid != INVALID_TIMER &&
!(ud->walk_count%WALK_SKILL_INTERVAL) &&
+ map->list[bl->m].users > 0 &&
mob->skill_use(md, tick, -1))
{
- if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER))
+ if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER)
+ && md->state.skillstate != MSS_WALK) //Walk skills are supposed to be used while walking
{ //Skill used, abort walking
clif->fixpos(bl); //Fix position as walk has been canceled.
return 0;
@@ -275,6 +376,21 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
if(tid == INVALID_TIMER) //A directly invoked timer is from battle_stop_walking, therefore the rest is irrelevant.
return 0;
+ //If stepaction is set then we remembered a client request that should be executed on the next step
+ if (ud->stepaction && ud->target_to) {
+ //Delete old stepaction even if not executed yet, the latest command is what counts
+ if(ud->steptimer != INVALID_TIMER) {
+ timer->delete(ud->steptimer, unit->step_timer);
+ ud->steptimer = INVALID_TIMER;
+ }
+ //Delay stepactions by half a step (so they are executed at full step)
+ if(ud->walkpath.path[ud->walkpath.path_pos]&1)
+ i = status->get_speed(bl)*14/20;
+ else
+ i = status->get_speed(bl)/2;
+ ud->steptimer = timer->add(tick+i, unit->step_timer, bl->id, 0);
+ }
+
if(ud->state.change_walk_target)
return unit->walktoxy_sub(bl);
@@ -294,7 +410,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
//Keep trying to run.
if ( !(unit->run(bl, NULL, SC_RUN) || unit->run(bl, sd, SC_WUGDASH)) )
ud->state.running = 0;
- } else if (ud->target_to) {
+ } else if (!ud->stepaction && ud->target_to) {
//Update target trajectory.
struct block_list *tbl = map->id2bl(ud->target_to);
if (!tbl || !status->check_visibility(bl, tbl)) {
@@ -323,6 +439,16 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
//Stopped walking. Update to_x and to_y to current location [Skotlex]
ud->to_x = bl->x;
ud->to_y = bl->y;
+
+ if(map->count_oncell(bl->m, x, y, BL_CHAR|BL_NPC, 1) > battle_config.official_cell_stack_limit) {
+ //Walked on occupied cell, call unit_walktoxy again
+ if(ud->steptimer != INVALID_TIMER) {
+ //Execute step timer on next step instead
+ timer->delete(ud->steptimer, unit_step_timer);
+ ud->steptimer = INVALID_TIMER;
+ }
+ return unit->walktoxy(bl, x, y, 8);
+ }
}
return 0;
}
@@ -340,6 +466,7 @@ int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
//&1 -> 1/0 = easy/hard
//&2 -> force walking
//&4 -> Delay walking if the reason you can't walk is the canwalk delay
+//&8 -> Search for an unoccupied cell and cancel if none available
int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
{
struct unit_data* ud = NULL;
@@ -352,6 +479,9 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
if( ud == NULL) return 0;
+ if ((flag&8) && !map->closest_freecell(bl->m, &x, &y, BL_CHAR|BL_NPC, 1)) //This might change x and y
+ return 0;
+
if (!path->search(&wpd, bl->m, bl->x, bl->y, x, y, flag&1, CELL_CHKNOPASS)) // Count walk path cells
return 0;
@@ -377,7 +507,7 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
ud->state.walk_easy = flag&1;
ud->to_x = x;
ud->to_y = y;
- unit->set_target(ud, 0);
+ unit->stop_attack(bl); //Sets target to 0
sc = status->get_sc(bl);
if( sc ) {
@@ -394,11 +524,6 @@ int unit_walktoxy( struct block_list *bl, short x, short y, int flag)
return 1;
}
- if(ud->attacktimer != INVALID_TIMER) {
- timer->delete( ud->attacktimer, unit->attack_timer );
- ud->attacktimer = INVALID_TIMER;
- }
-
return unit->walktoxy_sub(bl);
}
@@ -453,7 +578,7 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
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);
+ unit->stop_attack(bl); //Sets target to 0
sc = status->get_sc(bl);
if (sc && (sc->data[SC_CONFUSION] || sc->data[SC__CHAOS])) //Randomize the target position
@@ -474,11 +599,6 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
if(!unit->can_move(bl))
return 0;
- if(ud->attacktimer != INVALID_TIMER) {
- timer->delete( ud->attacktimer, unit->attack_timer );
- ud->attacktimer = INVALID_TIMER;
- }
-
if (unit->walktoxy_sub(bl)) {
set_mobstate(bl, flag&2);
return 1;
@@ -548,7 +668,7 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type
break;
//if sprinting and there's a PC/Mob/NPC, block the path [Kevin]
- if( map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC) )
+ if( map->count_oncell(bl->m, to_x+dir_x, to_y+dir_y, BL_PC|BL_MOB|BL_NPC, 0) )
break;
to_x += dir_x;
@@ -700,6 +820,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
}
if( sd ) {
+ unit->stop_stepaction(bl); //Stop stepaction when knocked back
sd->ud.to_x = nx;
sd->ud.to_y = ny;
}
@@ -930,7 +1051,7 @@ int unit_can_move(struct block_list *bl) {
|| sc->data[SC_ELECTRICSHOCKER]
|| sc->data[SC_WUGBITE]
|| sc->data[SC_THORNS_TRAP]
- || sc->data[SC_MAGNETICFIELD]
+ || ( sc->data[SC_MAGNETICFIELD] && !sc->data[SC_HOVERING] )
|| sc->data[SC__MANHOLE]
|| sc->data[SC_CURSEDCIRCLE_ATKER]
|| sc->data[SC_CURSEDCIRCLE_TARGET]
@@ -939,7 +1060,6 @@ int unit_can_move(struct block_list *bl) {
|| (sc->data[SC_CAMOUFLAGE] && sc->data[SC_CAMOUFLAGE]->val1 < 3 && !(sc->data[SC_CAMOUFLAGE]->val3&1))
|| sc->data[SC_MEIKYOUSISUI]
|| sc->data[SC_KG_KAGEHUMI]
- || sc->data[SC_KYOUGAKU]
|| sc->data[SC_NEEDLE_OF_PARALYZE]
|| sc->data[SC_VACUUM_EXTREME]
|| (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0)
@@ -965,6 +1085,17 @@ int unit_can_move(struct block_list *bl) {
return 0;
}
+
+ // Icewall walk block special trapped monster mode
+ if(bl->type == BL_MOB) {
+ struct mob_data *md = BL_CAST(BL_MOB, bl);
+ if(md && ((md->status.mode&MD_BOSS && battle_config.boss_icewall_walk_block == 1 && map->getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL))
+ || (!(md->status.mode&MD_BOSS) && battle_config.mob_icewall_walk_block == 1 && map->getcell(bl->m,bl->x,bl->y,CELL_CHKICEWALL)))) {
+ md->walktoxy_fail_count = 1; //Make sure rudeattacked skills are invoked
+ return 0;
+ }
+ }
+
return 1;
}
@@ -1000,12 +1131,6 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) {
struct unit_data *ud = unit->bl2ud(bl);
if (delay <= 0 || !ud) return 0;
- /**
- * MvP mobs have no walk delay
- **/
- if( bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS) )
- return 0;
-
if (type) {
if (DIFF_TICK(ud->canmove_tick, tick+delay) > 0)
return 0;
@@ -1013,6 +1138,9 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) {
//Don't set walk delays when already trapped.
if (!unit->can_move(bl))
return 0;
+ //Immune to being stopped for double the flinch time
+ if (DIFF_TICK(ud->canmove_tick, tick-delay) > 0)
+ return 0;
}
ud->canmove_tick = tick + delay;
if (ud->walktimer != INVALID_TIMER)
@@ -1028,7 +1156,7 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) {
}
else
{
- unit->stop_walking(bl,2|4);
+ unit->stop_walking(bl,4);
if(ud->target)
timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
}
@@ -1103,6 +1231,17 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
return 0;
}
break;
+ case GC_WEAPONCRUSH:
+ if( sc && sc->data[SC_COMBOATTACK] && sc->data[SC_COMBOATTACK]->val1 == GC_WEAPONBLOCKING ) {
+ if( (target=map->id2bl(sc->data[SC_COMBOATTACK]->val2)) == NULL ) {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0);
+ return 0;
+ }
+ } else {
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_GC_WEAPONBLOCKING,0);
+ return 0;
+ }
+ break;
}
if (target)
target_id = target->id;
@@ -1213,6 +1352,18 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
else
range = skill->get_range2(src, skill_id, skill_lv); // Skill cast distance from database
+ // New action request received, delete previous action request if not executed yet
+ if(ud->stepaction || ud->steptimer != INVALID_TIMER)
+ unit->stop_stepaction(src);
+ // Remember the skill request from the client while walking to the next cell
+ if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && !battle->check_range(src, target, range-1)) {
+ ud->stepaction = true;
+ ud->target_to = target_id;
+ ud->stepskill_id = skill_id;
+ ud->stepskill_lv = skill_lv;
+ return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ }
+
//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) ) {
@@ -1269,6 +1420,12 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
}
}
break;
+ case AB_CLEARANCE:
+ if( target->type != BL_MOB && battle->check_target(src,target,BCT_PARTY) <= 0 && sd ) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0);
+ return 0;
+ }
+ break;
case SR_GATEOFHELL:
case SR_TIGERCANNON:
if (sc && sc->data[SC_COMBOATTACK] &&
@@ -1469,6 +1626,12 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
+ /**
+ * "WHY IS IT HEREE": ice wall cannot be canceled past this point, the client displays the animation even,
+ * if we cancel it from castend_pos, so it has to be here for it to not display the animation.
+ **/
+ if ( skill_id == WZ_ICEWALL && map->getcell(src->m, skill_x, skill_y, CELL_CHKNOICEWALL) )
+ return 0;
}
if (!status->check_skilluse(src, NULL, skill_id, 0))
@@ -1491,10 +1654,24 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
else
range = skill->get_range2(src, skill_id, skill_lv); // Skill cast distance from database
+ // New action request received, delete previous action request if not executed yet
+ if(ud->stepaction || ud->steptimer != INVALID_TIMER)
+ unit->stop_stepaction(src);
+ // Remember the skill request from the client while walking to the next cell
+ if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && !battle->check_range(src, &bl, range-1)) {
+ struct map_data *md = &map->list[src->m];
+ // Convert coordinates to target_to so we can use it as target later
+ ud->stepaction = true;
+ ud->target_to = (skill_x + skill_y*md->xs);
+ ud->stepskill_id = skill_id;
+ ud->stepskill_lv = skill_lv;
+ return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ }
+
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) )
return 0; //Arrow-path check failed.
unit->stop_attack(src);
@@ -1576,18 +1753,51 @@ int unit_set_target(struct unit_data* ud, int target_id)
return 0;
}
-int unit_stop_attack(struct block_list *bl)
+/**
+ * Stop a unit's attacks
+ * @param bl: Object to stop
+ */
+void unit_stop_attack(struct block_list *bl)
{
- struct unit_data *ud = unit->bl2ud(bl);
- nullpo_ret(bl);
+ struct unit_data *ud;
+ nullpo_retv(bl);
+ ud = unit_bl2ud(bl);
+ nullpo_retv(ud);
- if(!ud || ud->attacktimer == INVALID_TIMER)
- return 0;
+ //Clear target
+ unit_set_target(ud, 0);
- timer->delete( ud->attacktimer, unit->attack_timer );
+ if(ud->attacktimer == INVALID_TIMER)
+ return;
+
+ //Clear timer
+ timer->delete(ud->attacktimer, unit->attack_timer);
ud->attacktimer = INVALID_TIMER;
- unit->set_target(ud, 0);
- return 0;
+}
+
+/**
+ * Stop a unit's step action
+ * @param bl: Object to stop
+ */
+void unit_stop_stepaction(struct block_list *bl)
+{
+ struct unit_data *ud;
+ nullpo_retv(bl);
+ ud = unit_bl2ud(bl);
+ nullpo_retv(ud);
+
+ //Clear remembered step action
+ ud->stepaction = false;
+ ud->target_to = 0;
+ ud->stepskill_id = 0;
+ ud->stepskill_lv = 0;
+
+ if(ud->steptimer == INVALID_TIMER)
+ return;
+
+ //Clear timer
+ timer->delete(ud->steptimer, unit->step_timer);
+ ud->steptimer = INVALID_TIMER;
}
//Means current target is unattackable. For now only unlocks mobs.
@@ -1596,6 +1806,7 @@ int unit_unattackable(struct block_list *bl)
struct unit_data *ud = unit->bl2ud(bl);
if (ud) {
ud->state.attack_continue = 0;
+ ud->state.step_attack = 0;
unit->set_target(ud, 0);
}
@@ -1613,6 +1824,7 @@ int unit_unattackable(struct block_list *bl)
int unit_attack(struct block_list *src,int target_id,int continuous) {
struct block_list *target;
struct unit_data *ud;
+ int range;
nullpo_ret(ud = unit->bl2ud(src));
@@ -1641,19 +1853,30 @@ int unit_attack(struct block_list *src,int target_id,int continuous) {
unit->unattackable(src);
return 1;
}
- ud->state.attack_continue = continuous;
+ ud->state.attack_continue = (continuous&1)?1:0;
+ ud->state.step_attack = (continuous&2)?1:0;
unit->set_target(ud, target_id);
+ range = status_get_range(src);
+
if (continuous) //If you're to attack continuously, set to auto-case character
- ud->chaserange = status_get_range(src);
+ ud->chaserange = range;
//Just change target/type. [Skotlex]
if(ud->attacktimer != INVALID_TIMER)
return 0;
- //Set Mob's ANGRY/BERSERK states.
- if(src->type == BL_MOB)
- ((TBL_MOB*)src)->state.skillstate = ((TBL_MOB*)src)->state.aggressive?MSS_ANGRY:MSS_BERSERK;
+ // New action request received, delete previous action request if not executed yet
+ if(ud->stepaction || ud->steptimer != INVALID_TIMER)
+ unit->stop_stepaction(src);
+ // Remember the attack request from the client while walking to the next cell
+ if(src->type == BL_PC && ud->walktimer != INVALID_TIMER && !battle->check_range(src, target, range-1)) {
+ ud->stepaction = true;
+ ud->target_to = ud->target;
+ ud->stepskill_id = 0;
+ ud->stepskill_lv = 0;
+ return 0; // Attacking will be handled by unit_walktoxy_timer in this case
+ }
if(DIFF_TICK(ud->attackabletime, timer->gettick()) > 0)
//Do attack next time it is possible. [Skotlex]
@@ -1855,15 +2078,19 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
}
sstatus = status->get_status_data(src);
- range = sstatus->rhw.range + 1;
+ range = sstatus->rhw.range;
- if( unit->is_walking(target) )
- range++; //Extra range when chasing
- if( !check_distance_bl(src,target,range) ) { //Chase if required.
- if(sd)
- clif->movetoattack(sd,target);
- else if(ud->state.attack_continue)
- unit->walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
+ if( (unit_is_walking(target) || ud->state.step_attack)
+ && (target->type == BL_PC || !map->getcell(target->m,target->x,target->y,CELL_CHKICEWALL)) )
+ range++; // Extra range when chasing (does not apply to mobs locked in an icewall)
+
+ if(sd && !check_distance_client_bl(src,target,range)) {
+ // Player tries to attack but target is too far, notify client
+ clif->movetoattack(sd,target);
+ return 1;
+ } else if(md && !check_distance_bl(src,target,range)) {
+ // Monster: Chase if required
+ unit_walktobl(src,target,ud->chaserange,ud->state.walk_easy|2);
return 1;
}
if( !battle->check_range(src,target,range) ) {
@@ -1885,8 +2112,15 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
if(ud->walktimer != INVALID_TIMER)
unit->stop_walking(src,1);
if(md) {
- if (mob->skill_use(md,tick,-1))
- return 1;
+ //First attack is always a normal attack
+ if(md->state.skillstate == MSS_ANGRY || md->state.skillstate == MSS_BERSERK) {
+ if (mob->skill_use(md,tick,-1))
+ return 1;
+ } else {
+ // Set mob's ANGRY/BERSERK states.
+ md->state.skillstate = md->state.aggressive?MSS_ANGRY:MSS_BERSERK;
+ }
+
if (sstatus->mode&MD_ASSIST && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME)
{ // Link monsters nearby [Skotlex]
md->last_linktime = tick;
@@ -2003,6 +2237,7 @@ void unit_dataset(struct block_list *bl) {
ud->walktimer = INVALID_TIMER;
ud->skilltimer = INVALID_TIMER;
ud->attacktimer = INVALID_TIMER;
+ ud->steptimer = INVALID_TIMER;
ud->attackabletime =
ud->canact_tick =
ud->canmove_tick = timer->gettick();
@@ -2068,15 +2303,19 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
map->freeblock_lock();
- unit->set_target(ud, 0);
-
if (ud->walktimer != INVALID_TIMER)
unit->stop_walking(bl,0);
- if (ud->attacktimer != INVALID_TIMER)
- unit->stop_attack(bl);
if (ud->skilltimer != INVALID_TIMER)
unit->skillcastcancel(bl,0);
+ //Clear target even if there is no timer
+ if (ud->target || ud->attacktimer != INVALID_TIMER)
+ unit_stop_attack(bl);
+
+ //Clear stepaction even if there is no timer
+ if (ud->stepaction || ud->steptimer != INVALID_TIMER)
+ unit->stop_stepaction(bl);
+
// Do not reset can-act delay. [Skotlex]
ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = timer->gettick();
if(sc && sc->count ) { //map-change/warp dispells.
@@ -2200,7 +2439,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
sd->debug_file, sd->debug_line, sd->debug_func, file, line, func);
} else if (--map->list[bl->m].users == 0 && battle_config.dynamic_mobs) //[Skotlex]
map->removemobs(bl->m);
- if( !(sd->sc.option&OPTION_INVISIBLE) ) {
+ if (!(pc_isinvisible(sd))) {
// decrement the number of active pvp players on the map
--map->list[bl->m].users_pvp;
}
@@ -2589,6 +2828,7 @@ int do_init_unit(bool minimal) {
timer->add_func_list(unit->walktoxy_timer,"unit_walktoxy_timer");
timer->add_func_list(unit->walktobl_sub, "unit_walktobl_sub");
timer->add_func_list(unit->delay_walktoxy_timer,"unit_delay_walktoxy_timer");
+ timer->add_func_list(unit->step_timer,"unit_step_timer");
return 0;
}
@@ -2622,6 +2862,8 @@ void unit_defaults(void) {
unit->warp = unit_warp;
unit->stop_walking = unit_stop_walking;
unit->skilluse_id = unit_skilluse_id;
+ unit->step_timer = unit_step_timer;
+ unit->stop_stepaction = unit_stop_stepaction;
unit->is_walking = unit_is_walking;
unit->can_move = unit_can_move;
unit->resume_running = unit_resume_running;
diff --git a/src/map/unit.h b/src/map/unit.h
index 9b95bae41..881fa16f4 100644
--- a/src/map/unit.h
+++ b/src/map/unit.h
@@ -30,6 +30,9 @@ struct unit_data {
int attacktimer;
int walktimer;
int chaserange;
+ bool stepaction; //Action should be executed on step [Playtester]
+ int steptimer; //Timer that triggers the action [Playtester]
+ uint16 stepskill_id,stepskill_lv; //Remembers skill that should be casted on step [Playtester]
int64 attackabletime;
int64 canact_tick;
int64 canmove_tick;
@@ -40,6 +43,7 @@ struct unit_data {
unsigned change_walk_target : 1 ;
unsigned skillcastcancel : 1 ;
unsigned attack_continue : 1 ;
+ unsigned step_attack : 1;
unsigned walk_easy : 1 ;
unsigned running : 1;
unsigned speed_changed : 1;
@@ -93,6 +97,8 @@ struct unit_interface {
int (*warp) (struct block_list *bl, short m, short x, short y, clr_type type);
int (*stop_walking) (struct block_list *bl, int type);
int (*skilluse_id) (struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv);
+ int (*step_timer) (int tid, int64 tick, int id, intptr_t data);
+ void (*stop_stepaction) (struct block_list *bl);
int (*is_walking) (struct block_list *bl);
int (*can_move) (struct block_list *bl);
int (*resume_running) (int tid, int64 tick, int id, intptr_t data);
@@ -101,7 +107,7 @@ struct unit_interface {
int (*skilluse_pos) (struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv);
int (*skilluse_pos2) (struct block_list *src, short skill_x, short skill_y, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel);
int (*set_target) (struct unit_data *ud, int target_id);
- int (*stop_attack) (struct block_list *bl);
+ void (*stop_attack) (struct block_list *bl);
int (*unattackable) (struct block_list *bl);
int (*attack) (struct block_list *src, int target_id, int continuous);
int (*cancel_combo) (struct block_list *bl);
diff --git a/src/plugins/HPMHooking.c b/src/plugins/HPMHooking.c
index 46792b268..3f3ecc4ec 100644
--- a/src/plugins/HPMHooking.c
+++ b/src/plugins/HPMHooking.c
@@ -11,6 +11,29 @@
#include "../common/malloc.h"
#include "../common/mmo.h"
#include "../common/socket.h"
+
+#if defined (HPMHOOKING_LOGIN)
+#define HPM_SERVER_TYPE SERVER_TYPE_LOGIN
+#define HPM_CORE_INCLUDE "../plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc"
+#define HPM_SYMBOL_INCLUDE "../plugins/HPMHooking/HPMHooking_login.GetSymbol.inc"
+#define HPM_HOOKS_INCLUDE "../plugins/HPMHooking/HPMHooking_login.Hooks.inc"
+#define HPM_POINTS_INCLUDE "../plugins/HPMHooking/HPMHooking_login.HookingPoints.inc"
+#define HPM_SOURCES_INCLUDE "../plugins/HPMHooking/HPMHooking_login.sources.inc"
+#elif defined (HPMHOOKING_CHAR)
+#define HPM_SERVER_TYPE SERVER_TYPE_CHAR
+#define HPM_CORE_INCLUDE "../plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc"
+#define HPM_SYMBOL_INCLUDE "../plugins/HPMHooking/HPMHooking_char.GetSymbol.inc"
+#define HPM_HOOKS_INCLUDE "../plugins/HPMHooking/HPMHooking_char.Hooks.inc"
+#define HPM_POINTS_INCLUDE "../plugins/HPMHooking/HPMHooking_char.HookingPoints.inc"
+#define HPM_SOURCES_INCLUDE "../plugins/HPMHooking/HPMHooking_char.sources.inc"
+#include "../char/pincode.h"
+#elif defined (HPMHOOKING_MAP)
+#define HPM_SERVER_TYPE SERVER_TYPE_MAP
+#define HPM_CORE_INCLUDE "../plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc"
+#define HPM_SYMBOL_INCLUDE "../plugins/HPMHooking/HPMHooking_map.GetSymbol.inc"
+#define HPM_HOOKS_INCLUDE "../plugins/HPMHooking/HPMHooking_map.Hooks.inc"
+#define HPM_POINTS_INCLUDE "../plugins/HPMHooking/HPMHooking_map.HookingPoints.inc"
+#define HPM_SOURCES_INCLUDE "../plugins/HPMHooking/HPMHooking_map.sources.inc"
#include "../map/atcommand.h"
#include "../map/battle.h"
#include "../map/battleground.h"
@@ -44,13 +67,22 @@
#include "../map/storage.h"
#include "../map/trade.h"
#include "../map/unit.h"
+#else
+#define HPM_SERVER_TYPE SERVER_TYPE_UNKNOWN
+#define HPM_CORE_INCLUDE "../plugins/HPMHooking/HPMHooking.HPMHooksCore.inc"
+#define HPM_SYMBOL_INCLUDE "../plugins/HPMHooking/HPMHooking.GetSymbol.inc"
+#define HPM_HOOKS_INCLUDE "../plugins/HPMHooking/HPMHooking.Hooks.inc"
+#define HPM_POINTS_INCLUDE "../plugins/HPMHooking/HPMHooking.HookingPoints.inc"
+#define HPM_SOURCES_INCLUDE "../plugins/HPMHooking/HPMHooking.sources.inc"
+#error HPMHooking plugin needs to be compiled for a specific server type. Please make sure your Makefiles are up to date.
+#endif
#include "../common/HPMDataCheck.h"
HPExport struct hplugin_info pinfo = {
"HPMHooking", // Plugin name
- SERVER_TYPE_MAP,// Which server types this plugin works with?
- "0.1", // Plugin version
+ HPM_SERVER_TYPE,// Which server types this plugin works with?
+ "0.2", // Plugin version
HPM_VERSION, // HPM Version (don't change, macro is automatically updated)
};
@@ -70,7 +102,7 @@ struct HPMHookPoint {
};
struct HPMHooksCore {
- #include "../plugins/HPMHooking/HPMHooking.HPMHooksCore.inc"
+ #include HPM_CORE_INCLUDE
struct {
int total;
} data;
@@ -89,7 +121,7 @@ HPExport bool Hooked (bool *fr) {
HPMforce_return = fr;
DB = GET_SYMBOL("DB");
iMalloc = GET_SYMBOL("iMalloc");
-#include "../plugins/HPMHooking/HPMHooking.GetSymbol.inc"
+#include HPM_SYMBOL_INCLUDE
HPM_HP_load();
return true;
}
@@ -127,7 +159,7 @@ HPExport bool HPM_Plugin_AddHook(enum HPluginHookType type, const char *target,
return false;
}
-#include "../plugins/HPMHooking/HPMHooking.Hooks.inc"
+#include HPM_HOOKS_INCLUDE
void HPM_HP_final(void) {
int i, len = HPMHooks.data.total * 2;
@@ -149,7 +181,7 @@ void HPM_HP_final(void) {
}
void HPM_HP_load(void) {
- #include "../plugins/HPMHooking/HPMHooking.HookingPoints.inc"
+ #include HPM_POINTS_INCLUDE
int i, len = ARRAYLENGTH(HookingPoints), idx = 0;
memset(&HPMHooks,0,sizeof(struct HPMHooksCore));
@@ -171,6 +203,6 @@ void HPM_HP_load(void) {
HPMHooks.data.total++;
}
- #include "../plugins/HPMHooking/HPMHooking.sources.inc"
+ #include HPM_SOURCES_INCLUDE
}
diff --git a/src/plugins/HPMHooking/HPMHooking_char.GetSymbol.inc b/src/plugins/HPMHooking/HPMHooking_char.GetSymbol.inc
new file mode 100644
index 000000000..84800ca49
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_char.GetSymbol.inc
@@ -0,0 +1,7 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
+if( !(pincode = GET_SYMBOL("pincode") ) ) return false;
diff --git a/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
new file mode 100644
index 000000000..4a940739f
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_char.HPMHooksCore.inc
@@ -0,0 +1,55 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
+struct {
+ struct HPMHookPoint *HP_pincode_handle_pre;
+ struct HPMHookPoint *HP_pincode_handle_post;
+ struct HPMHookPoint *HP_pincode_decrypt_pre;
+ struct HPMHookPoint *HP_pincode_decrypt_post;
+ struct HPMHookPoint *HP_pincode_error_pre;
+ struct HPMHookPoint *HP_pincode_error_post;
+ struct HPMHookPoint *HP_pincode_update_pre;
+ struct HPMHookPoint *HP_pincode_update_post;
+ struct HPMHookPoint *HP_pincode_sendstate_pre;
+ struct HPMHookPoint *HP_pincode_sendstate_post;
+ struct HPMHookPoint *HP_pincode_setnew_pre;
+ struct HPMHookPoint *HP_pincode_setnew_post;
+ struct HPMHookPoint *HP_pincode_change_pre;
+ struct HPMHookPoint *HP_pincode_change_post;
+ struct HPMHookPoint *HP_pincode_compare_pre;
+ struct HPMHookPoint *HP_pincode_compare_post;
+ struct HPMHookPoint *HP_pincode_check_pre;
+ struct HPMHookPoint *HP_pincode_check_post;
+ struct HPMHookPoint *HP_pincode_config_read_pre;
+ struct HPMHookPoint *HP_pincode_config_read_post;
+} list;
+
+struct {
+ int HP_pincode_handle_pre;
+ int HP_pincode_handle_post;
+ int HP_pincode_decrypt_pre;
+ int HP_pincode_decrypt_post;
+ int HP_pincode_error_pre;
+ int HP_pincode_error_post;
+ int HP_pincode_update_pre;
+ int HP_pincode_update_post;
+ int HP_pincode_sendstate_pre;
+ int HP_pincode_sendstate_post;
+ int HP_pincode_setnew_pre;
+ int HP_pincode_setnew_post;
+ int HP_pincode_change_pre;
+ int HP_pincode_change_post;
+ int HP_pincode_compare_pre;
+ int HP_pincode_compare_post;
+ int HP_pincode_check_pre;
+ int HP_pincode_check_post;
+ int HP_pincode_config_read_pre;
+ int HP_pincode_config_read_post;
+} count;
+
+struct {
+ struct pincode_interface pincode;
+} source;
diff --git a/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
new file mode 100644
index 000000000..11c3b86a7
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_char.HookingPoints.inc
@@ -0,0 +1,21 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
+struct HookingPointData HookingPoints[] = {
+/* pincode */
+ { HP_POP(pincode->handle, HP_pincode_handle) },
+ { HP_POP(pincode->decrypt, HP_pincode_decrypt) },
+ { HP_POP(pincode->error, HP_pincode_error) },
+ { HP_POP(pincode->update, HP_pincode_update) },
+ { HP_POP(pincode->sendstate, HP_pincode_sendstate) },
+ { HP_POP(pincode->setnew, HP_pincode_setnew) },
+ { HP_POP(pincode->change, HP_pincode_change) },
+ { HP_POP(pincode->compare, HP_pincode_compare) },
+ { HP_POP(pincode->check, HP_pincode_check) },
+ { HP_POP(pincode->config_read, HP_pincode_config_read) },
+};
+
+int HookingPointsLenMax = 20;
diff --git a/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
new file mode 100644
index 000000000..d795ebb4a
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_char.Hooks.inc
@@ -0,0 +1,269 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
+/* pincode */
+void HP_pincode_handle(int fd, struct char_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_handle_pre ) {
+ void (*preHookFunc) (int *fd, struct char_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_handle_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_handle_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.handle(fd, sd);
+ }
+ if( HPMHooks.count.HP_pincode_handle_post ) {
+ void (*postHookFunc) (int *fd, struct char_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_handle_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_handle_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+void HP_pincode_decrypt(unsigned int userSeed, char *pin) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_decrypt_pre ) {
+ void (*preHookFunc) (unsigned int *userSeed, char *pin);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_decrypt_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_decrypt_pre[hIndex].func;
+ preHookFunc(&userSeed, pin);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.decrypt(userSeed, pin);
+ }
+ if( HPMHooks.count.HP_pincode_decrypt_post ) {
+ void (*postHookFunc) (unsigned int *userSeed, char *pin);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_decrypt_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_decrypt_post[hIndex].func;
+ postHookFunc(&userSeed, pin);
+ }
+ }
+ return;
+}
+void HP_pincode_error(int account_id) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_error_pre ) {
+ void (*preHookFunc) (int *account_id);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_error_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_error_pre[hIndex].func;
+ preHookFunc(&account_id);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.error(account_id);
+ }
+ if( HPMHooks.count.HP_pincode_error_post ) {
+ void (*postHookFunc) (int *account_id);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_error_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_error_post[hIndex].func;
+ postHookFunc(&account_id);
+ }
+ }
+ return;
+}
+void HP_pincode_update(int account_id, char *pin) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_update_pre ) {
+ void (*preHookFunc) (int *account_id, char *pin);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_update_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_update_pre[hIndex].func;
+ preHookFunc(&account_id, pin);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.update(account_id, pin);
+ }
+ if( HPMHooks.count.HP_pincode_update_post ) {
+ void (*postHookFunc) (int *account_id, char *pin);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_update_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_update_post[hIndex].func;
+ postHookFunc(&account_id, pin);
+ }
+ }
+ return;
+}
+void HP_pincode_sendstate(int fd, struct char_session_data *sd, uint16 state) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_sendstate_pre ) {
+ void (*preHookFunc) (int *fd, struct char_session_data *sd, uint16 *state);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_sendstate_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_sendstate_pre[hIndex].func;
+ preHookFunc(&fd, sd, &state);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.sendstate(fd, sd, state);
+ }
+ if( HPMHooks.count.HP_pincode_sendstate_post ) {
+ void (*postHookFunc) (int *fd, struct char_session_data *sd, uint16 *state);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_sendstate_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_sendstate_post[hIndex].func;
+ postHookFunc(&fd, sd, &state);
+ }
+ }
+ return;
+}
+void HP_pincode_setnew(int fd, struct char_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_setnew_pre ) {
+ void (*preHookFunc) (int *fd, struct char_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_setnew_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_setnew_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.setnew(fd, sd);
+ }
+ if( HPMHooks.count.HP_pincode_setnew_post ) {
+ void (*postHookFunc) (int *fd, struct char_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_setnew_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_setnew_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+void HP_pincode_change(int fd, struct char_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_change_pre ) {
+ void (*preHookFunc) (int *fd, struct char_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_change_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_change_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.change(fd, sd);
+ }
+ if( HPMHooks.count.HP_pincode_change_post ) {
+ void (*postHookFunc) (int *fd, struct char_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_change_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_change_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+int HP_pincode_compare(int fd, struct char_session_data *sd, char *pin) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if( HPMHooks.count.HP_pincode_compare_pre ) {
+ int (*preHookFunc) (int *fd, struct char_session_data *sd, char *pin);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_compare_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_compare_pre[hIndex].func;
+ retVal___ = preHookFunc(&fd, sd, pin);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.pincode.compare(fd, sd, pin);
+ }
+ if( HPMHooks.count.HP_pincode_compare_post ) {
+ int (*postHookFunc) (int retVal___, int *fd, struct char_session_data *sd, char *pin);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_compare_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_compare_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, &fd, sd, pin);
+ }
+ }
+ return retVal___;
+}
+void HP_pincode_check(int fd, struct char_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pincode_check_pre ) {
+ void (*preHookFunc) (int *fd, struct char_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_check_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_check_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pincode.check(fd, sd);
+ }
+ if( HPMHooks.count.HP_pincode_check_post ) {
+ void (*postHookFunc) (int *fd, struct char_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_check_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_check_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+bool HP_pincode_config_read(char *w1, char *w2) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if( HPMHooks.count.HP_pincode_config_read_pre ) {
+ bool (*preHookFunc) (char *w1, char *w2);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_config_read_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pincode_config_read_pre[hIndex].func;
+ retVal___ = preHookFunc(w1, w2);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.pincode.config_read(w1, w2);
+ }
+ if( HPMHooks.count.HP_pincode_config_read_post ) {
+ bool (*postHookFunc) (bool retVal___, char *w1, char *w2);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pincode_config_read_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pincode_config_read_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, w1, w2);
+ }
+ }
+ return retVal___;
+}
diff --git a/src/plugins/HPMHooking/HPMHooking_char.sources.inc b/src/plugins/HPMHooking/HPMHooking_char.sources.inc
new file mode 100644
index 000000000..fd5d2d2bf
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_char.sources.inc
@@ -0,0 +1,7 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
+memcpy(&HPMHooks.source.pincode, pincode, sizeof(struct pincode_interface));
diff --git a/src/plugins/HPMHooking/HPMHooking_login.GetSymbol.inc b/src/plugins/HPMHooking/HPMHooking_login.GetSymbol.inc
new file mode 100644
index 000000000..6dcfae29d
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_login.GetSymbol.inc
@@ -0,0 +1,6 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
diff --git a/src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc
new file mode 100644
index 000000000..4c380b367
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_login.HPMHooksCore.inc
@@ -0,0 +1,14 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
+struct {
+} list;
+
+struct {
+} count;
+
+struct {
+} source;
diff --git a/src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc
new file mode 100644
index 000000000..6752a4324
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_login.HookingPoints.inc
@@ -0,0 +1,10 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
+struct HookingPointData HookingPoints[] = {
+};
+
+int HookingPointsLenMax = 0;
diff --git a/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
new file mode 100644
index 000000000..6dcfae29d
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_login.Hooks.inc
@@ -0,0 +1,6 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
diff --git a/src/plugins/HPMHooking/HPMHooking_login.sources.inc b/src/plugins/HPMHooking/HPMHooking_login.sources.inc
new file mode 100644
index 000000000..6dcfae29d
--- /dev/null
+++ b/src/plugins/HPMHooking/HPMHooking_login.sources.inc
@@ -0,0 +1,6 @@
+// Copyright (c) Hercules Dev Team, licensed under GNU GPL.
+// See the LICENSE file
+//
+// NOTE: This file was auto-generated and should never be manually edited,
+// as it will get overwritten.
+
diff --git a/src/plugins/HPMHooking/HPMHooking.GetSymbol.inc b/src/plugins/HPMHooking/HPMHooking_map.GetSymbol.inc
index 8482b9f80..8482b9f80 100644
--- a/src/plugins/HPMHooking/HPMHooking.GetSymbol.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.GetSymbol.inc
diff --git a/src/plugins/HPMHooking/HPMHooking.HPMHooksCore.inc b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
index d73525b70..81e0c1c2d 100644
--- a/src/plugins/HPMHooking/HPMHooking.HPMHooksCore.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HPMHooksCore.inc
@@ -977,6 +977,8 @@ struct {
struct HPMHookPoint *HP_clif_party_show_picker_post;
struct HPMHookPoint *HP_clif_partyinvitationstate_pre;
struct HPMHookPoint *HP_clif_partyinvitationstate_post;
+ struct HPMHookPoint *HP_clif_PartyLeaderChanged_pre;
+ struct HPMHookPoint *HP_clif_PartyLeaderChanged_post;
struct HPMHookPoint *HP_clif_guild_created_pre;
struct HPMHookPoint *HP_clif_guild_created_post;
struct HPMHookPoint *HP_clif_guild_belonginfo_pre;
@@ -1299,6 +1301,10 @@ struct {
struct HPMHookPoint *HP_clif_npc_market_open_post;
struct HPMHookPoint *HP_clif_npc_market_purchase_ack_pre;
struct HPMHookPoint *HP_clif_npc_market_purchase_ack_post;
+ struct HPMHookPoint *HP_clif_parse_roulette_db_pre;
+ struct HPMHookPoint *HP_clif_parse_roulette_db_post;
+ struct HPMHookPoint *HP_clif_roulette_generate_ack_pre;
+ struct HPMHookPoint *HP_clif_roulette_generate_ack_post;
struct HPMHookPoint *HP_clif_pWantToConnection_pre;
struct HPMHookPoint *HP_clif_pWantToConnection_post;
struct HPMHookPoint *HP_clif_pLoadEndAck_pre;
@@ -1739,6 +1745,16 @@ struct {
struct HPMHookPoint *HP_clif_pBankOpen_post;
struct HPMHookPoint *HP_clif_pBankClose_pre;
struct HPMHookPoint *HP_clif_pBankClose_post;
+ struct HPMHookPoint *HP_clif_pRouletteOpen_pre;
+ struct HPMHookPoint *HP_clif_pRouletteOpen_post;
+ struct HPMHookPoint *HP_clif_pRouletteInfo_pre;
+ struct HPMHookPoint *HP_clif_pRouletteInfo_post;
+ struct HPMHookPoint *HP_clif_pRouletteClose_pre;
+ struct HPMHookPoint *HP_clif_pRouletteClose_post;
+ struct HPMHookPoint *HP_clif_pRouletteGenerate_pre;
+ struct HPMHookPoint *HP_clif_pRouletteGenerate_post;
+ struct HPMHookPoint *HP_clif_pRouletteRecvItem_pre;
+ struct HPMHookPoint *HP_clif_pRouletteRecvItem_post;
struct HPMHookPoint *HP_clif_pNPCShopClosed_pre;
struct HPMHookPoint *HP_clif_pNPCShopClosed_post;
struct HPMHookPoint *HP_clif_pNPCMarketClosed_pre;
@@ -1999,10 +2015,8 @@ struct {
struct HPMHookPoint *HP_guild_get_alliance_count_post;
struct HPMHookPoint *HP_guild_castle_reconnect_sub_pre;
struct HPMHookPoint *HP_guild_castle_reconnect_sub_post;
- struct HPMHookPoint *HP_gstorage_id2storage_pre;
- struct HPMHookPoint *HP_gstorage_id2storage_post;
- struct HPMHookPoint *HP_gstorage_id2storage2_pre;
- struct HPMHookPoint *HP_gstorage_id2storage2_post;
+ struct HPMHookPoint *HP_gstorage_ensure_pre;
+ struct HPMHookPoint *HP_gstorage_ensure_post;
struct HPMHookPoint *HP_gstorage_init_pre;
struct HPMHookPoint *HP_gstorage_init_post;
struct HPMHookPoint *HP_gstorage_final_pre;
@@ -2673,6 +2687,8 @@ struct {
struct HPMHookPoint *HP_map_get_new_object_id_post;
struct HPMHookPoint *HP_map_search_freecell_pre;
struct HPMHookPoint *HP_map_search_freecell_post;
+ struct HPMHookPoint *HP_map_closest_freecell_pre;
+ struct HPMHookPoint *HP_map_closest_freecell_post;
struct HPMHookPoint *HP_map_quit_pre;
struct HPMHookPoint *HP_map_quit_post;
struct HPMHookPoint *HP_map_addnpc_pre;
@@ -3471,6 +3487,10 @@ struct {
struct HPMHookPoint *HP_path_check_distance_post;
struct HPMHookPoint *HP_path_distance_pre;
struct HPMHookPoint *HP_path_distance_post;
+ struct HPMHookPoint *HP_path_check_distance_client_pre;
+ struct HPMHookPoint *HP_path_check_distance_client_post;
+ struct HPMHookPoint *HP_path_distance_client_pre;
+ struct HPMHookPoint *HP_path_distance_client_post;
struct HPMHookPoint *HP_pcg_init_pre;
struct HPMHookPoint *HP_pcg_init_post;
struct HPMHookPoint *HP_pcg_final_pre;
@@ -3707,10 +3727,14 @@ struct {
struct HPMHookPoint *HP_pc_setcart_post;
struct HPMHookPoint *HP_pc_setfalcon_pre;
struct HPMHookPoint *HP_pc_setfalcon_post;
- struct HPMHookPoint *HP_pc_setriding_pre;
- struct HPMHookPoint *HP_pc_setriding_post;
+ struct HPMHookPoint *HP_pc_setridingpeco_pre;
+ struct HPMHookPoint *HP_pc_setridingpeco_post;
struct HPMHookPoint *HP_pc_setmadogear_pre;
struct HPMHookPoint *HP_pc_setmadogear_post;
+ struct HPMHookPoint *HP_pc_setridingdragon_pre;
+ struct HPMHookPoint *HP_pc_setridingdragon_post;
+ struct HPMHookPoint *HP_pc_setridingwug_pre;
+ struct HPMHookPoint *HP_pc_setridingwug_post;
struct HPMHookPoint *HP_pc_changelook_pre;
struct HPMHookPoint *HP_pc_changelook_post;
struct HPMHookPoint *HP_pc_equiplookall_pre;
@@ -4563,8 +4587,6 @@ struct {
struct HPMHookPoint *HP_skill_greed_post;
struct HPMHookPoint *HP_skill_destroy_trap_pre;
struct HPMHookPoint *HP_skill_destroy_trap_post;
- struct HPMHookPoint *HP_skill_icewall_block_pre;
- struct HPMHookPoint *HP_skill_icewall_block_post;
struct HPMHookPoint *HP_skill_unitgrouptickset_search_pre;
struct HPMHookPoint *HP_skill_unitgrouptickset_search_post;
struct HPMHookPoint *HP_skill_dance_switch_pre;
@@ -4973,6 +4995,10 @@ struct {
struct HPMHookPoint *HP_unit_stop_walking_post;
struct HPMHookPoint *HP_unit_skilluse_id_pre;
struct HPMHookPoint *HP_unit_skilluse_id_post;
+ struct HPMHookPoint *HP_unit_step_timer_pre;
+ struct HPMHookPoint *HP_unit_step_timer_post;
+ struct HPMHookPoint *HP_unit_stop_stepaction_pre;
+ struct HPMHookPoint *HP_unit_stop_stepaction_post;
struct HPMHookPoint *HP_unit_is_walking_pre;
struct HPMHookPoint *HP_unit_is_walking_post;
struct HPMHookPoint *HP_unit_can_move_pre;
@@ -6014,6 +6040,8 @@ struct {
int HP_clif_party_show_picker_post;
int HP_clif_partyinvitationstate_pre;
int HP_clif_partyinvitationstate_post;
+ int HP_clif_PartyLeaderChanged_pre;
+ int HP_clif_PartyLeaderChanged_post;
int HP_clif_guild_created_pre;
int HP_clif_guild_created_post;
int HP_clif_guild_belonginfo_pre;
@@ -6336,6 +6364,10 @@ struct {
int HP_clif_npc_market_open_post;
int HP_clif_npc_market_purchase_ack_pre;
int HP_clif_npc_market_purchase_ack_post;
+ int HP_clif_parse_roulette_db_pre;
+ int HP_clif_parse_roulette_db_post;
+ int HP_clif_roulette_generate_ack_pre;
+ int HP_clif_roulette_generate_ack_post;
int HP_clif_pWantToConnection_pre;
int HP_clif_pWantToConnection_post;
int HP_clif_pLoadEndAck_pre;
@@ -6776,6 +6808,16 @@ struct {
int HP_clif_pBankOpen_post;
int HP_clif_pBankClose_pre;
int HP_clif_pBankClose_post;
+ int HP_clif_pRouletteOpen_pre;
+ int HP_clif_pRouletteOpen_post;
+ int HP_clif_pRouletteInfo_pre;
+ int HP_clif_pRouletteInfo_post;
+ int HP_clif_pRouletteClose_pre;
+ int HP_clif_pRouletteClose_post;
+ int HP_clif_pRouletteGenerate_pre;
+ int HP_clif_pRouletteGenerate_post;
+ int HP_clif_pRouletteRecvItem_pre;
+ int HP_clif_pRouletteRecvItem_post;
int HP_clif_pNPCShopClosed_pre;
int HP_clif_pNPCShopClosed_post;
int HP_clif_pNPCMarketClosed_pre;
@@ -7036,10 +7078,8 @@ struct {
int HP_guild_get_alliance_count_post;
int HP_guild_castle_reconnect_sub_pre;
int HP_guild_castle_reconnect_sub_post;
- int HP_gstorage_id2storage_pre;
- int HP_gstorage_id2storage_post;
- int HP_gstorage_id2storage2_pre;
- int HP_gstorage_id2storage2_post;
+ int HP_gstorage_ensure_pre;
+ int HP_gstorage_ensure_post;
int HP_gstorage_init_pre;
int HP_gstorage_init_post;
int HP_gstorage_final_pre;
@@ -7710,6 +7750,8 @@ struct {
int HP_map_get_new_object_id_post;
int HP_map_search_freecell_pre;
int HP_map_search_freecell_post;
+ int HP_map_closest_freecell_pre;
+ int HP_map_closest_freecell_post;
int HP_map_quit_pre;
int HP_map_quit_post;
int HP_map_addnpc_pre;
@@ -8508,6 +8550,10 @@ struct {
int HP_path_check_distance_post;
int HP_path_distance_pre;
int HP_path_distance_post;
+ int HP_path_check_distance_client_pre;
+ int HP_path_check_distance_client_post;
+ int HP_path_distance_client_pre;
+ int HP_path_distance_client_post;
int HP_pcg_init_pre;
int HP_pcg_init_post;
int HP_pcg_final_pre;
@@ -8744,10 +8790,14 @@ struct {
int HP_pc_setcart_post;
int HP_pc_setfalcon_pre;
int HP_pc_setfalcon_post;
- int HP_pc_setriding_pre;
- int HP_pc_setriding_post;
+ int HP_pc_setridingpeco_pre;
+ int HP_pc_setridingpeco_post;
int HP_pc_setmadogear_pre;
int HP_pc_setmadogear_post;
+ int HP_pc_setridingdragon_pre;
+ int HP_pc_setridingdragon_post;
+ int HP_pc_setridingwug_pre;
+ int HP_pc_setridingwug_post;
int HP_pc_changelook_pre;
int HP_pc_changelook_post;
int HP_pc_equiplookall_pre;
@@ -9600,8 +9650,6 @@ struct {
int HP_skill_greed_post;
int HP_skill_destroy_trap_pre;
int HP_skill_destroy_trap_post;
- int HP_skill_icewall_block_pre;
- int HP_skill_icewall_block_post;
int HP_skill_unitgrouptickset_search_pre;
int HP_skill_unitgrouptickset_search_post;
int HP_skill_dance_switch_pre;
@@ -10010,6 +10058,10 @@ struct {
int HP_unit_stop_walking_post;
int HP_unit_skilluse_id_pre;
int HP_unit_skilluse_id_post;
+ int HP_unit_step_timer_pre;
+ int HP_unit_step_timer_post;
+ int HP_unit_stop_stepaction_pre;
+ int HP_unit_stop_stepaction_post;
int HP_unit_is_walking_pre;
int HP_unit_is_walking_post;
int HP_unit_can_move_pre;
diff --git a/src/plugins/HPMHooking/HPMHooking.HookingPoints.inc b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
index 05d484d20..5fa0bff3f 100644
--- a/src/plugins/HPMHooking/HPMHooking.HookingPoints.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.HookingPoints.inc
@@ -498,6 +498,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->party_xy_remove, HP_clif_party_xy_remove) },
{ HP_POP(clif->party_show_picker, HP_clif_party_show_picker) },
{ HP_POP(clif->partyinvitationstate, HP_clif_partyinvitationstate) },
+ { HP_POP(clif->PartyLeaderChanged, HP_clif_PartyLeaderChanged) },
{ HP_POP(clif->guild_created, HP_clif_guild_created) },
{ HP_POP(clif->guild_belonginfo, HP_clif_guild_belonginfo) },
{ HP_POP(clif->guild_masterormember, HP_clif_guild_masterormember) },
@@ -659,6 +660,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->delay_damage_sub, HP_clif_delay_damage_sub) },
{ HP_POP(clif->npc_market_open, HP_clif_npc_market_open) },
{ HP_POP(clif->npc_market_purchase_ack, HP_clif_npc_market_purchase_ack) },
+ { HP_POP(clif->parse_roulette_db, HP_clif_parse_roulette_db) },
+ { HP_POP(clif->roulette_generate_ack, HP_clif_roulette_generate_ack) },
{ HP_POP(clif->pWantToConnection, HP_clif_pWantToConnection) },
{ HP_POP(clif->pLoadEndAck, HP_clif_pLoadEndAck) },
{ HP_POP(clif->pTickSend, HP_clif_pTickSend) },
@@ -879,6 +882,11 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(clif->pBankCheck, HP_clif_pBankCheck) },
{ HP_POP(clif->pBankOpen, HP_clif_pBankOpen) },
{ HP_POP(clif->pBankClose, HP_clif_pBankClose) },
+ { HP_POP(clif->pRouletteOpen, HP_clif_pRouletteOpen) },
+ { HP_POP(clif->pRouletteInfo, HP_clif_pRouletteInfo) },
+ { HP_POP(clif->pRouletteClose, HP_clif_pRouletteClose) },
+ { HP_POP(clif->pRouletteGenerate, HP_clif_pRouletteGenerate) },
+ { HP_POP(clif->pRouletteRecvItem, HP_clif_pRouletteRecvItem) },
{ HP_POP(clif->pNPCShopClosed, HP_clif_pNPCShopClosed) },
{ HP_POP(clif->pNPCMarketClosed, HP_clif_pNPCMarketClosed) },
{ HP_POP(clif->pNPCMarketPurchase, HP_clif_pNPCMarketPurchase) },
@@ -1013,8 +1021,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(guild->get_alliance_count, HP_guild_get_alliance_count) },
{ HP_POP(guild->castle_reconnect_sub, HP_guild_castle_reconnect_sub) },
/* gstorage */
- { HP_POP(gstorage->id2storage, HP_gstorage_id2storage) },
- { HP_POP(gstorage->id2storage2, HP_gstorage_id2storage2) },
+ { HP_POP(gstorage->ensure, HP_gstorage_ensure) },
{ HP_POP(gstorage->init, HP_gstorage_init) },
{ HP_POP(gstorage->final, HP_gstorage_final) },
{ HP_POP(gstorage->delete, HP_gstorage_delete) },
@@ -1358,6 +1365,7 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(map->find_skill_unit_oncell, HP_map_find_skill_unit_oncell) },
{ HP_POP(map->get_new_object_id, HP_map_get_new_object_id) },
{ HP_POP(map->search_freecell, HP_map_search_freecell) },
+ { HP_POP(map->closest_freecell, HP_map_closest_freecell) },
{ HP_POP(map->quit, HP_map_quit) },
{ HP_POP(map->addnpc, HP_map_addnpc) },
{ HP_POP(map->clearflooritem_timer, HP_map_clearflooritem_timer) },
@@ -1764,6 +1772,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(path->search_long, HP_path_search_long) },
{ HP_POP(path->check_distance, HP_path_check_distance) },
{ HP_POP(path->distance, HP_path_distance) },
+ { HP_POP(path->check_distance_client, HP_path_check_distance_client) },
+ { HP_POP(path->distance_client, HP_path_distance_client) },
/* pcg */
{ HP_POP(pcg->init, HP_pcg_init) },
{ HP_POP(pcg->final, HP_pcg_final) },
@@ -1884,8 +1894,10 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(pc->setoption, HP_pc_setoption) },
{ HP_POP(pc->setcart, HP_pc_setcart) },
{ HP_POP(pc->setfalcon, HP_pc_setfalcon) },
- { HP_POP(pc->setriding, HP_pc_setriding) },
+ { HP_POP(pc->setridingpeco, HP_pc_setridingpeco) },
{ HP_POP(pc->setmadogear, HP_pc_setmadogear) },
+ { HP_POP(pc->setridingdragon, HP_pc_setridingdragon) },
+ { HP_POP(pc->setridingwug, HP_pc_setridingwug) },
{ HP_POP(pc->changelook, HP_pc_changelook) },
{ HP_POP(pc->equiplookall, HP_pc_equiplookall) },
{ HP_POP(pc->readparam, HP_pc_readparam) },
@@ -2317,7 +2329,6 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(skill->frostjoke_scream, HP_skill_frostjoke_scream) },
{ HP_POP(skill->greed, HP_skill_greed) },
{ HP_POP(skill->destroy_trap, HP_skill_destroy_trap) },
- { HP_POP(skill->icewall_block, HP_skill_icewall_block) },
{ HP_POP(skill->unitgrouptickset_search, HP_skill_unitgrouptickset_search) },
{ HP_POP(skill->dance_switch, HP_skill_dance_switch) },
{ HP_POP(skill->check_condition_char_sub, HP_skill_check_condition_char_sub) },
@@ -2526,6 +2537,8 @@ struct HookingPointData HookingPoints[] = {
{ HP_POP(unit->warp, HP_unit_warp) },
{ HP_POP(unit->stop_walking, HP_unit_stop_walking) },
{ HP_POP(unit->skilluse_id, HP_unit_skilluse_id) },
+ { HP_POP(unit->step_timer, HP_unit_step_timer) },
+ { HP_POP(unit->stop_stepaction, HP_unit_stop_stepaction) },
{ HP_POP(unit->is_walking, HP_unit_is_walking) },
{ HP_POP(unit->can_move, HP_unit_can_move) },
{ HP_POP(unit->resume_running, HP_unit_resume_running) },
diff --git a/src/plugins/HPMHooking/HPMHooking.Hooks.inc b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
index 8f209fe5c..9b518d097 100644
--- a/src/plugins/HPMHooking/HPMHooking.Hooks.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.Hooks.inc
@@ -12937,6 +12937,32 @@ void HP_clif_partyinvitationstate(struct map_session_data *sd) {
}
return;
}
+void HP_clif_PartyLeaderChanged(struct map_session_data *sd, int prev_leader_aid, int new_leader_aid) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_PartyLeaderChanged_pre ) {
+ void (*preHookFunc) (struct map_session_data *sd, int *prev_leader_aid, int *new_leader_aid);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_PartyLeaderChanged_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_PartyLeaderChanged_pre[hIndex].func;
+ preHookFunc(sd, &prev_leader_aid, &new_leader_aid);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.PartyLeaderChanged(sd, prev_leader_aid, new_leader_aid);
+ }
+ if( HPMHooks.count.HP_clif_PartyLeaderChanged_post ) {
+ void (*postHookFunc) (struct map_session_data *sd, int *prev_leader_aid, int *new_leader_aid);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_PartyLeaderChanged_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_PartyLeaderChanged_post[hIndex].func;
+ postHookFunc(sd, &prev_leader_aid, &new_leader_aid);
+ }
+ }
+ return;
+}
void HP_clif_guild_created(struct map_session_data *sd, int flag) {
int hIndex = 0;
if( HPMHooks.count.HP_clif_guild_created_pre ) {
@@ -17135,6 +17161,59 @@ void HP_clif_npc_market_purchase_ack(struct map_session_data *sd, struct packet_
}
return;
}
+bool HP_clif_parse_roulette_db(void) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if( HPMHooks.count.HP_clif_parse_roulette_db_pre ) {
+ bool (*preHookFunc) (void);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_parse_roulette_db_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_parse_roulette_db_pre[hIndex].func;
+ retVal___ = preHookFunc();
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.clif.parse_roulette_db();
+ }
+ if( HPMHooks.count.HP_clif_parse_roulette_db_post ) {
+ bool (*postHookFunc) (bool retVal___);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_parse_roulette_db_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_parse_roulette_db_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___);
+ }
+ }
+ return retVal___;
+}
+void HP_clif_roulette_generate_ack(struct map_session_data *sd, unsigned char result, short stage, short prizeIdx, short bonusItemID) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_roulette_generate_ack_pre ) {
+ void (*preHookFunc) (struct map_session_data *sd, unsigned char *result, short *stage, short *prizeIdx, short *bonusItemID);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_roulette_generate_ack_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_roulette_generate_ack_pre[hIndex].func;
+ preHookFunc(sd, &result, &stage, &prizeIdx, &bonusItemID);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.roulette_generate_ack(sd, result, stage, prizeIdx, bonusItemID);
+ }
+ if( HPMHooks.count.HP_clif_roulette_generate_ack_post ) {
+ void (*postHookFunc) (struct map_session_data *sd, unsigned char *result, short *stage, short *prizeIdx, short *bonusItemID);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_roulette_generate_ack_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_roulette_generate_ack_post[hIndex].func;
+ postHookFunc(sd, &result, &stage, &prizeIdx, &bonusItemID);
+ }
+ }
+ return;
+}
void HP_clif_pWantToConnection(int fd, struct map_session_data *sd) {
int hIndex = 0;
if( HPMHooks.count.HP_clif_pWantToConnection_pre ) {
@@ -22855,6 +22934,136 @@ void HP_clif_pBankClose(int fd, struct map_session_data *sd) {
}
return;
}
+void HP_clif_pRouletteOpen(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_pRouletteOpen_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteOpen_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_pRouletteOpen_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pRouletteOpen(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_pRouletteOpen_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteOpen_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_pRouletteOpen_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_pRouletteInfo(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_pRouletteInfo_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteInfo_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_pRouletteInfo_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pRouletteInfo(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_pRouletteInfo_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteInfo_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_pRouletteInfo_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_pRouletteClose(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_pRouletteClose_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteClose_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_pRouletteClose_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pRouletteClose(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_pRouletteClose_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteClose_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_pRouletteClose_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_pRouletteGenerate(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_pRouletteGenerate_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteGenerate_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_pRouletteGenerate_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pRouletteGenerate(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_pRouletteGenerate_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteGenerate_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_pRouletteGenerate_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
+void HP_clif_pRouletteRecvItem(int fd, struct map_session_data *sd) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_clif_pRouletteRecvItem_pre ) {
+ void (*preHookFunc) (int *fd, struct map_session_data *sd);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteRecvItem_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_clif_pRouletteRecvItem_pre[hIndex].func;
+ preHookFunc(&fd, sd);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.clif.pRouletteRecvItem(fd, sd);
+ }
+ if( HPMHooks.count.HP_clif_pRouletteRecvItem_post ) {
+ void (*postHookFunc) (int *fd, struct map_session_data *sd);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_clif_pRouletteRecvItem_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_clif_pRouletteRecvItem_post[hIndex].func;
+ postHookFunc(&fd, sd);
+ }
+ }
+ return;
+}
void HP_clif_pNPCShopClosed(int fd, struct map_session_data *sd) {
int hIndex = 0;
if( HPMHooks.count.HP_clif_pNPCShopClosed_pre ) {
@@ -26404,14 +26613,14 @@ void HP_guild_castle_reconnect_sub(void *key, void *data, va_list ap) {
return;
}
/* gstorage */
-struct guild_storage* HP_gstorage_id2storage(int guild_id) {
+struct guild_storage* HP_gstorage_ensure(int guild_id) {
int hIndex = 0;
struct guild_storage* retVal___ = NULL;
- if( HPMHooks.count.HP_gstorage_id2storage_pre ) {
+ if( HPMHooks.count.HP_gstorage_ensure_pre ) {
struct guild_storage* (*preHookFunc) (int *guild_id);
*HPMforce_return = false;
- for(hIndex = 0; hIndex < HPMHooks.count.HP_gstorage_id2storage_pre; hIndex++ ) {
- preHookFunc = HPMHooks.list.HP_gstorage_id2storage_pre[hIndex].func;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_gstorage_ensure_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_gstorage_ensure_pre[hIndex].func;
retVal___ = preHookFunc(&guild_id);
}
if( *HPMforce_return ) {
@@ -26420,39 +26629,12 @@ struct guild_storage* HP_gstorage_id2storage(int guild_id) {
}
}
{
- retVal___ = HPMHooks.source.gstorage.id2storage(guild_id);
+ retVal___ = HPMHooks.source.gstorage.ensure(guild_id);
}
- if( HPMHooks.count.HP_gstorage_id2storage_post ) {
+ if( HPMHooks.count.HP_gstorage_ensure_post ) {
struct guild_storage* (*postHookFunc) (struct guild_storage* retVal___, int *guild_id);
- for(hIndex = 0; hIndex < HPMHooks.count.HP_gstorage_id2storage_post; hIndex++ ) {
- postHookFunc = HPMHooks.list.HP_gstorage_id2storage_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, &guild_id);
- }
- }
- return retVal___;
-}
-struct guild_storage* HP_gstorage_id2storage2(int guild_id) {
- int hIndex = 0;
- struct guild_storage* retVal___ = NULL;
- if( HPMHooks.count.HP_gstorage_id2storage2_pre ) {
- struct guild_storage* (*preHookFunc) (int *guild_id);
- *HPMforce_return = false;
- for(hIndex = 0; hIndex < HPMHooks.count.HP_gstorage_id2storage2_pre; hIndex++ ) {
- preHookFunc = HPMHooks.list.HP_gstorage_id2storage2_pre[hIndex].func;
- retVal___ = preHookFunc(&guild_id);
- }
- if( *HPMforce_return ) {
- *HPMforce_return = false;
- return retVal___;
- }
- }
- {
- retVal___ = HPMHooks.source.gstorage.id2storage2(guild_id);
- }
- if( HPMHooks.count.HP_gstorage_id2storage2_post ) {
- struct guild_storage* (*postHookFunc) (struct guild_storage* retVal___, int *guild_id);
- for(hIndex = 0; hIndex < HPMHooks.count.HP_gstorage_id2storage2_post; hIndex++ ) {
- postHookFunc = HPMHooks.list.HP_gstorage_id2storage2_post[hIndex].func;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_gstorage_ensure_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_gstorage_ensure_post[hIndex].func;
retVal___ = postHookFunc(retVal___, &guild_id);
}
}
@@ -35299,15 +35481,15 @@ int HP_map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
}
return retVal___;
}
-int HP_map_count_oncell(int16 m, int16 x, int16 y, int type) {
+int HP_map_count_oncell(int16 m, int16 x, int16 y, int type, int flag) {
int hIndex = 0;
int retVal___ = 0;
if( HPMHooks.count.HP_map_count_oncell_pre ) {
- int (*preHookFunc) (int16 *m, int16 *x, int16 *y, int *type);
+ int (*preHookFunc) (int16 *m, int16 *x, int16 *y, int *type, int *flag);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_map_count_oncell_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_map_count_oncell_pre[hIndex].func;
- retVal___ = preHookFunc(&m, &x, &y, &type);
+ retVal___ = preHookFunc(&m, &x, &y, &type, &flag);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
@@ -35315,13 +35497,13 @@ int HP_map_count_oncell(int16 m, int16 x, int16 y, int type) {
}
}
{
- retVal___ = HPMHooks.source.map.count_oncell(m, x, y, type);
+ retVal___ = HPMHooks.source.map.count_oncell(m, x, y, type, flag);
}
if( HPMHooks.count.HP_map_count_oncell_post ) {
- int (*postHookFunc) (int retVal___, int16 *m, int16 *x, int16 *y, int *type);
+ int (*postHookFunc) (int retVal___, int16 *m, int16 *x, int16 *y, int *type, int *flag);
for(hIndex = 0; hIndex < HPMHooks.count.HP_map_count_oncell_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_map_count_oncell_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, &m, &x, &y, &type);
+ retVal___ = postHookFunc(retVal___, &m, &x, &y, &type, &flag);
}
}
return retVal___;
@@ -35407,6 +35589,33 @@ int HP_map_search_freecell(struct block_list *src, int16 m, int16 *x, int16 *y,
}
return retVal___;
}
+bool HP_map_closest_freecell(int16 m, int16 *x, int16 *y, int type, int flag) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if( HPMHooks.count.HP_map_closest_freecell_pre ) {
+ bool (*preHookFunc) (int16 *m, int16 *x, int16 *y, int *type, int *flag);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_map_closest_freecell_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_map_closest_freecell_pre[hIndex].func;
+ retVal___ = preHookFunc(&m, x, y, &type, &flag);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.map.closest_freecell(m, x, y, type, flag);
+ }
+ if( HPMHooks.count.HP_map_closest_freecell_post ) {
+ bool (*postHookFunc) (bool retVal___, int16 *m, int16 *x, int16 *y, int *type, int *flag);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_map_closest_freecell_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_map_closest_freecell_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, &m, x, y, &type, &flag);
+ }
+ }
+ return retVal___;
+}
int HP_map_quit(struct map_session_data *sd) {
int hIndex = 0;
int retVal___ = 0;
@@ -46375,11 +46584,11 @@ bool HP_path_search_long(struct shootpath_data *spd, int16 m, int16 x0, int16 y0
}
return retVal___;
}
-int HP_path_check_distance(int dx, int dy, int distance) {
+bool HP_path_check_distance(int dx, int dy, int distance) {
int hIndex = 0;
- int retVal___ = 0;
+ bool retVal___ = false;
if( HPMHooks.count.HP_path_check_distance_pre ) {
- int (*preHookFunc) (int *dx, int *dy, int *distance);
+ bool (*preHookFunc) (int *dx, int *dy, int *distance);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_path_check_distance_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_path_check_distance_pre[hIndex].func;
@@ -46394,7 +46603,7 @@ int HP_path_check_distance(int dx, int dy, int distance) {
retVal___ = HPMHooks.source.path.check_distance(dx, dy, distance);
}
if( HPMHooks.count.HP_path_check_distance_post ) {
- int (*postHookFunc) (int retVal___, int *dx, int *dy, int *distance);
+ bool (*postHookFunc) (bool retVal___, int *dx, int *dy, int *distance);
for(hIndex = 0; hIndex < HPMHooks.count.HP_path_check_distance_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_path_check_distance_post[hIndex].func;
retVal___ = postHookFunc(retVal___, &dx, &dy, &distance);
@@ -46429,6 +46638,60 @@ unsigned int HP_path_distance(int dx, int dy) {
}
return retVal___;
}
+bool HP_path_check_distance_client(int dx, int dy, int distance) {
+ int hIndex = 0;
+ bool retVal___ = false;
+ if( HPMHooks.count.HP_path_check_distance_client_pre ) {
+ bool (*preHookFunc) (int *dx, int *dy, int *distance);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_path_check_distance_client_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_path_check_distance_client_pre[hIndex].func;
+ retVal___ = preHookFunc(&dx, &dy, &distance);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.path.check_distance_client(dx, dy, distance);
+ }
+ if( HPMHooks.count.HP_path_check_distance_client_post ) {
+ bool (*postHookFunc) (bool retVal___, int *dx, int *dy, int *distance);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_path_check_distance_client_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_path_check_distance_client_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, &dx, &dy, &distance);
+ }
+ }
+ return retVal___;
+}
+int HP_path_distance_client(int dx, int dy) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if( HPMHooks.count.HP_path_distance_client_pre ) {
+ int (*preHookFunc) (int *dx, int *dy);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_path_distance_client_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_path_distance_client_pre[hIndex].func;
+ retVal___ = preHookFunc(&dx, &dy);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.path.distance_client(dx, dy);
+ }
+ if( HPMHooks.count.HP_path_distance_client_post ) {
+ int (*postHookFunc) (int retVal___, int *dx, int *dy);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_path_distance_client_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_path_distance_client_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, &dx, &dy);
+ }
+ }
+ return retVal___;
+}
/* pcg */
void HP_pcg_init(void) {
int hIndex = 0;
@@ -49580,64 +49843,62 @@ int HP_pc_setcart(struct map_session_data *sd, int type) {
}
return retVal___;
}
-int HP_pc_setfalcon(struct map_session_data *sd, int flag) {
+void HP_pc_setfalcon(struct map_session_data *sd, bool flag) {
int hIndex = 0;
- int retVal___ = 0;
if( HPMHooks.count.HP_pc_setfalcon_pre ) {
- int (*preHookFunc) (struct map_session_data *sd, int *flag);
+ void (*preHookFunc) (struct map_session_data *sd, bool *flag);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setfalcon_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_pc_setfalcon_pre[hIndex].func;
- retVal___ = preHookFunc(sd, &flag);
+ preHookFunc(sd, &flag);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
- return retVal___;
+ return;
}
}
{
- retVal___ = HPMHooks.source.pc.setfalcon(sd, flag);
+ HPMHooks.source.pc.setfalcon(sd, flag);
}
if( HPMHooks.count.HP_pc_setfalcon_post ) {
- int (*postHookFunc) (int retVal___, struct map_session_data *sd, int *flag);
+ void (*postHookFunc) (struct map_session_data *sd, bool *flag);
for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setfalcon_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_pc_setfalcon_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, sd, &flag);
+ postHookFunc(sd, &flag);
}
}
- return retVal___;
+ return;
}
-int HP_pc_setriding(struct map_session_data *sd, int flag) {
+void HP_pc_setridingpeco(struct map_session_data *sd, bool flag) {
int hIndex = 0;
- int retVal___ = 0;
- if( HPMHooks.count.HP_pc_setriding_pre ) {
- int (*preHookFunc) (struct map_session_data *sd, int *flag);
+ if( HPMHooks.count.HP_pc_setridingpeco_pre ) {
+ void (*preHookFunc) (struct map_session_data *sd, bool *flag);
*HPMforce_return = false;
- for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setriding_pre; hIndex++ ) {
- preHookFunc = HPMHooks.list.HP_pc_setriding_pre[hIndex].func;
- retVal___ = preHookFunc(sd, &flag);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setridingpeco_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pc_setridingpeco_pre[hIndex].func;
+ preHookFunc(sd, &flag);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
- return retVal___;
+ return;
}
}
{
- retVal___ = HPMHooks.source.pc.setriding(sd, flag);
+ HPMHooks.source.pc.setridingpeco(sd, flag);
}
- if( HPMHooks.count.HP_pc_setriding_post ) {
- int (*postHookFunc) (int retVal___, struct map_session_data *sd, int *flag);
- for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setriding_post; hIndex++ ) {
- postHookFunc = HPMHooks.list.HP_pc_setriding_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, sd, &flag);
+ if( HPMHooks.count.HP_pc_setridingpeco_post ) {
+ void (*postHookFunc) (struct map_session_data *sd, bool *flag);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setridingpeco_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pc_setridingpeco_post[hIndex].func;
+ postHookFunc(sd, &flag);
}
}
- return retVal___;
+ return;
}
-void HP_pc_setmadogear(struct map_session_data *sd, int flag) {
+void HP_pc_setmadogear(struct map_session_data *sd, bool flag) {
int hIndex = 0;
if( HPMHooks.count.HP_pc_setmadogear_pre ) {
- void (*preHookFunc) (struct map_session_data *sd, int *flag);
+ void (*preHookFunc) (struct map_session_data *sd, bool *flag);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setmadogear_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_pc_setmadogear_pre[hIndex].func;
@@ -49652,7 +49913,7 @@ void HP_pc_setmadogear(struct map_session_data *sd, int flag) {
HPMHooks.source.pc.setmadogear(sd, flag);
}
if( HPMHooks.count.HP_pc_setmadogear_post ) {
- void (*postHookFunc) (struct map_session_data *sd, int *flag);
+ void (*postHookFunc) (struct map_session_data *sd, bool *flag);
for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setmadogear_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_pc_setmadogear_post[hIndex].func;
postHookFunc(sd, &flag);
@@ -49660,6 +49921,58 @@ void HP_pc_setmadogear(struct map_session_data *sd, int flag) {
}
return;
}
+void HP_pc_setridingdragon(struct map_session_data *sd, unsigned int type) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pc_setridingdragon_pre ) {
+ void (*preHookFunc) (struct map_session_data *sd, unsigned int *type);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setridingdragon_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pc_setridingdragon_pre[hIndex].func;
+ preHookFunc(sd, &type);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pc.setridingdragon(sd, type);
+ }
+ if( HPMHooks.count.HP_pc_setridingdragon_post ) {
+ void (*postHookFunc) (struct map_session_data *sd, unsigned int *type);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setridingdragon_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pc_setridingdragon_post[hIndex].func;
+ postHookFunc(sd, &type);
+ }
+ }
+ return;
+}
+void HP_pc_setridingwug(struct map_session_data *sd, bool flag) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_pc_setridingwug_pre ) {
+ void (*preHookFunc) (struct map_session_data *sd, bool *flag);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setridingwug_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_pc_setridingwug_pre[hIndex].func;
+ preHookFunc(sd, &flag);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.pc.setridingwug(sd, flag);
+ }
+ if( HPMHooks.count.HP_pc_setridingwug_post ) {
+ void (*postHookFunc) (struct map_session_data *sd, bool *flag);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_pc_setridingwug_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_pc_setridingwug_post[hIndex].func;
+ postHookFunc(sd, &flag);
+ }
+ }
+ return;
+}
int HP_pc_changelook(struct map_session_data *sd, int type, int val) {
int hIndex = 0;
int retVal___ = 0;
@@ -61331,39 +61644,6 @@ int HP_skill_destroy_trap(struct block_list *bl, va_list ap) {
}
return retVal___;
}
-int HP_skill_icewall_block(struct block_list *bl, va_list ap) {
- int hIndex = 0;
- int retVal___ = 0;
- if( HPMHooks.count.HP_skill_icewall_block_pre ) {
- int (*preHookFunc) (struct block_list *bl, va_list ap);
- *HPMforce_return = false;
- for(hIndex = 0; hIndex < HPMHooks.count.HP_skill_icewall_block_pre; hIndex++ ) {
- va_list ap___copy; va_copy(ap___copy, ap);
- preHookFunc = HPMHooks.list.HP_skill_icewall_block_pre[hIndex].func;
- retVal___ = preHookFunc(bl, ap___copy);
- va_end(ap___copy);
- }
- if( *HPMforce_return ) {
- *HPMforce_return = false;
- return retVal___;
- }
- }
- {
- va_list ap___copy; va_copy(ap___copy, ap);
- retVal___ = HPMHooks.source.skill.icewall_block(bl, ap___copy);
- va_end(ap___copy);
- }
- if( HPMHooks.count.HP_skill_icewall_block_post ) {
- int (*postHookFunc) (int retVal___, struct block_list *bl, va_list ap);
- for(hIndex = 0; hIndex < HPMHooks.count.HP_skill_icewall_block_post; hIndex++ ) {
- va_list ap___copy; va_copy(ap___copy, ap);
- postHookFunc = HPMHooks.list.HP_skill_icewall_block_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, bl, ap___copy);
- va_end(ap___copy);
- }
- }
- return retVal___;
-}
struct skill_unit_group_tickset* HP_skill_unitgrouptickset_search(struct block_list *bl, struct skill_unit_group *group, int64 tick) {
int hIndex = 0;
struct skill_unit_group_tickset* retVal___ = NULL;
@@ -66920,6 +67200,59 @@ int HP_unit_skilluse_id(struct block_list *src, int target_id, uint16 skill_id,
}
return retVal___;
}
+int HP_unit_step_timer(int tid, int64 tick, int id, intptr_t data) {
+ int hIndex = 0;
+ int retVal___ = 0;
+ if( HPMHooks.count.HP_unit_step_timer_pre ) {
+ int (*preHookFunc) (int *tid, int64 *tick, int *id, intptr_t *data);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_unit_step_timer_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_unit_step_timer_pre[hIndex].func;
+ retVal___ = preHookFunc(&tid, &tick, &id, &data);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return retVal___;
+ }
+ }
+ {
+ retVal___ = HPMHooks.source.unit.step_timer(tid, tick, id, data);
+ }
+ if( HPMHooks.count.HP_unit_step_timer_post ) {
+ int (*postHookFunc) (int retVal___, int *tid, int64 *tick, int *id, intptr_t *data);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_unit_step_timer_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_unit_step_timer_post[hIndex].func;
+ retVal___ = postHookFunc(retVal___, &tid, &tick, &id, &data);
+ }
+ }
+ return retVal___;
+}
+void HP_unit_stop_stepaction(struct block_list *bl) {
+ int hIndex = 0;
+ if( HPMHooks.count.HP_unit_stop_stepaction_pre ) {
+ void (*preHookFunc) (struct block_list *bl);
+ *HPMforce_return = false;
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_unit_stop_stepaction_pre; hIndex++ ) {
+ preHookFunc = HPMHooks.list.HP_unit_stop_stepaction_pre[hIndex].func;
+ preHookFunc(bl);
+ }
+ if( *HPMforce_return ) {
+ *HPMforce_return = false;
+ return;
+ }
+ }
+ {
+ HPMHooks.source.unit.stop_stepaction(bl);
+ }
+ if( HPMHooks.count.HP_unit_stop_stepaction_post ) {
+ void (*postHookFunc) (struct block_list *bl);
+ for(hIndex = 0; hIndex < HPMHooks.count.HP_unit_stop_stepaction_post; hIndex++ ) {
+ postHookFunc = HPMHooks.list.HP_unit_stop_stepaction_post[hIndex].func;
+ postHookFunc(bl);
+ }
+ }
+ return;
+}
int HP_unit_is_walking(struct block_list *bl) {
int hIndex = 0;
int retVal___ = 0;
@@ -67136,32 +67469,31 @@ int HP_unit_set_target(struct unit_data *ud, int target_id) {
}
return retVal___;
}
-int HP_unit_stop_attack(struct block_list *bl) {
+void HP_unit_stop_attack(struct block_list *bl) {
int hIndex = 0;
- int retVal___ = 0;
if( HPMHooks.count.HP_unit_stop_attack_pre ) {
- int (*preHookFunc) (struct block_list *bl);
+ void (*preHookFunc) (struct block_list *bl);
*HPMforce_return = false;
for(hIndex = 0; hIndex < HPMHooks.count.HP_unit_stop_attack_pre; hIndex++ ) {
preHookFunc = HPMHooks.list.HP_unit_stop_attack_pre[hIndex].func;
- retVal___ = preHookFunc(bl);
+ preHookFunc(bl);
}
if( *HPMforce_return ) {
*HPMforce_return = false;
- return retVal___;
+ return;
}
}
{
- retVal___ = HPMHooks.source.unit.stop_attack(bl);
+ HPMHooks.source.unit.stop_attack(bl);
}
if( HPMHooks.count.HP_unit_stop_attack_post ) {
- int (*postHookFunc) (int retVal___, struct block_list *bl);
+ void (*postHookFunc) (struct block_list *bl);
for(hIndex = 0; hIndex < HPMHooks.count.HP_unit_stop_attack_post; hIndex++ ) {
postHookFunc = HPMHooks.list.HP_unit_stop_attack_post[hIndex].func;
- retVal___ = postHookFunc(retVal___, bl);
+ postHookFunc(bl);
}
}
- return retVal___;
+ return;
}
int HP_unit_unattackable(struct block_list *bl) {
int hIndex = 0;
diff --git a/src/plugins/HPMHooking/HPMHooking.sources.inc b/src/plugins/HPMHooking/HPMHooking_map.sources.inc
index 53bb6bcad..53bb6bcad 100644
--- a/src/plugins/HPMHooking/HPMHooking.sources.inc
+++ b/src/plugins/HPMHooking/HPMHooking_map.sources.inc
diff --git a/src/plugins/Makefile.in b/src/plugins/Makefile.in
index 77040d567..7f94e6b67 100644
--- a/src/plugins/Makefile.in
+++ b/src/plugins/Makefile.in
@@ -24,10 +24,11 @@ MYPLUGINS =
######### DO NOT EDIT ANYTHING BELOW THIS LINE!!! ##################
# All plugins in the src/plugins directory
-ALLPLUGINS = $(basename $(wildcard *.c))
+HPMHOOKING = $(addprefix HPMHooking_, login char map)
+ALLPLUGINS = $(filter-out HPMHooking, $(basename $(wildcard *.c))) $(HPMHOOKING)
# Plugins that will be built through 'make plugins' or 'make all'
-PLUGINS = sample db2sql HPMHooking $(MYPLUGINS)
+PLUGINS = sample db2sql HPMHooking_map $(MYPLUGINS)
COMMON_D = ../common
COMMON_H = $(wildcard $(COMMON_D)/*.h)
@@ -46,11 +47,14 @@ CC = @CC@
export CC
#####################################################################
-.PHONY: all $(ALLPLUGINS) clean buildclean help
+.PHONY: all $(ALLPLUGINS) HPMHooking clean buildclean help
all: $(PLUGINS) Makefile
$(ALLPLUGINS): %: ../../plugins/%@DLLEXT@
+ @echo " PLUGIN $@"
+
+HPMHooking: $(HPMHOOKING)
buildclean:
@echo " CLEAN plugins (build temp files)"
@@ -80,4 +84,12 @@ Makefile: Makefile.in
../../plugins/%@DLLEXT@: %.c $(ALL_H) $$(shell ls %/* 2>/dev/null)
@echo " CC $<"
- @$(CC) @DEFS@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ @SOFLAGS@ -o $@ $<
+ @$(CC) @PLUGINSTATIC@ @DEFS@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ @SOFLAGS@ -o $@ $<
+
+../../plugins/HPMHooking_login@DLLEXT@: HPMHOOKINGTYPE = LOGIN
+../../plugins/HPMHooking_char@DLLEXT@: HPMHOOKINGTYPE = CHAR
+../../plugins/HPMHooking_map@DLLEXT@: HPMHOOKINGTYPE = MAP
+
+../../plugins/HPMHooking_%@DLLEXT@: HPMHooking.c $(ALL_H) $$(shell ls HPMHooking/*_%* HPMHooking/*_common* 2>/dev/null)
+ @echo " CC $< ($(HPMHOOKINGTYPE))"
+ @$(CC) -DHPMHOOKING_$(HPMHOOKINGTYPE) @PLUGINSTATIC@ @DEFS@ @CFLAGS@ @CPPFLAGS@ @LDFLAGS@ @SOFLAGS@ -o $@ $<
diff --git a/src/plugins/sample.c b/src/plugins/sample.c
index 84df88e06..88ef84d48 100644
--- a/src/plugins/sample.c
+++ b/src/plugins/sample.c
@@ -19,7 +19,7 @@
HPExport struct hplugin_info pinfo = {
"Sample", // Plugin name
- SERVER_TYPE_MAP,// Which server types this plugin works with?
+ SERVER_TYPE_LOGIN|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)
};
diff --git a/src/tool/Makefile.in b/src/tool/Makefile.in
index 127d3841b..2d7699db0 100644
--- a/src/tool/Makefile.in
+++ b/src/tool/Makefile.in
@@ -36,7 +36,7 @@ mapcache: ../../mapcache@EXEEXT@
../../mapcache@EXEEXT@: $(MAPCACHE_DEPENDS) Makefile
@echo " LD $(notdir $@)"
- @$(CC) @LDFLAGS@ -o ../../mapcache@EXEEXT@ $(MAPCACHE_DEPENDS) @LIBS@
+ @$(CC) @STATIC@ @LDFLAGS@ -o ../../mapcache@EXEEXT@ $(MAPCACHE_DEPENDS) @LIBS@
buildclean:
@echo " CLEAN tool (build temp files)"