summaryrefslogtreecommitdiff
path: root/src/map
diff options
context:
space:
mode:
Diffstat (limited to 'src/map')
-rw-r--r--src/map/HPMmap.c56
-rw-r--r--src/map/HPMmap.h2
-rw-r--r--src/map/Makefile.in2
-rw-r--r--src/map/atcommand.c2436
-rw-r--r--src/map/battle.c762
-rw-r--r--src/map/battle.h172
-rw-r--r--src/map/battleground.c124
-rw-r--r--src/map/buyingstore.c15
-rw-r--r--src/map/chat.c32
-rw-r--r--src/map/chat.h23
-rw-r--r--src/map/chrif.c303
-rw-r--r--src/map/chrif.h16
-rw-r--r--src/map/clif.c1001
-rw-r--r--src/map/clif.h129
-rw-r--r--src/map/duel.c2
-rw-r--r--src/map/duel.h4
-rw-r--r--src/map/elemental.c44
-rw-r--r--src/map/elemental.h16
-rw-r--r--src/map/guild.c185
-rw-r--r--src/map/guild.h4
-rw-r--r--src/map/homunculus.c68
-rw-r--r--src/map/homunculus.h13
-rw-r--r--src/map/instance.c12
-rw-r--r--src/map/instance.h8
-rw-r--r--src/map/intif.c157
-rw-r--r--src/map/irc-bot.c34
-rw-r--r--src/map/itemdb.c145
-rw-r--r--src/map/itemdb.h34
-rw-r--r--src/map/log.c7
-rw-r--r--src/map/log.h8
-rw-r--r--src/map/map.c235
-rw-r--r--src/map/map.h145
-rw-r--r--src/map/mercenary.c2
-rw-r--r--src/map/mercenary.h20
-rw-r--r--src/map/mob.c544
-rw-r--r--src/map/mob.h39
-rw-r--r--src/map/npc.c274
-rw-r--r--src/map/npc.h8
-rw-r--r--src/map/packets.h335
-rw-r--r--src/map/packets_struct.h76
-rw-r--r--src/map/party.c44
-rw-r--r--src/map/party.h16
-rw-r--r--src/map/path.c99
-rw-r--r--src/map/path.h12
-rw-r--r--src/map/pc.c899
-rw-r--r--src/map/pc.h205
-rw-r--r--src/map/pc_groups.c4
-rw-r--r--src/map/pc_groups.h4
-rw-r--r--src/map/pet.c74
-rw-r--r--src/map/pet.h13
-rw-r--r--src/map/script.c1293
-rw-r--r--src/map/script.h29
-rw-r--r--src/map/searchstore.c4
-rw-r--r--src/map/skill.c1391
-rw-r--r--src/map/skill.h165
-rw-r--r--src/map/status.c2011
-rw-r--r--src/map/status.h162
-rw-r--r--src/map/storage.c172
-rw-r--r--src/map/storage.h3
-rw-r--r--src/map/trade.c43
-rw-r--r--src/map/unit.c565
-rw-r--r--src/map/unit.h8
-rw-r--r--src/map/vending.c30
63 files changed, 8459 insertions, 6279 deletions
diff --git a/src/map/HPMmap.c b/src/map/HPMmap.c
index cb8c979c6..f1cdec538 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 ) {
@@ -106,6 +101,18 @@ bool HPM_map_grabHPData(struct HPDataOperationStorage *ret, enum HPluginDataType
ret->HPDataSRCPtr = (void**)(&((struct instance_data *)ptr)->hdata);
ret->hdatac = &((struct instance_data *)ptr)->hdatac;
break;
+ case HPDT_MOBDB:
+ ret->HPDataSRCPtr = (void**)(&((struct mob_db *)ptr)->hdata);
+ ret->hdatac = &((struct mob_db *)ptr)->hdatac;
+ break;
+ case HPDT_MOBDATA:
+ ret->HPDataSRCPtr = (void**)(&((struct mob_data *)ptr)->hdata);
+ ret->hdatac = &((struct mob_data *)ptr)->hdatac;
+ break;
+ case HPDT_ITEMDATA:
+ ret->HPDataSRCPtr = (void**)(&((struct item_data *)ptr)->hdata);
+ ret->hdatac = &((struct item_data *)ptr)->hdatac;
+ break;
default:
return false;
}
@@ -147,29 +154,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 +167,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 +187,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 b5e8fa797..330fe6284 100644
--- a/src/map/atcommand.c
+++ b/src/map/atcommand.c
@@ -162,15 +162,15 @@ ACMD(send)
{
int len=0,off,end,type;
long num;
-
+
// read message type as hex number (without the 0x)
if(!message || !*message ||
!((sscanf(message, "len %x", &type)==1 && (len=1))
|| sscanf(message, "%x", &type)==1) ) {
clif->message(fd, msg_txt(900)); // Usage:
- clif->message(fd, msg_txt(901)); // @send len <packet hex number>
- clif->message(fd, msg_txt(902)); // @send <packet hex number> {<value>}*
- clif->message(fd, msg_txt(903)); // Value: <type=B(default),W,L><number> or S<length>"<string>"
+ clif->message(fd, msg_txt(901)); // @send len <packet hex number>
+ clif->message(fd, msg_txt(902)); // @send <packet hex number> {<value>}*
+ clif->message(fd, msg_txt(903)); // Value: <type=B(default),W,L><number> or S<length>"<string>"
return false;
}
@@ -200,14 +200,13 @@ ACMD(send)
} while(0) //define GET_VALUE
if (type > 0 && type < MAX_PACKET_DB) {
-
if(len)
{// show packet length
sprintf(atcmd_output, msg_txt(904), type, packet_db[type].len); // Packet 0x%x length: %d
clif->message(fd, atcmd_output);
return true;
}
-
+
len=packet_db[type].len;
off=2;
if(len == 0)
@@ -222,7 +221,7 @@ ACMD(send)
}
WFIFOHEAD(sd->fd, len);
WFIFOW(sd->fd,0)=TOW(type);
-
+
// parse packet contents
SKIP_VALUE(message);
while(*message != 0 && off < len){
@@ -266,7 +265,7 @@ ACMD(send)
++message;
}
}
-
+
// parse string
++message;
CHECK_EOS(message);
@@ -344,7 +343,7 @@ ACMD(send)
++message;
CHECK_EOS(message);
}
-
+
// terminate the string
if(off < end)
{// fill the rest with 0's
@@ -358,7 +357,7 @@ ACMD(send)
}
SKIP_VALUE(message);
}
-
+
if(packet_db[type].len == -1) {// send dynamic packet
WFIFOW(sd->fd,2)=TOW(off);
WFIFOSET(sd->fd,off);
@@ -388,21 +387,20 @@ ACMD(mapmove) {
unsigned short map_index;
short x = 0, y = 0;
int16 m = -1;
-
+
memset(map_name, '\0', sizeof(map_name));
-
+
if (!message || !*message ||
(sscanf(message, "%15s %hd %hd", map_name, &x, &y) < 3 &&
sscanf(message, "%15[^,],%hd,%hd", map_name, &x, &y) < 1)) {
-
clif->message(fd, msg_txt(909)); // Please enter a map (usage: @warp/@rura/@mapmove <mapname> <x> <y>).
return false;
}
-
+
map_index = mapindex->name2id(map_name);
if (map_index)
m = map->mapindex2mapid(map_index);
-
+
if (!map_index || m < 0) { // m < 0 means on different server or that map is disabled! [Kevin]
clif->message(fd, msg_txt(1)); // Map not found.
return false;
@@ -412,7 +410,7 @@ ACMD(mapmove) {
clif->message(fd, msg_txt(253)); // You already are at your destination!
return false;
}
-
+
if ((x || y) && map->getcell(m, x, y, CELL_CHKNOPASS) && pc_get_group_level(sd) < battle_config.gm_ignore_warpable_area) {
//This is to prevent the pc->setpos call from printing an error.
clif->message(fd, msg_txt(2));
@@ -431,7 +429,7 @@ ACMD(mapmove) {
clif->message(fd, msg_txt(1)); // Map not found.
return false;
}
-
+
clif->message(fd, msg_txt(0)); // Warped.
return true;
}
@@ -441,14 +439,14 @@ ACMD(mapmove) {
*------------------------------------------*/
ACMD(where) {
struct map_session_data* pl_sd;
-
+
memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif->message(fd, msg_txt(910)); // Please enter a player name (usage: @where <char name>).
return false;
}
-
+
pl_sd = map->nick2sd(atcmd_player_name);
if (pl_sd == NULL ||
strncmp(pl_sd->status.name, atcmd_player_name, NAME_LENGTH) != 0 ||
@@ -457,10 +455,10 @@ ACMD(where) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
snprintf(atcmd_output, sizeof atcmd_output, "%s %s %d %d", pl_sd->status.name, mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y);
clif->message(fd, atcmd_output);
-
+
return true;
}
@@ -489,7 +487,7 @@ ACMD(jumpto) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if (pl_sd->bl.m >= 0 && map->list[pl_sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(247)); // You are not authorized to warp to this map.
return false;
@@ -513,21 +511,21 @@ ACMD(jumpto) {
ACMD(jump)
{
short x = 0, y = 0;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
sscanf(message, "%hd %hd", &x, &y);
-
+
if (map->list[sd->bl.m].flag.noteleport && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
return false;
}
-
+
if( pc_isdead(sd) ) {
clif->message(fd, msg_txt(864)); // "You cannot use this command when dead."
return false;
}
-
+
if ((x || y) && map->getcell(sd->bl.m, x, y, CELL_CHKNOPASS)) {
//This is to prevent the pc->setpos call from printing an error.
clif->message(fd, msg_txt(2));
@@ -539,7 +537,7 @@ ACMD(jump)
clif->message(fd, msg_txt(253)); // You already are at your destination!
return false;
}
-
+
pc->setpos(sd, sd->mapindex, x, y, CLR_TELEPORT);
sprintf(atcmd_output, msg_txt(5), sd->bl.x, sd->bl.y); // Jumped to %d %d
clif->message(fd, atcmd_output);
@@ -565,25 +563,25 @@ ACMD(who) {
*/
int display_type = 1;
int map_id = -1;
-
+
if (stristr(info->command, "map") != NULL) {
if (sscanf(message, "%15s %23s", map_name, player_name) < 1 || (map_id = map->mapname2mapid(map_name)) < 0)
map_id = sd->bl.m;
} else {
sscanf(message, "%23s", player_name);
}
-
+
if (stristr(info->command, "2") != NULL)
display_type = 2;
else if (stristr(info->command, "3") != NULL)
display_type = 3;
-
+
level = pc_get_group_level(sd);
StrBuf->Init(&buf);
-
+
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
+ for (pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter)) {
+ if (!((pc_has_permission(pl_sd, PC_PERM_HIDE_SESSION) || pc_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;
@@ -598,7 +596,7 @@ ACMD(who) {
}
case 3: {
if (pc_has_permission(sd, PC_PERM_WHO_DISPLAY_AID))
- StrBuf->Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) "
+ StrBuf->Printf(&buf, msg_txt(912), pl_sd->status.char_id, pl_sd->status.account_id); // "(CID:%d/AID:%d) "
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
@@ -608,7 +606,7 @@ ACMD(who) {
default: {
struct party_data *p = party->search(pl_sd->status.party_id);
struct guild *g = pl_sd->guild;
-
+
StrBuf->Printf(&buf, msg_txt(343), pl_sd->status.name); // "Name: %s "
if (pc_get_group_id(pl_sd) > 0) // Player title, if exists
StrBuf->Printf(&buf, msg_txt(344), pcg->get_name(pl_sd->group)); // "(%s) "
@@ -619,13 +617,13 @@ ACMD(who) {
break;
}
}
- clif->message(fd, StrBuf->Value(&buf));
+ clif->colormes(fd, COLOR_DEFAULT, StrBuf->Value(&buf));/** for whatever reason clif->message crashes with some patterns, see bugreport:8186 **/
StrBuf->Clear(&buf);
count++;
}
}
mapit->free(iter);
-
+
if (map_id < 0) {
if (count == 0)
StrBuf->Printf(&buf, msg_txt(28)); // No player found.
@@ -659,65 +657,65 @@ ACMD(whogm)
char player_name[NAME_LENGTH];
struct guild *g;
struct party_data *p;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(match_text, '\0', sizeof(match_text));
memset(player_name, '\0', sizeof(player_name));
-
+
if (sscanf(message, "%199[^\n]", match_text) < 1)
strcpy(match_text, "");
for (j = 0; match_text[j]; j++)
match_text[j] = TOLOWER(match_text[j]);
-
+
count = 0;
level = pc_get_group_level(sd);
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
pl_level = pc_get_group_level(pl_sd);
if (!pl_level)
continue;
-
+
if (match_text[0])
{
memcpy(player_name, pl_sd->status.name, NAME_LENGTH);
for (j = 0; player_name[j]; j++)
player_name[j] = TOLOWER(player_name[j]);
- // search with no case sensitive
+ // search with no case sensitive
if (strstr(player_name, match_text) == NULL)
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);
count++;
continue;
}
-
+
sprintf(atcmd_output, msg_txt(914), // Name: %s (GM:%d) | Location: %s %d %d
pl_sd->status.name, pl_level,
mapindex_id2name(pl_sd->mapindex), pl_sd->bl.x, pl_sd->bl.y);
clif->message(fd, atcmd_output);
-
+
sprintf(atcmd_output, msg_txt(915), // BLvl: %d | Job: %s (Lvl: %d)
pl_sd->status.base_level,
pc->job_name(pl_sd->status.class_), pl_sd->status.job_level);
clif->message(fd, atcmd_output);
-
+
p = party->search(pl_sd->status.party_id);
g = pl_sd->guild;
-
- sprintf(atcmd_output,msg_txt(916), // Party: '%s' | Guild: '%s'
- p?p->party.name:msg_txt(917), g?g->name:msg_txt(917)); // None.
-
+
+ sprintf(atcmd_output,msg_txt(916), // Party: '%s' | Guild: '%s'
+ p?p->party.name:msg_txt(917), g?g->name:msg_txt(917)); // None.
+
clif->message(fd, atcmd_output);
count++;
}
mapit->free(iter);
-
+
if (count == 0)
clif->message(fd, msg_txt(150)); // No GM found.
else if (count == 1)
@@ -726,23 +724,23 @@ ACMD(whogm)
sprintf(atcmd_output, msg_txt(152), count); // %d GMs found.
clif->message(fd, atcmd_output);
}
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-ACMD(save) {
-
+ACMD(save)
+{
pc->setsavepoint(sd, sd->mapindex, sd->bl.x, sd->bl.y);
if (sd->status.pet_id > 0 && sd->pd)
intif->save_petdata(sd->status.account_id, &sd->pd->pet);
-
+
chrif->save(sd,0);
-
+
clif->message(fd, msg_txt(6)); // Your save point has been changed.
-
+
return true;
}
@@ -751,7 +749,7 @@ ACMD(save) {
*------------------------------------------*/
ACMD(load) {
int16 m;
-
+
m = map->mapindex2mapid(sd->status.save_point.map);
if (m >= 0 && map->list[m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(249)); // You are not authorized to warp to your save map.
@@ -761,10 +759,10 @@ ACMD(load) {
clif->message(fd, msg_txt(248)); // You are not authorized to warp from your current map.
return false;
}
-
+
pc->setpos(sd, sd->status.save_point.map, sd->status.save_point.x, sd->status.save_point.y, CLR_OUTSIGHT);
clif->message(fd, msg_txt(7)); // Warping to save point..
-
+
return true;
}
@@ -774,30 +772,30 @@ ACMD(load) {
ACMD(speed)
{
int speed;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%d", &speed) < 1) {
sprintf(atcmd_output, msg_txt(918), MIN_WALK_SPEED, MAX_WALK_SPEED); // Please enter a speed value (usage: @speed <%d-%d>).
clif->message(fd, atcmd_output);
return false;
}
-
+
sd->state.permanent_speed = 0;
-
+
if (speed < 0)
sd->base_status.speed = DEFAULT_WALK_SPEED;
else
sd->base_status.speed = cap_value(speed, MIN_WALK_SPEED, MAX_WALK_SPEED);
-
+
if( sd->base_status.speed != DEFAULT_WALK_SPEED ) {
sd->state.permanent_speed = 1; // Set lock when set to non-default speed.
clif->message(fd, msg_txt(8)); // Speed changed.
} else
clif->message(fd, msg_txt(172)); //Speed returned to normal.
-
+
status_calc_bl(&sd->bl, SCB_SPEED);
-
+
return true;
}
@@ -808,14 +806,14 @@ ACMD(storage)
{
if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading || sd->state.storage_flag)
return false;
-
+
if (storage->open(sd) == 1) { //Already open.
clif->message(fd, msg_txt(250));
return false;
}
-
+
clif->message(fd, msg_txt(919)); // Storage opened.
-
+
return true;
}
@@ -829,20 +827,20 @@ ACMD(guildstorage)
clif->message(fd, msg_txt(252));
return false;
}
-
+
if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.trading)
return false;
-
+
if (sd->state.storage_flag == 1) {
clif->message(fd, msg_txt(250));
return false;
}
-
+
if (sd->state.storage_flag == 2) {
clif->message(fd, msg_txt(251));
return false;
}
-
+
if( gstorage->open(sd) ) {
clif->message(fd, msg_txt(1201)); // Your guild's storage has already been opened by another member, try again later.
return false;
@@ -858,30 +856,30 @@ ACMD(guildstorage)
ACMD(option)
{
int param1 = 0, param2 = 0, param3 = 0;
-
+
if (!message || !*message || sscanf(message, "%d %d %d", &param1, &param2, &param3) < 1 || param1 < 0 || param2 < 0 || param3 < 0)
{// failed to match the parameters so inform the user of the options
const char* text;
-
+
// attempt to find the setting information for this command
text = atcommand_help_string( info );
-
+
// notify the user of the requirement to enter an option
clif->message(fd, msg_txt(921)); // Please enter at least one option.
-
+
if( text ) {// send the help text associated with this command
clif->messageln( fd, text );
}
-
+
return false;
}
-
+
sd->sc.opt1 = param1;
sd->sc.opt2 = param2;
pc->setoption(sd, param3);
-
+
clif->message(fd, msg_txt(9)); // Options changed.
-
+
return true;
}
@@ -889,17 +887,17 @@ 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);
else
status->set_viewdata(&sd->bl, sd->status.class_);
clif->message(fd, msg_txt(10)); // Invisible: Off
-
+
// increment the number of pvp players on the map
map->list[sd->bl.m].users_pvp++;
-
+
if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank ) {
// register the player for ranking calculations
sd->pvp_timer = timer->add( timer->gettick() + 200, pc->calc_pvprank_timer, sd->bl.id, 0 );
@@ -910,10 +908,10 @@ ACMD(hide) {
sd->sc.option |= OPTION_INVISIBLE;
sd->vd.class_ = INVISIBLE_CLASS;
clif->message(fd, msg_txt(11)); // Invisible: On
-
+
// decrement the number of pvp players on the map
map->list[sd->bl.m].users_pvp--;
-
+
if( map->list[sd->bl.m].flag.pvp && !map->list[sd->bl.m].flag.pvp_nocalcrank && sd->pvp_timer != INVALID_TIMER ) {
// unregister the player for ranking
timer->delete( sd->pvp_timer, pc->calc_pvprank_timer );
@@ -921,7 +919,7 @@ ACMD(hide) {
}
}
clif->changeoption(&sd->bl);
-
+
return true;
}
@@ -931,11 +929,11 @@ ACMD(hide) {
ACMD(jobchange) {
int job = 0, upper = 0;
const char* text;
-
+
if (!message || !*message || sscanf(message, "%d %d", &job, &upper) < 1) {
upper = 0;
-
- if( message ) {
+
+ if( message ) {
int i;
bool found = false;
@@ -946,7 +944,7 @@ ACMD(jobchange) {
found = true;
}
}
-
+
// High Jobs, Babies and Third
for( i = JOB_NOVICE_HIGH; i < JOB_MAX && !found; i++ ){
if (strncmpi(message, pc->job_name(i), 16) == 0) {
@@ -954,7 +952,7 @@ ACMD(jobchange) {
found = true;
}
}
-
+
if (!found) {
text = atcommand_help_string(info);
if (text)
@@ -965,14 +963,14 @@ ACMD(jobchange) {
}
/* WHY DO WE LIST THEM THEN? */
// Deny direct transformation into dummy jobs
- if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2 || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER
- || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2 || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2 || job == JOB_STAR_GLADIATOR2
- || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2)
- ) {
+ if (job == JOB_KNIGHT2 || job == JOB_CRUSADER2 || job == JOB_WEDDING || job == JOB_XMAS || job == JOB_SUMMER
+ || job == JOB_LORD_KNIGHT2 || job == JOB_PALADIN2 || job == JOB_BABY_KNIGHT2 || job == JOB_BABY_CRUSADER2 || job == JOB_STAR_GLADIATOR2
+ || (job >= JOB_RUNE_KNIGHT2 && job <= JOB_MECHANIC_T2) || (job >= JOB_BABY_RUNE2 && job <= JOB_BABY_MECHANIC2)
+ ) {
clif->message(fd, msg_txt(923)); //"You can not change to this job by command."
return true;
}
-
+
if (pcdb_checkid(job)) {
if (pc->jobchange(sd, job, upper) == 0)
clif->message(fd, msg_txt(12)); // Your job has been changed.
@@ -982,11 +980,11 @@ ACMD(jobchange) {
}
} else {
text = atcommand_help_string(info);
- if (text)
- clif->messageln(fd, text);
+ if (text)
+ clif->messageln(fd, text);
return false;
}
-
+
return true;
}
@@ -1022,15 +1020,15 @@ ACMD(alive)
ACMD(kami)
{
unsigned int color=0;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if(*(info->command + 4) != 'c' && *(info->command + 4) != 'C') {
if (!message || !*message) {
clif->message(fd, msg_txt(980)); // Please enter a message (usage: @kami <message>).
return false;
}
-
+
sscanf(message, "%199[^\n]", atcmd_output);
if (stristr(info->command, "l") != NULL)
clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
@@ -1041,7 +1039,7 @@ ACMD(kami)
clif->message(fd, msg_txt(981)); // Please enter color and message (usage: @kamic <color> <message>).
return false;
}
-
+
if(color > 0xFFFFFF) {
clif->message(fd, msg_txt(982)); // Invalid color.
return false;
@@ -1057,13 +1055,13 @@ ACMD(kami)
ACMD(heal)
{
int hp = 0, sp = 0; // [Valaris] thanks to fov
-
+
sscanf(message, "%d %d", &hp, &sp);
-
+
// some overflow checks
if( hp == INT_MIN ) hp++;
if( sp == INT_MIN ) sp++;
-
+
if ( hp == 0 && sp == 0 ) {
if (!status_percent_heal(&sd->bl, 100, 100))
clif->message(fd, msg_txt(157)); // HP and SP have already been recovered.
@@ -1071,7 +1069,7 @@ ACMD(heal)
clif->message(fd, msg_txt(17)); // HP, SP recovered.
return true;
}
-
+
if ( hp > 0 && sp >= 0 ) {
if(!status->heal(&sd->bl, hp, sp, 0))
clif->message(fd, msg_txt(157)); // HP and SP are already with the good value.
@@ -1079,14 +1077,14 @@ ACMD(heal)
clif->message(fd, msg_txt(17)); // HP, SP recovered.
return true;
}
-
+
if ( hp < 0 && sp <= 0 ) {
status->damage(NULL, &sd->bl, -hp, -sp, 0, 0);
clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0);
clif->message(fd, msg_txt(156)); // HP or/and SP modified.
return true;
}
-
+
//Opposing signs.
if ( hp ) {
if (hp > 0)
@@ -1096,14 +1094,14 @@ ACMD(heal)
clif->damage(&sd->bl,&sd->bl, 0, 0, -hp, 0, 4, 0);
}
}
-
+
if ( sp ) {
if (sp > 0)
status->heal(&sd->bl, 0, sp, 0);
else
status->damage(NULL, &sd->bl, 0, -sp, 0, 0);
}
-
+
clif->message(fd, msg_txt(156)); // HP or/and SP modified.
return true;
}
@@ -1119,7 +1117,7 @@ ACMD(item)
struct item item_tmp;
struct item_data *item_data;
int get_count, i;
-
+
memset(item_name, '\0', sizeof(item_name));
if (!strcmpi(info->command,"itembound") && (!message || !*message || (
@@ -1128,24 +1126,24 @@ ACMD(item)
))) {
clif->message(fd, msg_txt(295)); // Please enter an item name or ID (usage: @itembound <item name/ID> <quantity> <bound_type>).
return false;
- } else if (!message || !*message || (
- sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1 &&
- sscanf(message, "%99s %d", item_name, &number) < 1 ))
- {
- clif->message(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>).
+ } else if (!message || !*message
+ || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &number) < 1
+ && sscanf(message, "%99s %d", item_name, &number) < 1
+ )) {
+ clif->message(fd, msg_txt(983)); // Please enter an item name or ID (usage: @item <item name/ID> <quantity>).
return false;
}
-
+
if (number <= 0)
number = 1;
-
+
if ((item_data = itemdb->search_name(item_name)) == NULL &&
(item_data = itemdb->exists(atoi(item_name))) == NULL)
{
clif->message(fd, msg_txt(19)); // Invalid item ID or name.
return false;
}
-
+
if(!strcmpi(info->command,"itembound") ) {
if( !(bound >= IBT_MIN && bound <= IBT_MAX) ) {
clif->message(fd, msg_txt(298)); // Invalid bound type
@@ -1178,9 +1176,9 @@ ACMD(item)
clif->message(fd, msg_txt(498)); // Cannot create bounded pet eggs or pet armors.
return false;
}
- get_count = 1;
+ get_count = 1;
}
-
+
for (i = 0; i < number; i += get_count) {
// if not pet egg
if (!pet->create_egg(sd, item_id)) {
@@ -1188,12 +1186,12 @@ ACMD(item)
item_tmp.nameid = item_id;
item_tmp.identify = 1;
item_tmp.bound = (unsigned char)bound;
-
+
if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
clif->additem(sd, 0, 0, flag);
}
}
-
+
if (flag == 0)
clif->message(fd, msg_txt(18)); // Item created.
return true;
@@ -1210,24 +1208,24 @@ ACMD(item2)
int item_id, number = 0, bound = 0;
int identify = 0, refine = 0, attr = 0;
int c1 = 0, c2 = 0, c3 = 0, c4 = 0;
-
+
memset(item_name, '\0', sizeof(item_name));
-
+
if (!strcmpi(info->command,"itembound2") && (!message || !*message || (
sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 &&
sscanf(message, "%99s %d %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4, &bound) < 10 ))) {
clif->message(fd, msg_txt(296)); // Please enter all parameters (usage: @itembound2 <item name/ID> <quantity>
clif->message(fd, msg_txt(297)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4> <bound_type>).
return false;
- } else if ( !message || !*message || (
- sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9 &&
- sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
- )) {
+ } else if ( !message || !*message
+ || ( sscanf(message, "\"%99[^\"]\" %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
+ && sscanf(message, "%99s %d %d %d %d %d %d %d %d", item_name, &number, &identify, &refine, &attr, &c1, &c2, &c3, &c4) < 9
+ )) {
clif->message(fd, msg_txt(984)); // Please enter all parameters (usage: @item2 <item name/ID> <quantity>
clif->message(fd, msg_txt(985)); // <identify_flag> <refine> <attribute> <card1> <card2> <card3> <card4>).
return false;
}
-
+
if (number <= 0)
number = 1;
@@ -1240,7 +1238,7 @@ ACMD(item2)
if ((item_data = itemdb->search_name(item_name)) != NULL ||
(item_data = itemdb->exists(atoi(item_name))) != NULL)
item_id = item_data->nameid;
-
+
if (item_id > 500) {
int flag = 0;
int loop, get_count, i;
@@ -1253,7 +1251,7 @@ ACMD(item2)
clif->message(fd, msg_txt(498)); // Cannot create bounded pet eggs or pet armors.
return false;
}
- loop = number;
+ loop = number;
get_count = 1;
if (item_data->type == IT_PETEGG) {
identify = 1;
@@ -1278,18 +1276,18 @@ ACMD(item2)
item_tmp.card[1] = c2;
item_tmp.card[2] = c3;
item_tmp.card[3] = c4;
-
+
if ((flag = pc->additem(sd, &item_tmp, get_count, LOG_TYPE_COMMAND)))
clif->additem(sd, 0, 0, flag);
}
-
+
if (flag == 0)
clif->message(fd, msg_txt(18)); // Item created.
} else {
clif->message(fd, msg_txt(19)); // Invalid item ID or name.
return false;
}
-
+
return true;
}
@@ -1299,14 +1297,14 @@ ACMD(item2)
ACMD(itemreset)
{
int i;
-
+
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].amount && sd->status.inventory[i].equip == 0) {
pc->delitem(sd, i, sd->status.inventory[i].amount, 0, 0, LOG_TYPE_COMMAND);
}
}
clif->message(fd, msg_txt(20)); // All of your items have been removed.
-
+
return true;
}
@@ -1318,12 +1316,12 @@ ACMD(baselevelup)
int level=0, i=0, status_point=0;
level = atoi(message);
-
+
if (!message || !*message || !level) {
clif->message(fd, msg_txt(986)); // Please enter a level adjustment (usage: @lvup/@blevel/@baselvlup <number of levels>).
return false;
}
-
+
if (level > 0) {
if (sd->status.base_level >= pc->maxbaselv(sd)) { // check for max level by Valaris
clif->message(fd, msg_txt(47)); // Base level can't go any higher.
@@ -1333,7 +1331,7 @@ ACMD(baselevelup)
level = pc->maxbaselv(sd) - sd->status.base_level;
for (i = 0; i < level; i++)
status_point += pc->gets_status_point(sd->status.base_level + i);
-
+
sd->status.status_point += status_point;
sd->status.base_level += (unsigned int)level;
status_calc_pc(sd, SCO_FORCE);
@@ -1377,9 +1375,9 @@ ACMD(baselevelup)
ACMD(joblevelup)
{
int level=0;
-
+
level = atoi(message);
-
+
if (!message || !*message || !level) {
clif->message(fd, msg_txt(987)); // Please enter a level adjustment (usage: @joblvup/@jlevel/@joblvlup <number of levels>).
return false;
@@ -1405,7 +1403,7 @@ ACMD(joblevelup)
level = sd->status.job_level-1;
sd->status.job_level -= (unsigned int)level;
if (sd->status.skill_point < level)
- pc->resetskill(sd,0); //Reset skills since we need to subtract more points.
+ pc->resetskill(sd,0); //Reset skills since we need to subtract more points.
if (sd->status.skill_point < level)
sd->status.skill_point = 0;
else
@@ -1418,7 +1416,7 @@ ACMD(joblevelup)
clif->updatestatus(sd, SP_NEXTJOBEXP);
clif->updatestatus(sd, SP_SKILLPOINT);
status_calc_pc(sd, SCO_FORCE);
-
+
return true;
}
@@ -1429,7 +1427,7 @@ ACMD(help) {
const char *command_name = NULL;
char *default_command = "help";
AtCommandInfo *tinfo = NULL;
-
+
if (!message || !*message) {
command_name = default_command; // If no command_name specified, display help for @help.
} else {
@@ -1437,33 +1435,33 @@ ACMD(help) {
++message;
command_name = atcommand->check_alias(message);
}
-
+
if (!atcommand->can_use2(sd, command_name, COMMAND_ATCOMMAND)) {
sprintf(atcmd_output, msg_txt(153), message); // "%s is Unknown Command"
clif->message(fd, atcmd_output);
atcommand->get_suggestions(sd, command_name, true);
return false;
}
-
+
tinfo = atcommand->get_info_byname(atcommand->check_alias(command_name));
-
+
if ( !tinfo || tinfo->help == NULL ) {
sprintf(atcmd_output, msg_txt(988), atcommand->at_symbol, command_name); // There is no help for %c%s.
clif->message(fd, atcmd_output);
atcommand->get_suggestions(sd, command_name, true);
return false;
}
-
+
sprintf(atcmd_output, msg_txt(989), atcommand->at_symbol, command_name); // Help for command %c%s:
clif->message(fd, atcmd_output);
-
+
{ // Display aliases
DBIterator* iter;
AtCommandInfo *command_info;
AliasInfo *alias_info = NULL;
StringBuf buf;
bool has_aliases = false;
-
+
StrBuf->Init(&buf);
StrBuf->AppendStr(&buf, msg_txt(990)); // Available aliases:
command_info = atcommand->get_info_byname(command_name);
@@ -1479,7 +1477,7 @@ ACMD(help) {
clif->message(fd, StrBuf->Value(&buf));
StrBuf->Destroy(&buf);
}
-
+
// Display help contents
clif->message(fd, tinfo->help);
return true;
@@ -1512,16 +1510,16 @@ int atcommand_pvpoff_sub(struct block_list *bl,va_list ap)
return 0;
}
-ACMD(pvpoff) {
-
+ACMD(pvpoff)
+{
if (!map->list[sd->bl.m].flag.pvp) {
clif->message(fd, msg_txt(160)); // PvP is already Off.
return false;
}
-
+
map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
map->list[sd->bl.m].flag.pvp = 0;
-
+
if (!battle_config.pk_mode) {
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
@@ -1549,24 +1547,24 @@ int atcommand_pvpon_sub(struct block_list *bl,va_list ap)
return 0;
}
-ACMD(pvpon) {
-
+ACMD(pvpon)
+{
if (map->list[sd->bl.m].flag.pvp) {
clif->message(fd, msg_txt(161)); // PvP is already On.
return false;
}
-
+
map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_PVP_NAME));
map->list[sd->bl.m].flag.pvp = 1;
-
+
if (!battle_config.pk_mode) {// display pvp circle and rank
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_FREEPVPZONE);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
map->foreachinmap(atcommand->pvpon_sub,sd->bl.m, BL_PC);
}
-
+
clif->message(fd, msg_txt(32)); // PvP: On.
-
+
return true;
}
@@ -1574,38 +1572,38 @@ ACMD(pvpon) {
*
*------------------------------------------*/
ACMD(gvgoff) {
-
+
if (!map->list[sd->bl.m].flag.gvg) {
clif->message(fd, msg_txt(162)); // GvG is already Off.
return false;
}
-
+
map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
map->list[sd->bl.m].flag.gvg = 0;
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_NOTHING);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
map->foreachinmap(atcommand->stopattack,sd->bl.m, BL_CHAR, 0);
clif->message(fd, msg_txt(33)); // GvG: Off.
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-ACMD(gvgon) {
-
+ACMD(gvgon)
+{
if (map->list[sd->bl.m].flag.gvg) {
clif->message(fd, msg_txt(163)); // GvG is already On.
return false;
}
-
+
map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_GVG_NAME));
map->list[sd->bl.m].flag.gvg = 1;
clif->map_property_mapall(sd->bl.m, MAPPROPERTY_AGITZONE);
clif->maptypeproperty2(&sd->bl,ALL_SAMEMAP);
clif->message(fd, msg_txt(34)); // GvG: On.
-
+
return true;
}
@@ -1615,16 +1613,16 @@ ACMD(gvgon) {
ACMD(model)
{
int hair_style = 0, hair_color = 0, cloth_color = 0;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%d %d %d", &hair_style, &hair_color, &cloth_color) < 1) {
sprintf(atcmd_output, msg_txt(991), // Please enter at least one value (usage: @model <hair ID: %d-%d> <hair color: %d-%d> <clothes color: %d-%d>).
MIN_HAIR_STYLE, MAX_HAIR_STYLE, MIN_HAIR_COLOR, MAX_HAIR_COLOR, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
clif->message(fd, atcmd_output);
return false;
}
-
+
if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE &&
hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR &&
cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
@@ -1636,7 +1634,7 @@ ACMD(model)
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
}
-
+
return true;
}
@@ -1646,15 +1644,15 @@ ACMD(model)
ACMD(dye)
{
int cloth_color = 0;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%d", &cloth_color) < 1) {
sprintf(atcmd_output, msg_txt(992), MIN_CLOTH_COLOR, MAX_CLOTH_COLOR); // Please enter a clothes color (usage: @dye/@ccolor <clothes color: %d-%d>).
clif->message(fd, atcmd_output);
return false;
}
-
+
if (cloth_color >= MIN_CLOTH_COLOR && cloth_color <= MAX_CLOTH_COLOR) {
pc->changelook(sd, LOOK_CLOTHES_COLOR, cloth_color);
clif->message(fd, msg_txt(36)); // Appearance changed.
@@ -1662,7 +1660,7 @@ ACMD(dye)
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
}
-
+
return true;
}
@@ -1672,15 +1670,15 @@ ACMD(dye)
ACMD(hair_style)
{
int hair_style = 0;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%d", &hair_style) < 1) {
sprintf(atcmd_output, msg_txt(993), MIN_HAIR_STYLE, MAX_HAIR_STYLE); // Please enter a hair style (usage: @hairstyle/@hstyle <hair ID: %d-%d>).
clif->message(fd, atcmd_output);
return false;
}
-
+
if (hair_style >= MIN_HAIR_STYLE && hair_style <= MAX_HAIR_STYLE) {
pc->changelook(sd, LOOK_HAIR, hair_style);
clif->message(fd, msg_txt(36)); // Appearance changed.
@@ -1688,7 +1686,7 @@ ACMD(hair_style)
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
}
-
+
return true;
}
@@ -1698,15 +1696,15 @@ ACMD(hair_style)
ACMD(hair_color)
{
int hair_color = 0;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%d", &hair_color) < 1) {
sprintf(atcmd_output, msg_txt(994), MIN_HAIR_COLOR, MAX_HAIR_COLOR); // Please enter a hair color (usage: @haircolor/@hcolor <hair color: %d-%d>).
clif->message(fd, atcmd_output);
return false;
}
-
+
if (hair_color >= MIN_HAIR_COLOR && hair_color <= MAX_HAIR_COLOR) {
pc->changelook(sd, LOOK_HAIR_COLOR, hair_color);
clif->message(fd, msg_txt(36)); // Appearance changed.
@@ -1714,7 +1712,7 @@ ACMD(hair_color)
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
}
-
+
return true;
}
@@ -1725,7 +1723,7 @@ ACMD(go) {
int i;
int town = INT_MAX; // Initialized to INT_MAX instead of -1 to avoid conflicts with those who map [-3:-1] to @memo locations.
char map_name[MAP_NAME_LENGTH];
-
+
const struct {
char map[MAP_NAME_LENGTH];
int x, y;
@@ -1772,23 +1770,23 @@ ACMD(go) {
{ MAP_MALAYA, 242, 211, 5 }, // 34 = Malaya Port
{ MAP_ECLAGE, 110, 39, 3 }, // 35 = Eclage
};
-
+
memset(map_name, '\0', sizeof(map_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%11s", map_name) < 1) {
// no value matched so send the list of locations
const char* text;
-
+
// attempt to find the text help string
text = atcommand_help_string( info );
-
+
clif->message(fd, msg_txt(38)); // Invalid location number, or name.
-
+
if( text ) {// send the text to the client
clif->messageln( fd, text );
}
-
+
return false;
}
@@ -1852,7 +1850,7 @@ ACMD(go) {
clif->message(fd, msg_txt(38)); // Invalid location number or name.
return false;
}
-
+
return true;
}
@@ -1870,11 +1868,11 @@ ACMD(monster)
int i, k, range;
short mx, my;
unsigned int size;
-
+
memset(name, '\0', sizeof(name));
memset(monster, '\0', sizeof(monster));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(80)); // Please specify a display name or monster name/id.
return false;
@@ -1895,35 +1893,35 @@ ACMD(monster)
clif->message(fd, msg_txt(80)); // Give a display name and monster name/id please.
return false;
}
-
+
if ((mob_id = mob->db_searchname(monster)) == 0) // check name first (to avoid possible name beginning by a number)
mob_id = mob->db_checkid(atoi(monster));
-
+
if (mob_id == 0) {
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
return false;
}
-
+
if (number <= 0)
number = 1;
-
+
if( !name[0] )
strcpy(name, "--ja--");
-
+
// If value of atcommand_spawn_quantity_limit directive is greater than or equal to 1 and quantity of monsters is greater than value of the directive
if (battle_config.atc_spawn_quantity_limit && number > battle_config.atc_spawn_quantity_limit)
number = battle_config.atc_spawn_quantity_limit;
-
+
if (strcmpi(info->command, "monstersmall") == 0)
- size = SZ_SMALL;
+ size = SZ_MEDIUM;
else if (strcmpi(info->command, "monsterbig") == 0)
size = SZ_BIG;
else
- size = SZ_MEDIUM;
-
+ size = SZ_SMALL;
+
if (battle_config.etc_log)
ShowInfo("%s monster='%s' name='%s' id=%d count=%d (%d,%d)\n", command, monster, name, mob_id, number, sd->bl.x, sd->bl.y);
-
+
count = 0;
range = (int)sqrt((float)number) +2; // calculation of an odd number (+ 4 area around)
for (i = 0; i < number; i++) {
@@ -1931,7 +1929,7 @@ ACMD(monster)
k = mob->once_spawn(sd, sd->bl.m, mx, my, name, mob_id, 1, eventname, size, AI_NONE|(mob_id == MOBID_EMPERIUM?0x200:0x0));
count += (k != 0) ? 1 : 0;
}
-
+
if (count != 0)
if (number == count)
clif->message(fd, msg_txt(39)); // All monster summoned!
@@ -1943,7 +1941,7 @@ ACMD(monster)
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
return false;
}
-
+
return true;
}
@@ -1954,13 +1952,13 @@ int atkillmonster_sub(struct block_list *bl, va_list ap)
{
struct mob_data *md;
int flag;
-
+
nullpo_ret(md=(struct mob_data *)bl);
flag = va_arg(ap, int);
-
+
if (md->guardian_data)
return 0; //Do not touch WoE mobs!
-
+
if (flag)
status_zap(bl,md->status.hp, 0);
else
@@ -1971,22 +1969,22 @@ int atkillmonster_sub(struct block_list *bl, va_list ap)
ACMD(killmonster) {
int map_id, drop_flag;
char map_name[MAP_NAME_LENGTH_EXT];
-
+
memset(map_name, '\0', sizeof(map_name));
-
+
if (!message || !*message || sscanf(message, "%15s", map_name) < 1)
map_id = sd->bl.m;
else {
if ((map_id = map->mapname2mapid(map_name)) < 0)
map_id = sd->bl.m;
}
-
+
drop_flag = strcmpi(info->command, "killmonster2");
-
+
map->foreachinmap(atcommand->atkillmonster_sub, map_id, BL_MOB, -drop_flag);
-
+
clif->message(fd, msg_txt(165)); // All monsters killed!
-
+
return true;
}
@@ -1997,9 +1995,9 @@ ACMD(refine)
{
int i,j, position = 0, refine = 0, current_position, final_refine;
int count;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%d %d", &position, &refine) < 2) {
clif->message(fd, msg_txt(996)); // Please enter a position and an amount (usage: @refine <equip position> <+/- amount>).
sprintf(atcmd_output, msg_txt(997), EQP_HEAD_LOW); // %d: Lower Headgear
@@ -2024,9 +2022,9 @@ ACMD(refine)
clif->message(fd, atcmd_output);
return false;
}
-
+
refine = cap_value(refine, -MAX_REFINE, MAX_REFINE);
-
+
count = 0;
for (j = 0; j < EQI_MAX; j++) {
if ((i = sd->equip_index[j]) < 0)
@@ -2038,10 +2036,10 @@ ACMD(refine)
continue;
if(j == EQI_HEAD_TOP && (sd->equip_index[EQI_HEAD_MID] == i || sd->equip_index[EQI_HEAD_LOW] == i))
continue;
-
+
if(position && !(sd->status.inventory[i].equip & position))
continue;
-
+
final_refine = cap_value(sd->status.inventory[i].refine + refine, 0, MAX_REFINE);
if (sd->status.inventory[i].refine != final_refine) {
sd->status.inventory[i].refine = final_refine;
@@ -2055,7 +2053,7 @@ ACMD(refine)
count++;
}
}
-
+
if (count == 0)
clif->message(fd, msg_txt(166)); // No item has been refined.
else if (count == 1)
@@ -2064,7 +2062,7 @@ ACMD(refine)
sprintf(atcmd_output, msg_txt(168), count); // %d items have been refined.
clif->message(fd, atcmd_output);
}
-
+
return true;
}
@@ -2077,10 +2075,10 @@ ACMD(produce)
int item_id, attribute = 0, star = 0;
struct item_data *item_data;
struct item tmp_item;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(item_name, '\0', sizeof(item_name));
-
+
if (!message || !*message || (
sscanf(message, "\"%99[^\"]\" %d %d", item_name, &attribute, &star) < 1 &&
sscanf(message, "%99s %d %d", item_name, &attribute, &star) < 1
@@ -2088,15 +2086,15 @@ ACMD(produce)
clif->message(fd, msg_txt(1007)); // Please enter at least one item name/ID (usage: @produce <equip name/ID> <element> <# of very's>).
return false;
}
-
+
if ( (item_data = itemdb->search_name(item_name)) == NULL &&
(item_data = itemdb->exists(atoi(item_name))) == NULL ) {
clif->message(fd, msg_txt(170)); //This item is not an equipment.
return false;
}
-
+
item_id = item_data->nameid;
-
+
if (itemdb->isequip2(item_data)) {
int flag = 0;
if (attribute < MIN_ATTRIBUTE || attribute > MAX_ATTRIBUTE)
@@ -2114,7 +2112,7 @@ ACMD(produce)
tmp_item.card[3] = GetWord(sd->status.char_id, 1);
clif->produce_effect(sd, 0, item_id);
clif->misceffect(&sd->bl, 3);
-
+
if ((flag = pc->additem(sd, &tmp_item, 1, LOG_TYPE_COMMAND)))
clif->additem(sd, 0, 0, flag);
} else {
@@ -2122,7 +2120,7 @@ ACMD(produce)
clif->message(fd, atcmd_output);
return false;
}
-
+
return true;
}
@@ -2132,9 +2130,9 @@ ACMD(produce)
ACMD(memo)
{
int position = 0;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if( !message || !*message || sscanf(message, "%d", &position) < 1 )
{
int i;
@@ -2146,17 +2144,17 @@ ACMD(memo)
else
sprintf(atcmd_output, msg_txt(171), i); // %d - void
clif->message(sd->fd, atcmd_output);
- }
+ }
return true;
- }
-
+ }
+
if( position < 0 || position >= MAX_MEMOPOINTS )
{
sprintf(atcmd_output, msg_txt(1008), 0, MAX_MEMOPOINTS-1); // Please enter a valid position (usage: @memo <memo_position:%d-%d>).
clif->message(fd, atcmd_output);
return false;
}
-
+
pc->memo(sd, position);
return true;
}
@@ -2166,9 +2164,9 @@ ACMD(memo)
*------------------------------------------*/
ACMD(gat) {
int y;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
for (y = 2; y >= -2; y--) {
sprintf(atcmd_output, "%s (x= %d, y= %d) %02X %02X %02X %02X %02X",
map->list[sd->bl.m].name, sd->bl.x - 2, sd->bl.y + y,
@@ -2177,10 +2175,10 @@ ACMD(gat) {
map->getcell(sd->bl.m, sd->bl.x, sd->bl.y + y, CELL_GETTYPE),
map->getcell(sd->bl.m, sd->bl.x + 1, sd->bl.y + y, CELL_GETTYPE),
map->getcell(sd->bl.m, sd->bl.x + 2, sd->bl.y + y, CELL_GETTYPE));
-
+
clif->message(fd, atcmd_output);
}
-
+
return true;
}
@@ -2190,19 +2188,19 @@ ACMD(gat) {
ACMD(displaystatus)
{
int i, type, flag, tick, val1 = 0, val2 = 0, val3 = 0;
-
+
if (!message || !*message || (i = sscanf(message, "%d %d %d %d %d %d", &type, &flag, &tick, &val1, &val2, &val3)) < 1) {
clif->message(fd, msg_txt(1009)); // Please enter a status type/flag (usage: @displaystatus <status type> <flag> <tick> {<val1> {<val2> {<val3>}}}).
return false;
}
if (i < 2) flag = 1;
if (i < 3) tick = 0;
-
+
if( flag == 0 )
clif->sc_end(&sd->bl,sd->bl.id,AREA,type);
else
clif->status_change(&sd->bl, type, flag, tick, val1, val2, val3);
-
+
return true;
}
@@ -2213,12 +2211,12 @@ ACMD(statuspoint)
{
int point;
unsigned int new_status_point;
-
+
if (!message || !*message || (point = atoi(message)) == 0) {
clif->message(fd, msg_txt(1010)); // Please enter a number (usage: @stpoint <number of points>).
return false;
}
-
+
if(point < 0)
{
if(sd->status.status_point < (unsigned int)(-point))
@@ -2238,7 +2236,7 @@ ACMD(statuspoint)
{
new_status_point = sd->status.status_point + point;
}
-
+
if (new_status_point != sd->status.status_point) {
sd->status.status_point = new_status_point;
clif->updatestatus(sd, SP_STATUSPOINT);
@@ -2250,7 +2248,7 @@ ACMD(statuspoint)
clif->message(fd, msg_txt(149)); // Unable to increase the number/value.
return false;
}
-
+
return true;
}
@@ -2261,12 +2259,12 @@ ACMD(skillpoint)
{
int point;
unsigned int new_skill_point;
-
+
if (!message || !*message || (point = atoi(message)) == 0) {
clif->message(fd, msg_txt(1011)); // Please enter a number (usage: @skpoint <number of points>).
return false;
}
-
+
if(point < 0)
{
if(sd->status.skill_point < (unsigned int)(-point))
@@ -2286,7 +2284,7 @@ ACMD(skillpoint)
{
new_skill_point = sd->status.skill_point + point;
}
-
+
if (new_skill_point != sd->status.skill_point) {
sd->status.skill_point = new_skill_point;
clif->updatestatus(sd, SP_SKILLPOINT);
@@ -2298,7 +2296,7 @@ ACMD(skillpoint)
clif->message(fd, msg_txt(149)); // Unable to increase the number/value.
return false;
}
-
+
return true;
}
@@ -2308,12 +2306,12 @@ ACMD(skillpoint)
ACMD(zeny)
{
int zeny=0, ret=-1;
-
+
if (!message || !*message || (zeny = atoi(message)) == 0) {
clif->message(fd, msg_txt(1012)); // Please enter an amount (usage: @zeny <amount>).
return false;
}
-
+
if(zeny > 0){
if((ret=pc->getzeny(sd,zeny,LOG_TYPE_COMMAND,NULL)) == 1)
clif->message(fd, msg_txt(149)); // Unable to increase the number/value.
@@ -2338,34 +2336,34 @@ ACMD(param) {
int i, value = 0, new_value, max;
const char* param[] = { "str", "agi", "vit", "int", "dex", "luk" };
short* stats[6];
- //we don't use direct initialization because it isn't part of the c standard.
-
+ //we don't use direct initialization because it isn't part of the c standard.
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) {
clif->message(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>).
return false;
}
-
+
ARR_FIND( 0, ARRAYLENGTH(param), i, strcmpi(info->command, param[i]) == 0 );
-
+
if( i == ARRAYLENGTH(param) || i > MAX_STATUS_TYPE) { // normally impossible...
clif->message(fd, msg_txt(1013)); // Please enter a valid value (usage: @str/@agi/@vit/@int/@dex/@luk <+/-adjustment>).
return false;
}
-
+
stats[0] = &sd->status.str;
stats[1] = &sd->status.agi;
stats[2] = &sd->status.vit;
stats[3] = &sd->status.int_;
stats[4] = &sd->status.dex;
stats[5] = &sd->status.luk;
-
+
if( battle_config.atcommand_max_stat_bypass )
max = SHRT_MAX;
else
max = pc_maxparameter(sd);
-
+
if(value < 0 && *stats[i] <= -value) {
new_value = 1;
} else if(max - *stats[i] < value) {
@@ -2373,7 +2371,7 @@ ACMD(param) {
} else {
new_value = *stats[i] + value;
}
-
+
if (new_value != *stats[i]) {
*stats[i] = new_value;
clif->updatestatus(sd, SP_STR + i);
@@ -2387,7 +2385,7 @@ ACMD(param) {
clif->message(fd, msg_txt(149)); // Unable to increase the number/value.
return false;
}
-
+
return true;
}
@@ -2397,15 +2395,15 @@ ACMD(param) {
ACMD(stat_all) {
int index, count, value, max, new_value;
short* stats[6];
- //we don't use direct initialization because it isn't part of the c standard.
-
+ //we don't use direct initialization because it isn't part of the c standard.
+
stats[0] = &sd->status.str;
stats[1] = &sd->status.agi;
stats[2] = &sd->status.vit;
stats[3] = &sd->status.int_;
stats[4] = &sd->status.dex;
stats[5] = &sd->status.luk;
-
+
if (!message || !*message || sscanf(message, "%d", &value) < 1 || value == 0) {
value = pc_maxparameter(sd);
max = pc_maxparameter(sd);
@@ -2415,17 +2413,16 @@ ACMD(stat_all) {
else
max = pc_maxparameter(sd);
}
-
+
count = 0;
for (index = 0; index < ARRAYLENGTH(stats); index++) {
-
if (value > 0 && *stats[index] > max - value)
new_value = max;
else if (value < 0 && *stats[index] <= -value)
new_value = 1;
else
new_value = *stats[index] +value;
-
+
if (new_value != (int)*stats[index]) {
*stats[index] = new_value;
clif->updatestatus(sd, SP_STR + index);
@@ -2433,7 +2430,7 @@ ACMD(stat_all) {
count++;
}
}
-
+
if (count > 0) { // if at least 1 stat modified
status_calc_pc(sd, SCO_FORCE);
clif->message(fd, msg_txt(84)); // All stats changed!
@@ -2444,7 +2441,7 @@ ACMD(stat_all) {
clif->message(fd, msg_txt(178)); // You cannot increase that stat anymore.
return false;
}
-
+
return true;
}
@@ -2455,12 +2452,12 @@ ACMD(guildlevelup) {
int level = 0;
int16 added_level;
struct guild *guild_info;
-
+
if (!message || !*message || sscanf(message, "%d", &level) < 1 || level == 0) {
clif->message(fd, msg_txt(1014)); // Please enter a valid level (usage: @guildlvup/@guildlvlup <# of levels>).
return false;
}
-
+
if (sd->status.guild_id <= 0 || (guild_info = sd->guild) == NULL) {
clif->message(fd, msg_txt(43)); // You're not in a guild.
return false;
@@ -2471,13 +2468,13 @@ ACMD(guildlevelup) {
return false;
}
#endif // 0
-
+
if (level > INT16_MAX || (level > 0 && level > MAX_GUILDLEVEL - guild_info->guild_lv)) // fix positive overflow
level = MAX_GUILDLEVEL - guild_info->guild_lv;
else if (level < INT16_MIN || (level < 0 && level < 1 - guild_info->guild_lv)) // fix negative overflow
level = 1 - guild_info->guild_lv;
added_level = (int16)level;
-
+
if (added_level != 0) {
intif->guild_change_basicinfo(guild_info->guild_id, GBI_GUILDLV, &added_level, sizeof(added_level));
clif->message(fd, msg_txt(179)); // Guild level changed.
@@ -2485,7 +2482,7 @@ ACMD(guildlevelup) {
clif->message(fd, msg_txt(45)); // Guild level change failed.
return false;
}
-
+
return true;
}
@@ -2496,12 +2493,12 @@ ACMD(makeegg)
{
struct item_data *item_data;
int id, pet_id;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1015)); // Please enter a monster/egg name/ID (usage: @makeegg <pet>).
return false;
}
-
+
if ((item_data = itemdb->search_name(message)) != NULL) // for egg name
id = item_data->nameid;
else
@@ -2509,7 +2506,7 @@ ACMD(makeegg)
;
else
id = atoi(message);
-
+
pet_id = pet->search_petDB_index(id, PET_CLASS);
if (pet_id < 0)
pet_id = pet->search_petDB_index(id, PET_EGG);
@@ -2524,7 +2521,7 @@ ACMD(makeegg)
clif->message(fd, msg_txt(180)); // The monster/egg name/id doesn't exist.
return false;
}
-
+
return true;
}
@@ -2539,7 +2536,7 @@ ACMD(hatch)
clif->message(fd, msg_txt(181)); // You already have a pet.
return false;
}
-
+
return true;
}
@@ -2550,29 +2547,29 @@ ACMD(petfriendly)
{
int friendly;
struct pet_data *pd;
-
+
if (!message || !*message || (friendly = atoi(message)) < 0) {
clif->message(fd, msg_txt(1016)); // Please enter a valid value (usage: @petfriendly <0-1000>).
return false;
}
-
+
pd = sd->pd;
if (!pd) {
clif->message(fd, msg_txt(184)); // Sorry, but you have no pet.
return false;
}
-
+
if (friendly < 0 || friendly > 1000)
{
clif->message(fd, msg_txt(37)); // An invalid number was specified.
return false;
}
-
+
if (friendly == pd->pet.intimate) {
clif->message(fd, msg_txt(183)); // Pet intimacy is already at maximum.
return false;
}
-
+
pet->set_intimate(pd, friendly);
clif->send_petstatus(sd);
clif->message(fd, msg_txt(182)); // Pet intimacy changed.
@@ -2586,12 +2583,12 @@ ACMD(pethungry)
{
int hungry;
struct pet_data *pd;
-
+
if (!message || !*message || (hungry = atoi(message)) < 0) {
clif->message(fd, msg_txt(1017)); // Please enter a valid number (usage: @pethungry <0-100>).
return false;
}
-
+
pd = sd->pd;
if (!sd->status.pet_id || !pd) {
clif->message(fd, msg_txt(184)); // Sorry, but you have no pet.
@@ -2605,11 +2602,11 @@ ACMD(pethungry)
clif->message(fd, msg_txt(186)); // Pet hunger is already at maximum.
return false;
}
-
+
pd->pet.hungry = hungry;
clif->send_petstatus(sd);
clif->message(fd, msg_txt(185)); // Pet hunger changed.
-
+
return true;
}
@@ -2628,12 +2625,12 @@ ACMD(petrename)
clif->message(fd, msg_txt(188)); // You can already rename your pet.
return false;
}
-
+
pd->pet.rename_flag = 0;
intif->save_petdata(sd->status.account_id, &pd->pet);
clif->send_petstatus(sd);
clif->message(fd, msg_txt(187)); // You can now rename your pet.
-
+
return true;
}
@@ -2642,24 +2639,23 @@ ACMD(petrename)
*------------------------------------------*/
ACMD(recall) {
struct map_session_data *pl_sd = NULL;
-
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1018)); // Please enter a player name (usage: @recall <char name/ID>).
return false;
}
-
+
if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
clif->message(fd, msg_txt(81)); // Your GM level doesn't authorize you to preform this action on the specified player.
return false;
}
-
+
if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(1019)); // You are not authorized to warp someone to this map.
return false;
@@ -2674,7 +2670,7 @@ ACMD(recall) {
pc->setpos(pl_sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_RESPAWN);
sprintf(atcmd_output, msg_txt(46), pl_sd->status.name); // %s recalled!
clif->message(fd, atcmd_output);
-
+
return true;
}
@@ -2684,17 +2680,17 @@ ACMD(recall) {
*------------------------------------------*/
ACMD(char_block)
{
-
+
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1021)); // Please enter a player name (usage: @block <char name>).
return false;
}
-
+
chrif->char_ask_name(sd->status.account_id, atcmd_player_name, 1, 0, 0, 0, 0, 0, 0); // type: 1 - block
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
-
+
return true;
}
@@ -2719,17 +2715,17 @@ ACMD(char_ban)
int year, month, day, hour, minute, second, value;
time_t timestamp;
struct tm *tmtime;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message || sscanf(message, "%255s %23[^\n]", atcmd_output, atcmd_player_name) < 2) {
clif->message(fd, msg_txt(1022)); // Please enter ban time and a player name (usage: @ban <time> <char name>).
return false;
}
-
+
atcmd_output[sizeof(atcmd_output)-1] = '\0';
-
+
modif_p = atcmd_output;
year = month = day = hour = minute = second = 0;
while (modif_p[0] != '\0') {
@@ -2787,10 +2783,10 @@ ACMD(char_ban)
clif->message(fd,msg_txt(1023)); // You are not allowed to reduce the length of a ban.
return false;
}
-
+
chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charban") ? 6 : 2, year, month, day, hour, minute, second); // type: 2 - ban; 6 - charban
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
-
+
return true;
}
@@ -2799,18 +2795,17 @@ ACMD(char_ban)
*------------------------------------------*/
ACMD(char_unblock)
{
-
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1024)); // Please enter a player name (usage: @unblock <char name>).
return false;
}
-
+
// send answer to login server via char-server
chrif->char_ask_name(sd->status.account_id, atcmd_player_name, 3, 0, 0, 0, 0, 0, 0); // type: 3 - unblock
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
-
+
return true;
}
@@ -2819,48 +2814,47 @@ ACMD(char_unblock)
*------------------------------------------*/
ACMD(char_unban)
{
-
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1025)); // Please enter a player name (usage: @unban <char name>).
return false;
}
-
+
// send answer to login server via char-server
chrif->char_ask_name(sd->status.account_id, atcmd_player_name, !strcmpi(info->command,"charunban") ? 7 : 4, 0, 0, 0, 0, 0, 0); // type: 4 - unban account; type 7 - unban character
clif->message(fd, msg_txt(88)); // Character name sent to char-server to ask it.
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-ACMD(night) {
-
+ACMD(night)
+{
if (map->night_flag != 1) {
pc->map_night_timer(pc->night_timer_tid, 0, 0, 1);
} else {
clif->message(fd, msg_txt(89)); // Night mode is already enabled.
return false;
}
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-ACMD(day) {
-
+ACMD(day)
+{
if (map->night_flag != 0) {
pc->map_day_timer(pc->day_timer_tid, 0, 0, 1);
} else {
clif->message(fd, msg_txt(90)); // Day mode is already enabled.
return false;
}
-
+
return true;
}
@@ -2871,7 +2865,7 @@ ACMD(doom)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
@@ -2883,9 +2877,9 @@ ACMD(doom)
}
}
mapit->free(iter);
-
+
clif->message(fd, msg_txt(62)); // Judgment was made.
-
+
return true;
}
@@ -2896,7 +2890,7 @@ ACMD(doommap)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
@@ -2908,19 +2902,19 @@ ACMD(doommap)
}
}
mapit->free(iter);
-
+
clif->message(fd, msg_txt(62)); // Judgment was made.
-
+
return true;
}
/*==========================================
*
*------------------------------------------*/
-void atcommand_raise_sub(struct map_session_data* sd) {
-
+void atcommand_raise_sub(struct map_session_data* sd)
+{
status->revive(&sd->bl, 100, 100);
-
+
clif->skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,4,1);
clif->message(sd->fd, msg_txt(63)); // Mercy has been shown.
}
@@ -2932,15 +2926,15 @@ ACMD(raise)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
if( pc_isdead(pl_sd) )
atcommand->raise_sub(pl_sd);
mapit->free(iter);
-
+
clif->message(fd, msg_txt(64)); // Mercy has been granted.
-
+
return true;
}
@@ -2951,15 +2945,15 @@ ACMD(raisemap)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
if (sd->bl.m == pl_sd->bl.m && pc_isdead(pl_sd) )
atcommand->raise_sub(pl_sd);
mapit->free(iter);
-
+
clif->message(fd, msg_txt(64)); // Mercy has been granted.
-
+
return true;
}
@@ -2969,27 +2963,27 @@ ACMD(raisemap)
ACMD(kick)
{
struct map_session_data *pl_sd;
-
+
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1026)); // Please enter a player name (usage: @kick <char name/ID>).
return false;
}
-
+
if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
-
+
clif->GM_kick(sd, pl_sd);
-
+
return true;
}
@@ -3000,7 +2994,7 @@ ACMD(kickall)
{
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
@@ -3010,9 +3004,9 @@ ACMD(kickall)
}
}
mapit->free(iter);
-
+
clif->message(fd, msg_txt(195)); // All players have been kicked!
-
+
return true;
}
@@ -3025,7 +3019,7 @@ ACMD(allskill)
sd->status.skill_point = 0; // 0 skill points
clif->updatestatus(sd, SP_SKILLPOINT); // update
clif->message(fd, msg_txt(76)); // All skills have been added to your skill tree.
-
+
return true;
}
@@ -3035,21 +3029,21 @@ ACMD(allskill)
ACMD(questskill)
{
uint16 skill_id, index;
-
+
if (!message || !*message || (skill_id = atoi(message)) <= 0)
{// also send a list of skills applicable to this command
const char* text;
-
+
// attempt to find the text corresponding to this command
text = atcommand_help_string( info );
-
+
// send the error message as always
clif->message(fd, msg_txt(1027)); // Please enter a quest skill number.
-
+
if( text ) {// send the skill ID list associated with this command
clif->messageln( fd, text );
}
-
+
return false;
}
if( !(index = skill->get_index(skill_id)) ) {
@@ -3064,10 +3058,10 @@ ACMD(questskill)
clif->message(fd, msg_txt(196)); // You already have this quest skill.
return false;
}
-
+
pc->skill(sd, skill_id, 1, 0);
clif->message(fd, msg_txt(70)); // You have learned the skill.
-
+
return true;
}
@@ -3077,21 +3071,21 @@ ACMD(questskill)
ACMD(lostskill)
{
uint16 skill_id, index;
-
+
if (!message || !*message || (skill_id = atoi(message)) <= 0)
{// also send a list of skills applicable to this command
const char* text;
-
+
// attempt to find the text corresponding to this command
text = atcommand_help_string( info );
-
+
// send the error message as always
clif->message(fd, msg_txt(1027)); // Please enter a quest skill number.
-
+
if( text ) {// send the skill ID list associated with this command
clif->messageln( fd, text );
}
-
+
return false;
}
if ( !( index = skill->get_index(skill_id) ) ) {
@@ -3106,12 +3100,12 @@ ACMD(lostskill)
clif->message(fd, msg_txt(201)); // You don't have this quest skill.
return false;
}
-
+
sd->status.skill[index].lv = 0;
sd->status.skill[index].flag = 0;
clif->deleteskill(sd,skill_id);
clif->message(fd, msg_txt(71)); // You have forgotten the skill.
-
+
return true;
}
@@ -3122,9 +3116,9 @@ ACMD(spiritball)
{
int max_spiritballs;
int number;
-
+
max_spiritballs = min(ARRAYLENGTH(sd->spirit_timer), 0x7FFF);
-
+
if( !message || !*message || (number = atoi(message)) < 0 || number > max_spiritballs )
{
char msg[CHAT_SIZE_MAX];
@@ -3132,13 +3126,13 @@ ACMD(spiritball)
clif->message(fd, msg);
return false;
}
-
+
if( sd->spiritball > 0 )
pc->delspiritball(sd, sd->spiritball, 1);
sd->spiritball = number;
clif->spiritball(&sd->bl);
// no message, player can look the difference
-
+
return true;
}
@@ -3148,16 +3142,16 @@ ACMD(spiritball)
ACMD(party)
{
char party_name[NAME_LENGTH];
-
+
memset(party_name, '\0', sizeof(party_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) {
clif->message(fd, msg_txt(1029)); // Please enter a party name (usage: @party <party_name>).
return false;
}
-
+
party->create(sd, party_name, 0, 0);
-
+
return true;
}
@@ -3168,25 +3162,24 @@ ACMD(guild)
{
char guild_name[NAME_LENGTH];
int prev;
-
+
memset(guild_name, '\0', sizeof(guild_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) {
clif->message(fd, msg_txt(1030)); // Please enter a guild name (usage: @guild <guild_name>).
return false;
}
-
+
prev = battle_config.guild_emperium_check;
battle_config.guild_emperium_check = 0;
guild->create(sd, guild_name);
battle_config.guild_emperium_check = prev;
-
+
return true;
}
ACMD(breakguild)
{
-
if (sd->status.guild_id) { // Check if the player has a guild
struct guild *g;
g = sd->guild; // Search the guild
@@ -3222,11 +3215,11 @@ ACMD(agitstart) {
clif->message(fd, msg_txt(73)); // War of Emperium is currently in progress.
return false;
}
-
+
map->agit_flag = 1;
guild->agit_start();
clif->message(fd, msg_txt(72)); // War of Emperium has been initiated.
-
+
return true;
}
@@ -3238,11 +3231,11 @@ ACMD(agitstart2) {
clif->message(fd, msg_txt(404)); // "War of Emperium SE is currently in progress."
return false;
}
-
+
map->agit2_flag = 1;
guild->agit2_start();
clif->message(fd, msg_txt(403)); // "War of Emperium SE has been initiated."
-
+
return true;
}
@@ -3254,11 +3247,11 @@ ACMD(agitend) {
clif->message(fd, msg_txt(75)); // War of Emperium is currently not in progress.
return false;
}
-
+
map->agit_flag = 0;
guild->agit_end();
clif->message(fd, msg_txt(74)); // War of Emperium has been ended.
-
+
return true;
}
@@ -3270,11 +3263,11 @@ ACMD(agitend2) {
clif->message(fd, msg_txt(406)); // "War of Emperium SE is currently not in progress."
return false;
}
-
+
map->agit2_flag = 0;
guild->agit2_end();
clif->message(fd, msg_txt(405)); // "War of Emperium SE has been ended."
-
+
return true;
}
@@ -3294,15 +3287,15 @@ ACMD(idsearch)
char item_name[100];
unsigned int i, match;
struct item_data *item_array[MAX_SEARCH];
-
+
memset(item_name, '\0', sizeof(item_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%99s", item_name) < 0) {
clif->message(fd, msg_txt(1031)); // Please enter part of an item name (usage: @idsearch <part_of_item_name>).
return false;
}
-
+
sprintf(atcmd_output, msg_txt(77), item_name); // Search results for '%s' (name: id):
clif->message(fd, atcmd_output);
match = itemdb->search_name_array(item_array, MAX_SEARCH, item_name, 0);
@@ -3317,7 +3310,7 @@ ACMD(idsearch)
}
sprintf(atcmd_output, msg_txt(79), match); // %d results found.
clif->message(fd, atcmd_output);
-
+
return true;
}
@@ -3329,14 +3322,14 @@ ACMD(recallall)
struct map_session_data* pl_sd;
struct s_mapiterator* iter;
int count;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map.
return false;
}
-
+
count = 0;
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
@@ -3355,13 +3348,13 @@ ACMD(recallall)
}
}
mapit->free(iter);
-
+
clif->message(fd, msg_txt(92)); // All characters recalled!
if (count) {
sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled.
clif->message(fd, atcmd_output);
}
-
+
return true;
}
@@ -3375,29 +3368,29 @@ ACMD(guildrecall)
int count;
char guild_name[NAME_LENGTH];
struct guild *g;
-
+
memset(guild_name, '\0', sizeof(guild_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) {
clif->message(fd, msg_txt(1034)); // Please enter a guild name/ID (usage: @guildrecall <guild_name/ID>).
return false;
}
-
+
if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map.
return false;
}
-
+
if ((g = guild->searchname(guild_name)) == NULL && // name first to avoid error when name begin with a number
(g = guild->search(atoi(message))) == NULL)
{
clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online.
return false;
}
-
+
count = 0;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
@@ -3411,14 +3404,14 @@ ACMD(guildrecall)
}
}
mapit->free(iter);
-
+
sprintf(atcmd_output, msg_txt(93), g->name); // All online characters of the %s guild have been recalled to your position.
clif->message(fd, atcmd_output);
if (count) {
sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled.
clif->message(fd, atcmd_output);
}
-
+
return true;
}
@@ -3432,29 +3425,29 @@ ACMD(partyrecall)
char party_name[NAME_LENGTH];
struct party_data *p;
int count;
-
+
memset(party_name, '\0', sizeof(party_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) {
clif->message(fd, msg_txt(1035)); // Please enter a party name/ID (usage: @partyrecall <party_name/ID>).
return false;
}
-
+
if (sd->bl.m >= 0 && map->list[sd->bl.m].flag.nowarpto && !pc_has_permission(sd, PC_PERM_WARP_ANYWHERE)) {
clif->message(fd, msg_txt(1032)); // You are not authorized to warp someone to your current map.
return false;
}
-
+
if ((p = party->searchname(party_name)) == NULL && // name first to avoid error when name begin with a number
(p = party->search(atoi(message))) == NULL)
{
clif->message(fd, msg_txt(96)); // Incorrect name or ID, or no one from the party is online.
return false;
}
-
+
count = 0;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
if (sd->status.account_id != pl_sd->status.account_id && pl_sd->status.party_id == p->party.party_id) {
@@ -3467,14 +3460,14 @@ ACMD(partyrecall)
}
}
mapit->free(iter);
-
+
sprintf(atcmd_output, msg_txt(95), p->party.name); // All online characters of the %s party have been recalled to your position.
clif->message(fd, atcmd_output);
if (count) {
sprintf(atcmd_output, msg_txt(1033), count); // Because you are not authorized to warp from some maps, %d player(s) have not been recalled.
clif->message(fd, atcmd_output);
}
-
+
return true;
}
@@ -3485,7 +3478,7 @@ ACMD(reloaditemdb)
{
itemdb->reload();
clif->message(fd, msg_txt(97)); // Item database has been reloaded.
-
+
return true;
}
@@ -3500,7 +3493,7 @@ ACMD(reloadmobdb) {
mercenary->read_skilldb();
elemental->reload_db();
clif->message(fd, msg_txt(98)); // Monster database has been reloaded.
-
+
return true;
}
@@ -3514,7 +3507,7 @@ ACMD(reloadskilldb)
elemental->reload_skilldb();
mercenary->read_skilldb();
clif->message(fd, msg_txt(99)); // Skill database has been reloaded.
-
+
return true;
}
@@ -3523,21 +3516,21 @@ ACMD(reloadskilldb)
*------------------------------------------*/
ACMD(reloadatcommand) {
config_t run_test;
-
+
if (libconfig->read_file(&run_test, "conf/groups.conf")) {
clif->message(fd, msg_txt(1036)); // Error reading groups.conf, reload failed.
return false;
}
-
+
libconfig->destroy(&run_test);
-
+
if (libconfig->read_file(&run_test, map->ATCOMMAND_CONF_FILENAME)) {
clif->message(fd, msg_txt(1037)); // Error reading atcommand.conf, reload failed.
return false;
}
-
+
libconfig->destroy(&run_test);
-
+
atcommand->doload();
pcg->reload();
clif->message(fd, msg_txt(254));
@@ -3550,9 +3543,9 @@ ACMD(reloadbattleconf)
{
struct Battle_Config prev_config;
memcpy(&prev_config, &battle_config, sizeof(prev_config));
-
+
battle->config_read(map->BATTLE_CONF_FILENAME);
-
+
if( prev_config.item_rate_mvp != battle_config.item_rate_mvp
|| prev_config.item_rate_common != battle_config.item_rate_common
|| prev_config.item_rate_common_boss != battle_config.item_rate_common_boss
@@ -3583,8 +3576,7 @@ ACMD(reloadbattleconf)
|| prev_config.item_drop_treasure_max != battle_config.item_drop_treasure_max
|| prev_config.base_exp_rate != battle_config.base_exp_rate
|| prev_config.job_exp_rate != battle_config.job_exp_rate
- )
- { // Exp or Drop rates changed.
+ ) { // Exp or Drop rates changed.
mob->reload(); //Needed as well so rate changes take effect.
chrif->ragsrvinfo(battle_config.base_exp_rate, battle_config.job_exp_rate, battle_config.item_rate_common);
}
@@ -3618,7 +3610,7 @@ ACMD(reloadscript) {
//atcommand_broadcast( fd, sd, "@broadcast", "Server is reloading scripts..." );
//atcommand_broadcast( fd, sd, "@broadcast", "You will feel a bit of lag at this point !" );
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
if (pl_sd->npc_id || pl_sd->npc_shopid) {
@@ -3638,14 +3630,14 @@ ACMD(reloadscript) {
}
}
mapit->free(iter);
-
+
flush_fifos();
map->reloadnpc(true, NULL, 0); // reload config files seeking for npcs
script->reload();
npc->reload();
-
+
clif->message(fd, msg_txt(100)); // Scripts have been reloaded.
-
+
return true;
}
@@ -3667,33 +3659,33 @@ ACMD(mapinfo) {
int i, m_id, chat_num = 0, list = 0, vend_num = 0;
unsigned short m_index;
char mapname[24];
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(mapname, '\0', sizeof(mapname));
memset(direction, '\0', sizeof(direction));
-
+
sscanf(message, "%d %23[^\n]", &list, mapname);
-
+
if (list < 0 || list > 3) {
clif->message(fd, msg_txt(1038)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
return false;
}
-
+
if (mapname[0] == '\0') {
safestrncpy(mapname, mapindex_id2name(sd->mapindex), MAP_NAME_LENGTH);
m_id = map->mapindex2mapid(sd->mapindex);
} else {
m_id = map->mapname2mapid(mapname);
}
-
+
if (m_id < 0) {
clif->message(fd, msg_txt(1)); // Map not found.
return false;
}
m_index = mapindex->name2id(mapname); //This one shouldn't fail since the previous seek did not.
-
+
clif->message(fd, msg_txt(1039)); // ------ Map Info ------
-
+
// count chats (for initial message)
chat_num = 0;
iter = mapit_getallusers();
@@ -3706,21 +3698,21 @@ ACMD(mapinfo) {
}
}
mapit->free(iter);
-
+
sprintf(atcmd_output, msg_txt(1040), mapname, map->list[m_id].zone->name, map->list[m_id].users, map->list[m_id].npc_num, chat_num, vend_num); // Map: %s (Zone:%s) | Players: %d | NPCs: %d | Chats: %d | Vendings: %d
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1041)); // ------ Map Flags ------
if (map->list[m_id].flag.town)
clif->message(fd, msg_txt(1042)); // Town Map
-
+
if (battle_config.autotrade_mapflag == map->list[m_id].flag.autotrade)
clif->message(fd, msg_txt(1043)); // Autotrade Enabled
else
clif->message(fd, msg_txt(1044)); // Autotrade Disabled
-
+
if (map->list[m_id].flag.battleground)
clif->message(fd, msg_txt(1045)); // Battlegrounds ON
-
+
strcpy(atcmd_output,msg_txt(1046)); // PvP Flags:
if (map->list[m_id].flag.pvp)
strcat(atcmd_output, msg_txt(1047)); // Pvp ON |
@@ -3733,7 +3725,7 @@ ACMD(mapinfo) {
if (map->list[m_id].flag.pvp_nocalcrank)
strcat(atcmd_output, msg_txt(1051)); // NoCalcRank |
clif->message(fd, atcmd_output);
-
+
strcpy(atcmd_output,msg_txt(1052)); // GvG Flags:
if (map->list[m_id].flag.gvg)
strcat(atcmd_output, msg_txt(1053)); // GvG ON |
@@ -3744,7 +3736,7 @@ ACMD(mapinfo) {
if (map->list[m_id].flag.gvg_noparty)
strcat(atcmd_output, msg_txt(1056)); // NoParty |
clif->message(fd, atcmd_output);
-
+
strcpy(atcmd_output,msg_txt(1057)); // Teleport Flags:
if (map->list[m_id].flag.noteleport)
strcat(atcmd_output, msg_txt(1058)); // NoTeleport |
@@ -3759,12 +3751,12 @@ ACMD(mapinfo) {
if (map->list[m_id].flag.nomemo)
strcat(atcmd_output, msg_txt(1064)); // NoMemo |
clif->message(fd, atcmd_output);
-
+
sprintf(atcmd_output, msg_txt(1065), // No Exp Penalty: %s | No Zeny Penalty: %s
(map->list[m_id].flag.noexppenalty) ? msg_txt(1066) : msg_txt(1067),
(map->list[m_id].flag.nozenypenalty) ? msg_txt(1066) : msg_txt(1067)); // On / Off
clif->message(fd, atcmd_output);
-
+
if (map->list[m_id].flag.nosave) {
if (!map->list[m_id].save.map)
clif->message(fd, msg_txt(1068)); // No Save (Return to last Save Point)
@@ -3777,7 +3769,7 @@ ACMD(mapinfo) {
clif->message(fd, atcmd_output);
}
}
-
+
strcpy(atcmd_output,msg_txt(1071)); // Weather Flags:
if (map->list[m_id].flag.snow)
strcat(atcmd_output, msg_txt(1072)); // Snow |
@@ -3796,7 +3788,7 @@ ACMD(mapinfo) {
if (map->list[m_id].flag.nightenabled)
strcat(atcmd_output, msg_txt(1080)); // Displays Night |
clif->message(fd, atcmd_output);
-
+
strcpy(atcmd_output,msg_txt(1081)); // Other Flags:
if (map->list[m_id].flag.nobranch)
strcat(atcmd_output, msg_txt(1082)); // NoBranch |
@@ -3815,7 +3807,7 @@ ACMD(mapinfo) {
if (map->list[m_id].flag.reset)
strcat(atcmd_output, msg_txt(1089)); // Reset |
clif->message(fd, atcmd_output);
-
+
strcpy(atcmd_output,msg_txt(1090)); // Other Flags:
if (map->list[m_id].nocommand)
strcat(atcmd_output, msg_txt(1091)); // NoCommand |
@@ -3832,7 +3824,7 @@ ACMD(mapinfo) {
if (map->list[m_id].flag.guildlock)
strcat(atcmd_output, msg_txt(1097)); // GuildLock |
clif->message(fd, atcmd_output);
-
+
switch (list) {
case 0:
// Do nothing. It's list 0, no additional display.
@@ -3881,8 +3873,8 @@ ACMD(mapinfo) {
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
{
if ((cd = (struct chat_data*)map->id2bl(pl_sd->chatID)) != NULL &&
- pl_sd->mapindex == m_index &&
- cd->usersd[0] == pl_sd)
+ pl_sd->mapindex == m_index &&
+ cd->usersd[0] == pl_sd)
{
sprintf(atcmd_output, msg_txt(1114), // Chat: %s | Player: %s | Location: %d %d
cd->title, pl_sd->status.name, cd->bl.x, cd->bl.y);
@@ -3898,7 +3890,7 @@ ACMD(mapinfo) {
clif->message(fd, msg_txt(1118)); // Please enter at least one valid list number (usage: @mapinfo <0-3> <map>).
return false;
}
-
+
return true;
}
@@ -3911,24 +3903,24 @@ ACMD(mount_peco)
clif->message(fd, msg_txt(212)); // Cannot mount while in disguise.
return false;
}
-
+
if( sd->sc.data[SC_ALL_RIDING] ) {
clif->message(fd, msg_txt(1476)); // You are already mounting something else
return false;
}
-
+
if( (sd->class_&MAPID_THIRDMASK) == MAPID_RUNE_KNIGHT ) {
if( !pc->checkskill(sd,RK_DRAGONTRAINING) ) {
sprintf(atcmd_output, msg_txt(213), skill->get_desc(RK_DRAGONTRAINING)); // You need %s to mount!
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 +3932,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;
@@ -3982,10 +3974,10 @@ ACMD(mount_peco)
ACMD(guildspy) {
char guild_name[NAME_LENGTH];
struct guild *g;
-
+
memset(guild_name, '\0', sizeof(guild_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!map->enable_spy)
{
clif->message(fd, msg_txt(1125)); // The mapserver has spy command support disabled.
@@ -3995,7 +3987,7 @@ ACMD(guildspy) {
clif->message(fd, msg_txt(1126)); // Please enter a guild name/ID (usage: @guildspy <guild_name/ID>).
return false;
}
-
+
if ((g = guild->searchname(guild_name)) != NULL || // name first to avoid error when name begin with a number
(g = guild->search(atoi(message))) != NULL) {
if (sd->guildspy == g->guild_id) {
@@ -4011,7 +4003,7 @@ ACMD(guildspy) {
clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the specified guild is online.
return false;
}
-
+
return true;
}
@@ -4021,21 +4013,21 @@ ACMD(guildspy) {
ACMD(partyspy) {
char party_name[NAME_LENGTH];
struct party_data *p;
-
+
memset(party_name, '\0', sizeof(party_name));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!map->enable_spy)
{
clif->message(fd, msg_txt(1125)); // The mapserver has spy command support disabled.
return false;
}
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", party_name) < 1) {
clif->message(fd, msg_txt(1127)); // Please enter a party name/ID (usage: @partyspy <party_name/ID>).
return false;
}
-
+
if ((p = party->searchname(party_name)) != NULL || // name first to avoid error when name begin with a number
(p = party->search(atoi(message))) != NULL) {
if (sd->partyspy == p->party.party_id) {
@@ -4051,7 +4043,7 @@ ACMD(partyspy) {
clif->message(fd, msg_txt(96)); // Incorrect name/ID, or no one from the specified party is online.
return false;
}
-
+
return true;
}
@@ -4061,7 +4053,7 @@ ACMD(partyspy) {
ACMD(repairall)
{
int count, i;
-
+
count = 0;
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].nameid && sd->status.inventory[i].attribute == 1) {
@@ -4070,7 +4062,7 @@ ACMD(repairall)
count++;
}
}
-
+
if (count > 0) {
clif->misceffect(&sd->bl, 3);
clif->equiplist(sd);
@@ -4079,7 +4071,7 @@ ACMD(repairall)
clif->message(fd, msg_txt(108)); // No item need to be repaired.
return false;
}
-
+
return true;
}
@@ -4088,14 +4080,14 @@ ACMD(repairall)
*------------------------------------------*/
ACMD(nuke) {
struct map_session_data *pl_sd;
-
+
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1128)); // Please enter a player name (usage: @nuke <char name>).
return false;
}
-
+
if ((pl_sd = map->nick2sd(atcmd_player_name)) != NULL) {
if (pc_get_group_level(sd) >= pc_get_group_level(pl_sd)) { // you can kill only lower or same GM level
skill->castend_nodamage_id(&pl_sd->bl, &pl_sd->bl, NPC_SELFDESTRUCTION, 99, timer->gettick(), 0);
@@ -4108,7 +4100,7 @@ ACMD(nuke) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
return true;
}
@@ -4118,14 +4110,14 @@ ACMD(nuke) {
ACMD(tonpc) {
char npcname[NAME_LENGTH+1];
struct npc_data *nd;
-
+
memset(npcname, 0, sizeof(npcname));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", npcname) < 1) {
clif->message(fd, msg_txt(1129)); // Please enter a NPC name (usage: @tonpc <NPC_name>).
return false;
}
-
+
if ((nd = npc->name2id(npcname)) != NULL) {
if (nd->bl.m != -1 && pc->setpos(sd, map_id2index(nd->bl.m), nd->bl.x, nd->bl.y, CLR_TELEPORT) == 0)
clif->message(fd, msg_txt(0)); // Warped.
@@ -4135,7 +4127,7 @@ ACMD(tonpc) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
-
+
return true;
}
@@ -4145,14 +4137,14 @@ ACMD(tonpc) {
ACMD(shownpc)
{
char NPCname[NAME_LENGTH+1];
-
+
memset(NPCname, '\0', sizeof(NPCname));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) {
clif->message(fd, msg_txt(1130)); // Please enter a NPC name (usage: @enablenpc <NPC_name>).
return false;
}
-
+
if (npc->name2id(NPCname) != NULL) {
npc->enable(NPCname, 1);
clif->message(fd, msg_txt(110)); // Npc Enabled.
@@ -4160,7 +4152,7 @@ ACMD(shownpc)
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
-
+
return true;
}
@@ -4170,19 +4162,19 @@ ACMD(shownpc)
ACMD(hidenpc)
{
char NPCname[NAME_LENGTH+1];
-
+
memset(NPCname, '\0', sizeof(NPCname));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", NPCname) < 1) {
clif->message(fd, msg_txt(1131)); // Please enter a NPC name (usage: @hidenpc <NPC_name>).
return false;
}
-
+
if (npc->name2id(NPCname) == NULL) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
-
+
npc->enable(NPCname, 0);
clif->message(fd, msg_txt(112)); // Npc Disabled.
return true;
@@ -4191,26 +4183,26 @@ ACMD(hidenpc)
ACMD(loadnpc)
{
FILE *fp;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1132)); // Please enter a script file name (usage: @loadnpc <file name>).
return false;
}
-
+
// check if script file exists
if ((fp = fopen(message, "r")) == NULL) {
clif->message(fd, msg_txt(261));
return false;
}
fclose(fp);
-
+
// add to list of script sources and run it
npc->addsrcfile(message);
npc->parsesrcfile(message,true);
npc->read_event_script();
-
+
clif->message(fd, msg_txt(262));
-
+
return true;
}
@@ -4218,19 +4210,19 @@ ACMD(unloadnpc)
{
struct npc_data *nd;
char NPCname[NAME_LENGTH+1];
-
+
memset(NPCname, '\0', sizeof(NPCname));
-
+
if (!message || !*message || sscanf(message, "%24[^\n]", NPCname) < 1) {
clif->message(fd, msg_txt(1133)); // Please enter a NPC name (usage: @npcoff <NPC_name>).
return false;
}
-
+
if ((nd = npc->name2id(NPCname)) == NULL) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
-
+
npc->unload_duplicates(nd);
npc->unload(nd,true);
npc->read_event_script();
@@ -4246,16 +4238,16 @@ char* txt_time(unsigned int duration)
int days, hours, minutes, seconds;
static char temp1[CHAT_SIZE_MAX];
int tlen = 0;
-
+
memset(temp1, '\0', sizeof(temp1));
-
+
days = duration / (60 * 60 * 24);
duration = duration - (60 * 60 * 24 * days);
hours = duration / (60 * 60);
duration = duration - (60 * 60 * hours);
minutes = duration / 60;
seconds = duration - (60 * minutes);
-
+
if (days == 1)
tlen += sprintf(tlen + temp1, msg_txt(219), days); // %d day
else if (days > 1)
@@ -4272,7 +4264,7 @@ char* txt_time(unsigned int duration)
sprintf(tlen + temp1, msg_txt(225), seconds); // and %d second
else if (seconds > 1)
sprintf(tlen + temp1, msg_txt(226), seconds); // and %d seconds
-
+
return temp1;
}
@@ -4284,19 +4276,19 @@ ACMD(servertime) {
time_t time_server; // variable for number of seconds (used with time() function)
struct tm *datetime; // variable for time in structure ->tm_mday, ->tm_sec, ...
char temp[CHAT_SIZE_MAX];
-
+
memset(temp, '\0', sizeof(temp));
-
+
time(&time_server); // get time in seconds since 1/1/1970
datetime = localtime(&time_server); // convert seconds in structure
// like sprintf, but only for date/time (Sunday, November 02 2003 15:12:52)
strftime(temp, sizeof(temp)-1, msg_txt(230), datetime); // Server time (normal time): %A, %B %d %Y %X.
clif->message(fd, temp);
-
+
if (pc->day_timer_tid != INVALID_TIMER && pc->night_timer_tid != INVALID_TIMER) {
const struct TimerData * timer_data = timer->get(pc->night_timer_tid);
const struct TimerData * timer_data2 = timer->get(pc->day_timer_tid);
-
+
if (map->night_flag == 0) {
sprintf(temp, msg_txt(235), // Game time: The game is actually in daylight for %s.
txt_time((unsigned int)(DIFF_TICK(timer_data->tick,timer->gettick())/1000)));
@@ -4328,7 +4320,7 @@ ACMD(servertime) {
else
clif->message(fd, msg_txt(232)); // Game time: The game is in permanent night.
}
-
+
return true;
}
@@ -4341,7 +4333,7 @@ void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int
const int factor_month = 43200; //30*24*60 = 43200
const int factor_day = 1440; //24*60 = 1440
const int factor_hour = 60;
-
+
*year = jailtime/factor_year;
jailtime -= *year*factor_year;
*month = jailtime/factor_month;
@@ -4351,7 +4343,7 @@ void get_jail_time(int jailtime, int* year, int* month, int* day, int* hour, int
*hour = jailtime/factor_hour;
jailtime -= *hour*factor_hour;
*minute = jailtime;
-
+
*year = *year > 0? *year : 0;
*month = *month > 0? *month : 0;
*day = *day > 0? *day : 0;
@@ -4368,31 +4360,31 @@ ACMD(jail) {
struct map_session_data *pl_sd;
int x, y;
unsigned short m_index;
-
+
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1134)); // Please enter a player name (usage: @jail <char_name>).
return false;
}
-
+
if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
- if (pc_get_group_level(sd) < pc_get_group_level(pl_sd))
- { // you can jail only lower or same GM
+
+ if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) {
+ // you can jail only lower or same GM
clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
-
+
if (pl_sd->sc.data[SC_JAILED])
{
clif->message(fd, msg_txt(118)); // Player warped in jails.
return false;
}
-
+
switch(rnd() % 2) { //Jail Locations
case 0:
m_index = mapindex->name2id(MAP_JAIL);
@@ -4405,7 +4397,7 @@ ACMD(jail) {
y = 75;
break;
}
-
+
//Duration of INT_MAX to specify infinity.
sc_start4(NULL,&pl_sd->bl,SC_JAILED,100,INT_MAX,m_index,x,y,1000);
clif->message(pl_sd->fd, msg_txt(117)); // You have been jailed by a GM.
@@ -4419,31 +4411,31 @@ ACMD(jail) {
*------------------------------------------*/
ACMD(unjail) {
struct map_session_data *pl_sd;
-
+
memset(atcmd_player_name, '\0', sizeof(atcmd_player_name));
-
+
if (!message || !*message || sscanf(message, "%23[^\n]", atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1135)); // Please enter a player name (usage: @unjail/@discharge <char_name>).
return false;
}
-
+
if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if (pc_get_group_level(sd) < pc_get_group_level(pl_sd)) { // you can jail only lower or same GM
-
+
clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
-
+
if (!pl_sd->sc.data[SC_JAILED])
{
clif->message(fd, msg_txt(119)); // This player is not in jails.
return false;
}
-
+
//Reset jail time to 1 sec.
sc_start(NULL,&pl_sd->bl,SC_JAILED,100,1,1000);
clif->message(pl_sd->fd, msg_txt(120)); // A GM has discharged you from jail.
@@ -4457,14 +4449,14 @@ ACMD(jailfor) {
char * modif_p;
int jailtime = 0,x,y;
short m_index = 0;
-
+
if (!message || !*message || sscanf(message, "%255s %23[^\n]",atcmd_output,atcmd_player_name) < 2) {
- clif->message(fd, msg_txt(400)); //Usage: @jailfor <time> <character name>
+ clif->message(fd, msg_txt(400)); //Usage: @jailfor <time> <character name>
return false;
}
-
+
atcmd_output[sizeof(atcmd_output)-1] = '\0';
-
+
modif_p = atcmd_output;
year = month = day = hour = minute = 0;
while (modif_p[0] != '\0') {
@@ -4499,33 +4491,32 @@ ACMD(jailfor) {
}
}
}
-
+
if (year == 0 && month == 0 && day == 0 && hour == 0 && minute == 0) {
clif->message(fd, msg_txt(1136)); // Invalid time for jail command.
return false;
}
-
+
if ((pl_sd = map->nick2sd(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if (pc_get_group_level(pl_sd) > pc_get_group_level(sd)) {
clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
-
- jailtime = year*12*30*24*60 + month*30*24*60 + day*24*60 + hour*60 + minute; //In minutes
-
+
+ jailtime = year*12*30*24*60 + month*30*24*60 + day*24*60 + hour*60 + minute; //In minutes
+
if(jailtime==0) {
clif->message(fd, msg_txt(1136)); // Invalid time for jail command.
return false;
}
-
+
//Added by Coltaro
- if(pl_sd->sc.data[SC_JAILED] &&
- pl_sd->sc.data[SC_JAILED]->val1 != INT_MAX)
- { //Update the player's jail time
+ if (pl_sd->sc.data[SC_JAILED] && pl_sd->sc.data[SC_JAILED]->val1 != INT_MAX) {
+ //Update the player's jail time
jailtime += pl_sd->sc.data[SC_JAILED]->val1;
if (jailtime <= 0) {
jailtime = 0;
@@ -4534,15 +4525,15 @@ ACMD(jailfor) {
} else {
atcommand->get_jail_time(jailtime,&year,&month,&day,&hour,&minute);
sprintf(atcmd_output,msg_txt(402),msg_txt(1137),year,month,day,hour,minute); //%s in jail for %d years, %d months, %d days, %d hours and %d minutes
- clif->message(pl_sd->fd, atcmd_output);
+ clif->message(pl_sd->fd, atcmd_output);
sprintf(atcmd_output,msg_txt(402),msg_txt(1138),year,month,day,hour,minute); //This player is now in jail for %d years, %d months, %d days, %d hours and %d minutes
- clif->message(fd, atcmd_output);
+ clif->message(fd, atcmd_output);
}
} else if (jailtime < 0) {
clif->message(fd, msg_txt(1136));
return false;
}
-
+
//Jail locations, add more as you wish.
switch(rnd()%2)
{
@@ -4555,7 +4546,7 @@ ACMD(jailfor) {
x = 24; y = 75;
break;
}
-
+
sc_start4(NULL,&pl_sd->bl,SC_JAILED,100,jailtime,m_index,x,y,jailtime?60000:1000); //jailtime = 0: Time was reset to 0. Wait 1 second to warp player out (since it's done in status->change_timer).
return true;
}
@@ -4565,28 +4556,28 @@ ACMD(jailfor) {
ACMD(jailtime)
{
int year, month, day, hour, minute;
-
+
if (!sd->sc.data[SC_JAILED]) {
clif->message(fd, msg_txt(1139)); // You are not in jail.
return false;
}
-
+
if (sd->sc.data[SC_JAILED]->val1 == INT_MAX) {
clif->message(fd, msg_txt(1140)); // You have been jailed indefinitely.
return true;
}
-
+
if (sd->sc.data[SC_JAILED]->val1 <= 0) { // Was not jailed with @jailfor (maybe @jail? or warped there? or got recalled?)
clif->message(fd, msg_txt(1141)); // You have been jailed for an unknown amount of time.
return false;
}
-
+
//Get remaining jail time
atcommand->get_jail_time(sd->sc.data[SC_JAILED]->val1,&year,&month,&day,&hour,&minute);
sprintf(atcmd_output,msg_txt(402),msg_txt(1142),year,month,day,hour,minute); // You will remain in jail for %d years, %d months, %d days, %d hours and %d minutes
-
+
clif->message(fd, atcmd_output);
-
+
return true;
}
@@ -4596,17 +4587,18 @@ ACMD(jailtime)
ACMD(disguise)
{
int id = 0;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1143)); // Please enter a Monster/NPC name/ID (usage: @disguise <name/ID>).
return false;
}
-
- if ((id = atoi(message)) > 0)
- { //Acquired an ID
+
+ if ((id = atoi(message)) > 0) {
+ //Acquired an ID
if (!mob->db_checkid(id) && !npcdb_checkid(id))
id = 0; //Invalid id for either mobs or npcs.
- } else { //Acquired a Name
+ } else {
+ //Acquired a Name
if ((id = mob->db_searchname(message)) == 0)
{
struct npc_data* nd = npc->name2id(message);
@@ -4614,19 +4606,18 @@ ACMD(disguise)
id = nd->class_;
}
}
-
+
if (id == 0)
{
- clif->message(fd, msg_txt(123)); // Invalid Monster/NPC name/ID specified.
+ clif->message(fd, msg_txt(123)); // Invalid Monster/NPC name/ID specified.
return false;
}
-
- if(pc_isriding(sd))
- {
+
+ if (pc_hasmount(sd)) {
clif->message(fd, msg_txt(1144)); // Character cannot be disguised while mounted.
return false;
}
-
+
if(sd->sc.data[SC_MONSTER_TRANSFORM])
{
clif->message(fd, msg_txt(1487)); // Character cannot be disguised while in monster form.
@@ -4635,7 +4626,7 @@ ACMD(disguise)
pc->disguise(sd, id);
clif->message(fd, msg_txt(122)); // Disguise applied.
-
+
return true;
}
@@ -4647,25 +4638,25 @@ ACMD(disguiseall)
int mob_id=0;
struct map_session_data *pl_sd;
struct s_mapiterator* iter;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1145)); // Please enter a Monster/NPC name/ID (usage: @disguiseall <name/ID>).
return false;
}
-
+
if ((mob_id = mob->db_searchname(message)) == 0) // check name first (to avoid possible name begining by a number)
mob_id = atoi(message);
-
+
if (!mob->db_checkid(mob_id) && !npcdb_checkid(mob_id)) { //if mob or npc...
clif->message(fd, msg_txt(123)); // Monster/NPC name/id not found.
return false;
}
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
pc->disguise(pl_sd, mob_id);
mapit->free(iter);
-
+
clif->message(fd, msg_txt(122)); // Disguise applied.
return true;
}
@@ -4679,15 +4670,15 @@ ACMD(disguiseguild)
char monster[NAME_LENGTH], guild_name[NAME_LENGTH];
struct map_session_data *pl_sd;
struct guild *g;
-
+
memset(monster, '\0', sizeof(monster));
memset(guild_name, '\0', sizeof(guild_name));
-
+
if( !message || !*message || sscanf(message, "%23[^,], %23[^\r\n]", monster, guild_name) < 2 ) {
clif->message(fd, msg_txt(1146)); // Please enter a mob name/ID and guild name/ID (usage: @disguiseguild <mob name/ID>, <guild name/ID>).
return false;
}
-
+
if( (id = atoi(monster)) > 0 ) {
if( !mob->db_checkid(id) && !npcdb_checkid(id) )
id = 0;
@@ -4698,21 +4689,21 @@ ACMD(disguiseguild)
id = nd->class_;
}
}
-
+
if( id == 0 ) {
- clif->message(fd, msg_txt(123)); // Monster/NPC name/id hasn't been found.
+ clif->message(fd, msg_txt(123)); // Monster/NPC name/id hasn't been found.
return false;
}
-
+
if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(guild_name))) == NULL ) {
clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online.
return false;
}
-
- for( i = 0; i < g->max_member; i++ )
- if( (pl_sd = g->member[i].sd) && !pc_isriding(pl_sd) )
+
+ 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.
return true;
}
@@ -4730,7 +4721,7 @@ ACMD(undisguise)
clif->message(fd, msg_txt(125)); // You're not disguised.
return false;
}
-
+
return true;
}
@@ -4740,15 +4731,15 @@ ACMD(undisguise)
ACMD(undisguiseall) {
struct map_session_data *pl_sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) )
if( pl_sd->disguise != -1 )
pc->disguise(pl_sd, -1);
mapit->free(iter);
-
+
clif->message(fd, msg_txt(124)); // Disguise removed.
-
+
return true;
}
@@ -4761,25 +4752,25 @@ ACMD(undisguiseguild)
struct map_session_data *pl_sd;
struct guild *g;
int i;
-
+
memset(guild_name, '\0', sizeof(guild_name));
-
+
if(!message || !*message || sscanf(message, "%23[^\n]", guild_name) < 1) {
clif->message(fd, msg_txt(1147)); // Please enter guild name/ID (usage: @undisguiseguild <guild name/ID>).
return false;
}
-
+
if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(message))) == NULL ) {
clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online.
return false;
}
-
+
for(i = 0; i < g->max_member; i++)
if( (pl_sd = g->member[i].sd) && pl_sd->disguise != -1 )
pc->disguise(pl_sd, -1);
-
+
clif->message(fd, msg_txt(124)); // Disguise removed.
-
+
return true;
}
@@ -4792,15 +4783,15 @@ ACMD(exp)
double nextb, nextj;
memset(output, '\0', sizeof(output));
-
+
nextb = pc->nextbaseexp(sd);
if (nextb)
nextb = sd->status.base_exp*100.0/nextb;
-
+
nextj = pc->nextjobexp(sd);
if (nextj)
nextj = sd->status.job_exp*100.0/nextj;
-
+
sprintf(output, msg_txt(1148), sd->status.base_level, nextb, sd->status.job_level, nextj); // Base Level: %d (%.3f%%) | Job Level: %d (%.3f%%)
clif->message(fd, output);
return true;
@@ -4812,17 +4803,16 @@ ACMD(exp)
*------------------------------------------*/
ACMD(broadcast)
{
-
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1149)); // Please enter a message (usage: @broadcast <message>).
return false;
}
-
+
sprintf(atcmd_output, "%s: %s", sd->status.name, message);
intif->broadcast(atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT);
-
+
return true;
}
@@ -4832,16 +4822,16 @@ ACMD(broadcast)
ACMD(localbroadcast)
{
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1150)); // Please enter a message (usage: @localbroadcast <message>).
return false;
}
-
+
sprintf(atcmd_output, "%s: %s", sd->status.name, message);
-
+
clif->broadcast(&sd->bl, atcmd_output, strlen(atcmd_output) + 1, BC_DEFAULT, ALL_SAMEMAP);
-
+
return true;
}
@@ -4852,15 +4842,15 @@ ACMD(email)
{
char actual_email[100];
char new_email[100];
-
+
memset(actual_email, '\0', sizeof(actual_email));
memset(new_email, '\0', sizeof(new_email));
-
+
if (!message || !*message || sscanf(message, "%99s %99s", actual_email, new_email) < 2) {
clif->message(fd, msg_txt(1151)); // Please enter two e-mail addresses (usage: @email <current@email> <new@email>).
return false;
}
-
+
if (e_mail_check(actual_email) == 0) {
clif->message(fd, msg_txt(144)); // Invalid e-mail. If your email hasn't been set, use a@a.com.
return false;
@@ -4874,7 +4864,7 @@ ACMD(email)
clif->message(fd, msg_txt(147)); // New e-mail must be different from the current e-mail address.
return false;
}
-
+
chrif->changeemail(sd->status.account_id, actual_email, new_email);
clif->message(fd, msg_txt(148)); // Information sended to login-server via char-server.
return true;
@@ -4886,12 +4876,12 @@ ACMD(email)
ACMD(effect)
{
int type = 0, flag = 0;
-
+
if (!message || !*message || sscanf(message, "%d", &type) < 1) {
clif->message(fd, msg_txt(1152)); // Please enter an effect number (usage: @effect <effect number>).
return false;
}
-
+
clif->specialeffect(&sd->bl, type, (send_target)flag);
clif->message(fd, msg_txt(229)); // Your effect has changed.
return true;
@@ -4904,7 +4894,7 @@ ACMD(effect)
ACMD(killer)
{
sd->state.killer = !sd->state.killer;
-
+
if(sd->state.killer)
clif->message(fd, msg_txt(241));
else {
@@ -4920,7 +4910,7 @@ ACMD(killer)
*------------------------------------------*/
ACMD(killable) {
sd->state.killable = !sd->state.killable;
-
+
if(sd->state.killable)
clif->message(fd, msg_txt(242));
else {
@@ -4959,29 +4949,29 @@ ACMD(npcmove) {
struct npc_data *nd = 0;
memset(atcmd_player_name, '\0', sizeof atcmd_player_name);
-
+
if (!message || !*message || sscanf(message, "%d %d %23[^\n]", &x, &y, atcmd_player_name) < 3) {
clif->message(fd, msg_txt(1153)); // Usage: @npcmove <X> <Y> <npc_name>
return false;
}
-
+
if ((nd = npc->name2id(atcmd_player_name)) == NULL) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist.
return false;
}
-
+
if ((m=nd->bl.m) < 0 || nd->bl.prev == NULL) {
clif->message(fd, msg_txt(1154)); // NPC is not in this map.
- return false; //Not on a map.
+ return false; //Not on a map.
}
-
+
x = cap_value(x, 0, map->list[m].xs-1);
y = cap_value(y, 0, map->list[m].ys-1);
map->foreachinrange(clif->outsight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
map->moveblock(&nd->bl, x, y, timer->gettick());
map->foreachinrange(clif->insight, &nd->bl, AREA_SIZE, BL_PC, &nd->bl);
clif->message(fd, msg_txt(1155)); // NPC moved.
-
+
return true;
}
@@ -4995,14 +4985,14 @@ ACMD(addwarp)
int x,y;
unsigned short m;
struct npc_data* nd;
-
+
memset(warpname, '\0', sizeof(warpname));
-
+
if (!message || !*message || sscanf(message, "%31s %d %d %23[^\n]", mapname, &x, &y, warpname) < 4) {
clif->message(fd, msg_txt(1156)); // Usage: @addwarp <mapname> <X> <Y> <npc name>
return false;
}
-
+
m = mapindex->name2id(mapname);
if( m == 0 )
{
@@ -5010,11 +5000,11 @@ ACMD(addwarp)
clif->message(fd, atcmd_output);
return false;
}
-
+
nd = npc->add_warp(warpname, sd->bl.m, sd->bl.x, sd->bl.y, 2, 2, m, x, y);
if( nd == NULL )
return false;
-
+
sprintf(atcmd_output, msg_txt(1158), nd->exname); // New warp NPC '%s' created.
clif->message(fd, atcmd_output);
return true;
@@ -5026,22 +5016,21 @@ ACMD(addwarp)
*------------------------------------------*/
ACMD(follow) {
struct map_session_data *pl_sd = NULL;
-
+
if (!message || !*message) {
if (sd->followtarget == -1)
return false;
-
pc->stop_following (sd);
clif->message(fd, msg_txt(1159)); // Follow mode OFF.
return true;
}
-
+
if ( (pl_sd = map->nick2sd((char *)message)) == NULL )
{
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if (sd->followtarget == pl_sd->bl.id) {
pc->stop_following (sd);
clif->message(fd, msg_txt(1159)); // Follow mode OFF.
@@ -5049,7 +5038,7 @@ ACMD(follow) {
pc->follow(sd, pl_sd->bl.id);
clif->message(fd, msg_txt(1160)); // Follow mode ON.
}
-
+
return true;
}
@@ -5079,15 +5068,15 @@ ACMD(dropall)
ACMD(storeall)
{
int i;
-
- if (sd->state.storage_flag != 1)
- { //Open storage.
+
+ if (sd->state.storage_flag != 1) {
+ //Open storage.
if( storage->open(sd) == 1 ) {
clif->message(fd, msg_txt(1161)); // You currently cannot open your storage.
return false;
}
}
-
+
for (i = 0; i < MAX_INVENTORY; i++) {
if (sd->status.inventory[i].amount) {
if(sd->status.inventory[i].equip != 0)
@@ -5096,7 +5085,7 @@ ACMD(storeall)
}
}
storage->close(sd);
-
+
clif->message(fd, msg_txt(1162)); // All items stored.
return true;
}
@@ -5104,18 +5093,18 @@ ACMD(storeall)
ACMD(clearstorage)
{
int i, j;
-
+
if (sd->state.storage_flag == 1) {
clif->message(fd, msg_txt(250));
return false;
}
-
+
j = sd->status.storage.storage_amount;
for (i = 0; i < j; ++i) {
storage->delitem(sd, i, sd->status.storage.items[i].amount);
}
storage->close(sd);
-
+
clif->message(fd, msg_txt(1394)); // Your storage was cleaned.
return true;
}
@@ -5125,29 +5114,29 @@ ACMD(cleargstorage)
int i, j;
struct guild *g;
struct guild_storage *guild_storage;
-
+
g = sd->guild;
-
+
if (g == NULL) {
clif->message(fd, msg_txt(43));
return false;
}
-
+
if (sd->state.storage_flag == 1) {
clif->message(fd, msg_txt(250));
return false;
}
-
+
if (sd->state.storage_flag == 2) {
clif->message(fd, msg_txt(251));
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;
}
-
+
j = guild_storage->storage_amount;
guild_storage->lock = 1; // Lock @gstorage: do not allow any item to be retrieved or stored from any guild member
for (i = 0; i < j; ++i) {
@@ -5155,7 +5144,7 @@ ACMD(cleargstorage)
}
gstorage->close(sd);
guild_storage->lock = 0; // Cleaning done, release lock
-
+
clif->message(fd, msg_txt(1395)); // Your guild storage was cleaned.
return true;
}
@@ -5163,24 +5152,24 @@ ACMD(cleargstorage)
ACMD(clearcart)
{
int i;
-
+
if (pc_iscarton(sd) == 0) {
clif->message(fd, msg_txt(1396)); // You do not have a cart to be cleaned.
return false;
}
-
+
if( sd->state.vending == 1 ) {
clif->message(fd, msg_txt(548)); // You can't clean a cart while vending!
- return false;
- }
-
+ return false;
+ }
+
for( i = 0; i < MAX_CART; i++ )
if(sd->status.cart[i].nameid > 0)
pc->cart_delitem(sd, i, sd->status.cart[i].amount, 1, LOG_TYPE_OTHER);
-
+
clif->clearcart(fd);
clif->updatestatus(sd,SP_CARTINFO);
-
+
clif->message(fd, msg_txt(1397)); // Your cart was cleaned.
return true;
}
@@ -5198,16 +5187,16 @@ ACMD(skillid) {
DBKey key;
DBData *data;
char partials[MAX_SKILLID_PARTIAL_RESULTS][MAX_SKILLID_PARTIAL_RESULTS_LEN];
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1163)); // Please enter a skill name to look up (usage: @skillid <skill name>).
return false;
}
-
+
skillen = strlen(message);
-
+
iter = db_iterator(skill->name2id_db);
-
+
for( data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key) ) {
idx = skill->get_index(DB->data2i(data));
if (strnicmp(key.str, message, skillen) == 0 || strnicmp(skill->db[idx].desc, message, skillen) == 0) {
@@ -5217,18 +5206,18 @@ ACMD(skillid) {
snprintf(partials[found++], MAX_SKILLID_PARTIAL_RESULTS_LEN, msg_txt(1164), DB->data2i(data), skill->db[idx].desc, key.str);
}
}
-
+
dbi_destroy(iter);
-
+
if( found ) {
sprintf(atcmd_output, msg_txt(1398), found); // -- Displaying first %d partial matches
clif->message(fd, atcmd_output);
}
-
+
for(i = 0; i < found; i++) { /* partials */
clif->message(fd, partials[i]);
}
-
+
return true;
}
@@ -5242,38 +5231,38 @@ ACMD(useskill) {
uint16 skill_id;
uint16 skill_lv;
char target[100];
-
+
if(!message || !*message || sscanf(message, "%hu %hu %23[^\n]", &skill_id, &skill_lv, target) != 3) {
clif->message(fd, msg_txt(1165)); // Usage: @useskill <skill ID> <skill level> <target>
return false;
}
-
+
if(!strcmp(target,"self"))
pl_sd = sd; //quick keyword
else if ( (pl_sd = map->nick2sd(target)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
clif->message(fd, msg_txt(81)); // Your GM level don't authorized you to do this action on this player.
return false;
}
-
+
if (skill_id >= HM_SKILLBASE && skill_id < HM_SKILLBASE+MAX_HOMUNSKILL
&& sd->hd && homun_alive(sd->hd)) // (If used with @useskill, put the homunc as dest)
bl = &sd->hd->bl;
else
bl = &sd->bl;
-
+
pc->delinvincibletimer(sd);
-
+
if (skill->get_inf(skill_id)&INF_GROUND_SKILL)
unit->skilluse_pos(bl, pl_sd->bl.x, pl_sd->bl.y, skill_id, skill_lv);
else
unit->skilluse_id(bl, pl_sd->bl.id, skill_id, skill_lv);
-
+
return true;
}
@@ -5287,7 +5276,7 @@ ACMD(displayskill) {
int64 tick;
uint16 skill_id;
uint16 skill_lv = 1;
-
+
if (!message || !*message || sscanf(message, "%hu %hu", &skill_id, &skill_lv) < 1) {
clif->message(fd, msg_txt(1166)); // Usage: @displayskill <skill ID> {<skill level>}
return false;
@@ -5310,32 +5299,32 @@ ACMD(skilltree) {
int meets, j, c=0;
char target[NAME_LENGTH];
struct skill_tree_entry *ent;
-
+
if(!message || !*message || sscanf(message, "%hu %23[^\r\n]", &skill_id, target) != 2) {
clif->message(fd, msg_txt(1167)); // Usage: @skilltree <skill ID> <target>
return false;
}
-
+
if ( (pl_sd = map->nick2sd(target)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
c = pc->calc_skilltree_normalize_job(pl_sd);
c = pc->mapid2jobid(c, pl_sd->status.sex);
-
+
sprintf(atcmd_output, msg_txt(1168), pc->job_name(c), pc->checkskill(pl_sd, NV_BASIC)); // Player is using %s skill tree (%d basic points).
clif->message(fd, atcmd_output);
-
+
ARR_FIND( 0, MAX_SKILL_TREE, j, pc->skill_tree[c][j].id == 0 || pc->skill_tree[c][j].id == skill_id );
if( j == MAX_SKILL_TREE || pc->skill_tree[c][j].id == 0 )
{
clif->message(fd, msg_txt(1169)); // The player cannot use that skill.
return false;
}
-
+
ent = &pc->skill_tree[c][j];
-
+
meets = 1;
for(j=0;j<MAX_PC_SKILL_REQUIRE;j++)
{
@@ -5349,7 +5338,7 @@ ACMD(skilltree) {
if (meets == 1) {
clif->message(fd, msg_txt(1171)); // The player meets all the requirements for that skill.
}
-
+
return true;
}
@@ -5358,14 +5347,14 @@ void getring(struct map_session_data* sd) {
int flag, item_id;
struct item item_tmp;
item_id = (sd->status.sex) ? WEDDING_RING_M : WEDDING_RING_F;
-
+
memset(&item_tmp, 0, sizeof(item_tmp));
item_tmp.nameid = item_id;
item_tmp.identify = 1;
item_tmp.card[0] = 255;
item_tmp.card[2] = sd->status.partner_id;
item_tmp.card[3] = sd->status.partner_id >> 16;
-
+
if((flag = pc->additem(sd,&item_tmp,1,LOG_TYPE_COMMAND))) {
clif->additem(sd,0,0,flag);
map->addflooritem(&item_tmp,1,sd->bl.m,sd->bl.x,sd->bl.y,0,0,0,0);
@@ -5379,17 +5368,17 @@ void getring(struct map_session_data* sd) {
ACMD(marry) {
struct map_session_data *pl_sd = NULL;
char player_name[NAME_LENGTH] = "";
-
+
if (!message || !*message || sscanf(message, "%23s", player_name) != 1) {
clif->message(fd, msg_txt(1172)); // Usage: @marry <char name>
return false;
}
-
+
if ((pl_sd = map->nick2sd(player_name)) == NULL) {
clif->message(fd, msg_txt(3));
return false;
}
-
+
if (pc->marriage(sd, pl_sd) == 0) {
clif->message(fd, msg_txt(1173)); // They are married... wish them well.
clif->wedding_effect(&pl_sd->bl); //wedding effect and music [Lupus]
@@ -5397,7 +5386,7 @@ ACMD(marry) {
getring(pl_sd);
return true;
}
-
+
clif->message(fd, msg_txt(1174)); // The two cannot wed because one is either a baby or already married.
return false;
}
@@ -5413,7 +5402,7 @@ ACMD(divorce)
clif->message(fd, atcmd_output);
return false;
}
-
+
sprintf(atcmd_output, msg_txt(1176), sd->status.name); // '%s' and his/her partner are now divorced.
clif->message(fd, atcmd_output);
return true;
@@ -5426,7 +5415,7 @@ ACMD(changelook)
{
int i, j = 0, k = 0;
int pos[7] = { LOOK_HEAD_TOP,LOOK_HEAD_MID,LOOK_HEAD_BOTTOM,LOOK_WEAPON,LOOK_SHIELD,LOOK_SHOES,LOOK_ROBE };
-
+
if((i = sscanf(message, "%d %d", &j, &k)) < 1) {
clif->message(fd, msg_txt(1177)); // Usage: @changelook {<position>} <view id>
clif->message(fd, msg_txt(1178)); // Position: 1-Top 2-Middle 3-Bottom 4-Weapon 5-Shield 6-Shoes 7-Robe
@@ -5435,13 +5424,13 @@ ACMD(changelook)
if (j < 1 || j > 7)
j = 1;
j = pos[j - 1];
- } else if( i == 1 ) { // position not defined, use HEAD_TOP as default
- k = j; // swap
+ } else if( i == 1 ) { // position not defined, use HEAD_TOP as default
+ k = j; // swap
j = LOOK_HEAD_TOP;
}
-
+
clif->changelook(&sd->bl,j,k);
-
+
return true;
}
@@ -5449,44 +5438,42 @@ ACMD(changelook)
* @autotrade by durf [Lupus] [Paradox924X]
* Turns on/off Autotrade for a specific player
*------------------------------------------*/
-ACMD(autotrade) {
-
+ACMD(autotrade)
+{
if( map->list[sd->bl.m].flag.autotrade != battle_config.autotrade_mapflag ) {
clif->message(fd, msg_txt(1179)); // Autotrade is not allowed in this map.
return false;
}
-
+
if( pc_isdead(sd) ) {
clif->message(fd, msg_txt(1180)); // You cannot autotrade when dead.
return false;
}
-
+
if( !sd->state.vending && !sd->state.buyingstore ) { //check if player is vending or buying
clif->message(fd, msg_txt(549)); // "You should have a shop open in order to use @autotrade."
return false;
}
-
+
sd->state.autotrade = 1;
if( battle_config.at_timeout ) {
int timeout = atoi(message);
- status->change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0, ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, 0);
+ status->change_start(NULL,&sd->bl, SC_AUTOTRADE, 10000, 0, 0, 0, 0,
+ ((timeout > 0) ? min(timeout,battle_config.at_timeout) : battle_config.at_timeout) * 60000, SCFLAG_NONE);
}
+ clif->chsys_quit(sd);
+
+ clif->authfail_fd(sd->fd, 15);
+
/* currently standalone is not supporting buyingstores, so we rely on the previous method */
- if( sd->state.buyingstore ) {
- clif->authfail_fd(fd, 15);
+ if( sd->state.buyingstore )
return true;
- }
-
- clif->chsys_quit(sd);
-
- clif->authfail_fd(sd->fd, 15);
-
-
#ifdef AUTOTRADE_PERSISTENCY
+ sd->state.autotrade = 2;/** state will enter pre-save, we use it to rule out some criterias **/
pc->autotrade_prepare(sd);
-
+
return false;/* we fail to not cause it to proceed on is_atcommand */
#else
return true;
@@ -5500,27 +5487,27 @@ ACMD(autotrade) {
ACMD(changegm) {
struct guild *g;
struct map_session_data *pl_sd;
-
+
if (sd->status.guild_id == 0 || (g = sd->guild) == NULL || strcmp(g->master,sd->status.name)) {
clif->message(fd, msg_txt(1181)); // You need to be a Guild Master to use this command.
return false;
}
-
+
if( map->list[sd->bl.m].flag.guildlock || map->list[sd->bl.m].flag.gvg_castle ) {
clif->message(fd, msg_txt(1182)); // You cannot change guild leaders in this map.
return false;
}
-
+
if( !message[0] ) {
clif->message(fd, msg_txt(1183)); // Usage: @changegm <guild_member_name>
return false;
}
-
+
if((pl_sd=map->nick2sd((char *) message)) == NULL || pl_sd->status.guild_id != sd->status.guild_id) {
clif->message(fd, msg_txt(1184)); // Target character must be online and be a guild member.
return false;
}
-
+
guild->gm_change(sd->status.guild_id, pl_sd);
return true;
}
@@ -5530,12 +5517,12 @@ ACMD(changegm) {
* Changes the leader of a party.
*------------------------------------------*/
ACMD(changeleader) {
-
+
if( !message[0] ) {
clif->message(fd, msg_txt(1185)); // Usage: @changeleader <party_member_name>
return false;
}
-
+
if (party->changeleader(sd, map->nick2sd((char *) message)))
return true;
return false;
@@ -5550,37 +5537,37 @@ ACMD(partyoption)
struct party_data *p;
int mi, option;
char w1[16], w2[16];
-
+
if (sd->status.party_id == 0 || (p = party->search(sd->status.party_id)) == NULL)
{
clif->message(fd, msg_txt(282));
return false;
}
-
+
ARR_FIND( 0, MAX_PARTY, mi, p->data[mi].sd == sd );
if (mi == MAX_PARTY)
return false; //Shouldn't happen
-
+
if (!p->party.member[mi].leader)
{
clif->message(fd, msg_txt(282));
return false;
}
-
+
if(!message || !*message || sscanf(message, "%15s %15s", w1, w2) < 2)
{
clif->message(fd, msg_txt(1186)); // Usage: @partyoption <pickup share: yes/no> <item distribution: yes/no>
return false;
}
-
+
option = (config_switch(w1)?1:0)|(config_switch(w2)?2:0);
-
+
//Change item share type.
if (option != p->party.item)
party->changeoption(sd, p->party.exp, option);
else
clif->message(fd, msg_txt(286));
-
+
return true;
}
@@ -5606,14 +5593,14 @@ ACMD(autoloot)
}
if (rate < 0) rate = 0;
if (rate > 10000) rate = 10000;
-
+
sd->state.autoloot = rate;
if (sd->state.autoloot) {
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1187),((double)sd->state.autoloot)/100.); // Autolooting items with drop rates of %0.02f%% and below.
clif->message(fd, atcmd_output);
}else
clif->message(fd, msg_txt(1188)); // Autoloot is now off.
-
+
return true;
}
@@ -5625,7 +5612,7 @@ ACMD(autolootitem)
struct item_data *item_data = NULL;
int i;
int action = 3; // 1=add, 2=remove, 3=help+list (default), 4=reset
-
+
if (message && *message) {
if (message[0] == '+') {
message++;
@@ -5649,7 +5636,7 @@ ACMD(autolootitem)
}
}
}
-
+
switch(action) {
case 1:
ARR_FIND(0, AUTOLOOTITEM_SIZE, i, sd->state.autolootid[i] == item_data->nameid);
@@ -5813,8 +5800,8 @@ ACMD(autoloottype) {
/*==========================================
* It is made to snow.
*------------------------------------------*/
-ACMD(snow) {
-
+ACMD(snow)
+{
if (map->list[sd->bl.m].flag.snow) {
map->list[sd->bl.m].flag.snow=0;
clif->weather(sd->bl.m);
@@ -5824,7 +5811,7 @@ ACMD(snow) {
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1204)); // It has started to snow.
}
-
+
return true;
}
@@ -5859,7 +5846,7 @@ ACMD(clouds) {
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1208)); // Clouds appear.
}
-
+
return true;
}
@@ -5877,7 +5864,7 @@ ACMD(clouds2) {
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1210)); // Alternative clouds appear.
}
-
+
return true;
}
@@ -5912,7 +5899,7 @@ ACMD(leaves) {
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1214)); // Fallen leaves fall.
}
-
+
return true;
}
@@ -5930,15 +5917,15 @@ ACMD(fireworks) {
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(1216)); // Fireworks have launched.
}
-
+
return true;
}
/*==========================================
* Clearing Weather Effects by Dexity
*------------------------------------------*/
-ACMD(clearweather) {
-
+ACMD(clearweather)
+{
map->list[sd->bl.m].flag.snow=0;
map->list[sd->bl.m].flag.sakura=0;
map->list[sd->bl.m].flag.clouds=0;
@@ -5948,7 +5935,7 @@ ACMD(clearweather) {
map->list[sd->bl.m].flag.leaves=0;
clif->weather(sd->bl.m);
clif->message(fd, msg_txt(291)); // "Weather effects will disappear after teleporting or refreshing."
-
+
return true;
}
@@ -5958,24 +5945,24 @@ ACMD(clearweather) {
ACMD(sound)
{
char sound_file[100];
-
+
memset(sound_file, '\0', sizeof(sound_file));
-
+
if(!message || !*message || sscanf(message, "%99[^\n]", sound_file) < 1) {
clif->message(fd, msg_txt(1217)); // Please enter a sound filename (usage: @sound <filename>).
return false;
}
-
+
if(strstr(sound_file, ".wav") == NULL)
strcat(sound_file, ".wav");
-
+
clif->soundeffectall(&sd->bl, sound_file, 0, AREA);
-
+
return true;
}
/*==========================================
- * MOB Search
+ * MOB Search
*------------------------------------------*/
ACMD(mobsearch)
{
@@ -5983,12 +5970,12 @@ ACMD(mobsearch)
int mob_id;
int number = 0;
struct s_mapiterator* it;
-
+
if (!message || !*message || sscanf(message, "%99[^\n]", mob_name) < 1) {
clif->message(fd, msg_txt(1218)); // Please enter a monster name (usage: @mobsearch <monster name>).
return false;
}
-
+
if ((mob_id = atoi(mob_name)) == 0)
mob_id = mob->db_searchname(mob_name);
if(mob_id > 0 && mob->db_checkid(mob_id) == 0){
@@ -5997,24 +5984,24 @@ ACMD(mobsearch)
return false;
}
if(mob_id == atoi(mob_name) && mob->db(mob_id)->jname)
- strcpy(mob_name,mob->db(mob_id)->jname); // --ja--
- // strcpy(mob_name,mob_db(mob_id)->name); // --en--
-
+ strcpy(mob_name,mob->db(mob_id)->jname); // --ja--
+ //strcpy(mob_name,mob_db(mob_id)->name); // --en--
+
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1220), mob_name, mapindex_id2name(sd->mapindex)); // Mob Search... %s %s
clif->message(fd, atcmd_output);
-
+
it = mapit_geteachmob();
for(;;)
{
TBL_MOB* md = (TBL_MOB*)mapit->next(it);
if( md == NULL )
break;// no more mobs
-
+
if( md->bl.m != sd->bl.m )
continue;
if( mob_id != -1 && md->class_ != mob_id )
continue;
-
+
++number;
if( md->spawn_timer == INVALID_TIMER )
snprintf(atcmd_output, sizeof(atcmd_output), "%2d[%3d:%3d] %s", number, md->bl.x, md->bl.y, md->name);
@@ -6023,7 +6010,7 @@ ACMD(mobsearch)
clif->message(fd, atcmd_output);
}
mapit->free(it);
-
+
return true;
}
@@ -6034,7 +6021,7 @@ ACMD(mobsearch)
int atcommand_cleanfloor_sub(struct block_list *bl, va_list ap) {
nullpo_ret(bl);
map->clearflooritem(bl);
-
+
return 0;
}
@@ -6046,7 +6033,7 @@ ACMD(cleanmap) {
ACMD(cleanarea) {
int x0 = 0, y0 = 0, x1 = 0, y1 = 0;
-
+
if (!message || !*message || sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) < 1) {
map->foreachinrange(atcommand->cleanfloor_sub, &sd->bl, AREA_SIZE * 2, BL_ITEM);
} else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 1) {
@@ -6054,7 +6041,7 @@ ACMD(cleanarea) {
} else if (sscanf(message, "%d %d %d %d", &x0, &y0, &x1, &y1) == 4) {
map->foreachinarea(atcommand->cleanfloor_sub, sd->bl.m, x0, y0, x1, y1, BL_ITEM);
}
-
+
clif->message(fd, msg_txt(1221)); // All dropped items have been cleaned up.
return true;
}
@@ -6069,12 +6056,12 @@ ACMD(npctalk)
struct npc_data *nd;
bool ifcolor=(*(info->command + 7) != 'c' && *(info->command + 7) != 'C')?0:1;
unsigned int color = 0;
-
+
if (sd->sc.count && //no "chatting" while muted.
(sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
-
+
if(!ifcolor) {
if (!message || !*message || sscanf(message, "%23[^,], %99[^\n]", name, mes) < 2) {
clif->message(fd, msg_txt(1222)); // Please enter the correct parameters (usage: @npctalk <npc name>, <message>).
@@ -6087,18 +6074,18 @@ ACMD(npctalk)
return false;
}
}
-
+
if (!(nd = npc->name2id(name))) {
clif->message(fd, msg_txt(111)); // This NPC doesn't exist
return false;
}
-
+
strtok(name, "#"); // discard extra name identifier if present
snprintf(temp, sizeof(temp), "%s : %s", name, mes);
-
+
if(ifcolor) clif->messagecolor(&nd->bl,color,temp);
else clif->disp_overhead(&nd->bl, temp);
-
+
return true;
}
@@ -6106,29 +6093,29 @@ ACMD(pettalk)
{
char mes[100],temp[100];
struct pet_data *pd;
-
+
if ( battle_config.min_chat_delay ) {
if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
return true;
sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
-
+
if(!sd->status.pet_id || !(pd=sd->pd))
{
clif->message(fd, msg_txt(184));
return false;
}
-
+
if (sd->sc.count && //no "chatting" while muted.
(sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
-
+
if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) {
clif->message(fd, msg_txt(1224)); // Please enter a message (usage: @pettalk <message>).
return false;
}
-
+
if (message[0] == '/')
{// pet emotion processing
const char* emo[] = {
@@ -6152,15 +6139,15 @@ ACMD(pettalk)
return true;
}
sd->emotionlasttime = time(NULL);
-
+
clif->emotion(&pd->bl, i);
return true;
}
}
-
+
snprintf(temp, sizeof temp ,"%s : %s", pd->pet.name, mes);
clif->disp_overhead(&pd->bl, temp);
-
+
return true;
}
@@ -6173,10 +6160,10 @@ ACMD(users)
int users[MAX_MAPINDEX];
int users_all;
struct s_mapiterator* iter;
-
+
memset(users, 0, sizeof(users));
users_all = 0;
-
+
// count users on each map
iter = mapit_getallusers();
for(;;)
@@ -6184,29 +6171,29 @@ ACMD(users)
struct map_session_data* sd2 = (struct map_session_data*)mapit->next(iter);
if( sd2 == NULL )
break;// no more users
-
+
if( sd2->mapindex >= MAX_MAPINDEX )
continue;// invalid mapindex
-
+
if( users[sd2->mapindex] < INT_MAX ) ++users[sd2->mapindex];
if( users_all < INT_MAX ) ++users_all;
}
mapit->free(iter);
-
+
// display results for each map
for( i = 0; i < MAX_MAPINDEX; ++i )
{
if( users[i] == 0 )
continue;// empty
-
+
safesnprintf(buf, sizeof(buf), "%s: %d (%.2f%%)", mapindex_id2name(i), users[i], (float)(100.0f*users[i]/users_all));
clif->message(sd->fd, buf);
}
-
+
// display overall count
safesnprintf(buf, sizeof(buf), "all: %d", users_all);
clif->message(sd->fd, buf);
-
+
return true;
}
@@ -6232,31 +6219,31 @@ ACMD(summon)
int duration = 0;
struct mob_data *md;
int64 tick=timer->gettick();
-
+
if (!message || !*message || sscanf(message, "%23s %d", name, &duration) < 1)
{
clif->message(fd, msg_txt(1225)); // Please enter a monster name (usage: @summon <monster name> {duration}).
return false;
}
-
+
if (duration < 1)
duration =1;
else if (duration > 60)
duration =60;
-
+
if ((mob_id = atoi(name)) == 0)
mob_id = mob->db_searchname(name);
if(mob_id == 0 || mob->db_checkid(mob_id) == 0)
{
- clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
+ clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
return false;
}
-
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_MEDIUM, AI_NONE);
-
+
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, -1, -1, "--ja--", mob_id, "", SZ_SMALL, AI_NONE);
+
if(!md)
return false;
-
+
md->master_id=sd->bl.id;
md->special_state.ai=1;
md->deletetimer=timer->add(tick+(duration*60000),mob->timer_delete,md->bl.id,0);
@@ -6264,8 +6251,8 @@ ACMD(summon)
mob->spawn(md);
sc_start4(NULL,&md->bl, SC_MODECHANGE, 100, 1, 0, MD_AGGRESSIVE, 0, 60000);
clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,md->bl.x,md->bl.y,tick);
- clif->message(fd, msg_txt(39)); // All monster summoned!
-
+ clif->message(fd, msg_txt(39)); // All monster summoned!
+
return true;
}
@@ -6277,12 +6264,12 @@ ACMD(summon)
ACMD(adjgroup)
{
int new_group = 0;
-
+
if (!message || !*message || sscanf(message, "%d", &new_group) != 1) {
clif->message(fd, msg_txt(1226)); // Usage: @adjgroup <group_id>
return false;
}
-
+
if (pc->set_group(sd, new_group) != 0) {
clif->message(fd, msg_txt(1227)); // Specified group does not exist.
return false;
@@ -6298,18 +6285,18 @@ ACMD(adjgroup)
* Open a trade window with a remote player
*------------------------------------------*/
ACMD(trade) {
- struct map_session_data *pl_sd = NULL;
-
+ struct map_session_data *pl_sd = NULL;
+
if (!message || !*message) {
clif->message(fd, msg_txt(1230)); // Please enter a player name (usage: @trade <char name>).
return false;
}
-
+
if ( (pl_sd = map->nick2sd((char *)message)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
trade->request(sd, pl_sd);
return true;
}
@@ -6321,19 +6308,19 @@ ACMD(trade) {
ACMD(setbattleflag)
{
char flag[128], value[128];
-
+
if (!message || !*message || sscanf(message, "%127s %127s", flag, value) != 2) {
clif->message(fd, msg_txt(1231)); // Usage: @setbattleflag <flag> <value>
return false;
}
-
+
if (battle->config_set_value(flag, value) == 0) {
clif->message(fd, msg_txt(1232)); // Unknown battle_config flag.
return false;
}
-
+
clif->message(fd, msg_txt(1233)); // Set battle_config as requested.
-
+
return true;
}
@@ -6342,27 +6329,27 @@ ACMD(setbattleflag)
*------------------------------------------*/
ACMD(unmute) {
struct map_session_data *pl_sd = NULL;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1234)); // Please enter a player name (usage: @unmute <char name>).
return false;
}
-
+
if ( (pl_sd = map->nick2sd((char *)message)) == NULL )
{
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if(!pl_sd->sc.data[SC_NOCHAT]) {
clif->message(sd->fd,msg_txt(1235)); // Player is not muted.
return false;
}
-
+
pl_sd->status.manner = 0;
status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER);
clif->message(sd->fd,msg_txt(1236)); // Player unmuted.
-
+
return true;
}
@@ -6373,7 +6360,7 @@ ACMD(uptime)
{
unsigned long seconds = 0, day = 24*60*60, hour = 60*60,
minute = 60, days = 0, hours = 0, minutes = 0;
-
+
seconds = timer->get_uptime();
days = seconds/day;
seconds -= (seconds/day>0)?(seconds/day)*day:0;
@@ -6381,10 +6368,10 @@ ACMD(uptime)
seconds -= (seconds/hour>0)?(seconds/hour)*hour:0;
minutes = seconds/minute;
seconds -= (seconds/minute>0)?(seconds/minute)*minute:0;
-
+
snprintf(atcmd_output, sizeof(atcmd_output), msg_txt(245), days, hours, minutes, seconds);
clif->message(fd, atcmd_output);
-
+
return true;
}
@@ -6410,26 +6397,26 @@ ACMD(changesex)
ACMD(mute) {
struct map_session_data *pl_sd = NULL;
int manner;
-
+
if (!message || !*message || sscanf(message, "%d %23[^\n]", &manner, atcmd_player_name) < 1) {
clif->message(fd, msg_txt(1237)); // Usage: @mute <time> <char name>
return false;
}
-
+
if ( (pl_sd = map->nick2sd(atcmd_player_name)) == NULL ) {
clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if ( pc_get_group_level(sd) < pc_get_group_level(pl_sd) )
{
clif->message(fd, msg_txt(81)); // Your GM level don't authorize you to do this action on this player.
return false;
}
-
+
clif->manner_message(sd, 0);
clif->manner_message(pl_sd, 5);
-
+
if( pl_sd->status.manner < manner ) {
pl_sd->status.manner -= manner;
sc_start(NULL,&pl_sd->bl,SC_NOCHAT,100,0,0);
@@ -6437,9 +6424,9 @@ ACMD(mute) {
pl_sd->status.manner = 0;
status_change_end(&pl_sd->bl, SC_NOCHAT, INVALID_TIMER);
}
-
+
clif->GM_silence(sd, pl_sd, (manner > 0 ? 1 : 0));
-
+
return true;
}
@@ -6456,7 +6443,7 @@ ACMD(refreshall)
{
struct map_session_data* iter_sd;
struct s_mapiterator* iter;
-
+
iter = mapit_getallusers();
for (iter_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); iter_sd = (TBL_PC*)mapit->next(iter))
clif->refresh(iter_sd);
@@ -6471,7 +6458,7 @@ ACMD(refreshall)
ACMD(identify)
{
int i,num;
-
+
for(i=num=0;i<MAX_INVENTORY;i++){
if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].identify!=1){
num++;
@@ -6493,7 +6480,7 @@ ACMD(misceffect) {
if (sscanf(message, "%d", &effect) < 1)
return false;
clif->misceffect(&sd->bl,effect);
-
+
return true;
}
@@ -6520,103 +6507,109 @@ ACMD(mobinfo)
struct mob_db *monster, *mob_array[MAX_SEARCH];
int count;
int i, j, k;
-
+
memset(atcmd_output, '\0', sizeof(atcmd_output));
memset(atcmd_output2, '\0', sizeof(atcmd_output2));
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1239)); // Please enter a monster name/ID (usage: @mobinfo <monster_name_or_monster_ID>).
return false;
}
-
+
// If monster identifier/name argument is a name
if ((i = mob->db_checkid(atoi(message)))) {
mob_array[0] = mob->db(i);
count = 1;
} else
count = mob->db_searchname_array(mob_array, MAX_SEARCH, message, 0);
-
+
if (!count) {
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
return false;
}
-
+
if (count > MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count);
clif->message(fd, atcmd_output);
count = MAX_SEARCH;
}
-
+
for (k = 0; k < count; k++) {
unsigned int job_exp, base_exp;
-
+
monster = mob_array[k];
-
+
job_exp = monster->job_exp;
base_exp = monster->base_exp;
-
+
#ifdef RENEWAL_EXP
if( battle_config.atcommand_mobinfo_type ) {
base_exp = base_exp * pc->level_penalty_mod(monster->lv - sd->status.base_level, monster->status.race, monster->status.mode, 1) / 100;
job_exp = job_exp * pc->level_penalty_mod(monster->lv - sd->status.base_level, monster->status.race, monster->status.mode, 1) / 100;
}
#endif
-
+
// stats
if (monster->mexp)
sprintf(atcmd_output, msg_txt(1240), monster->name, monster->jname, monster->sprite, monster->vd.class_); // MVP Monster: '%s'/'%s'/'%s' (%d)
else
sprintf(atcmd_output, msg_txt(1241), monster->name, monster->jname, monster->sprite, monster->vd.class_); // Monster: '%s'/'%s'/'%s' (%d)
clif->message(fd, atcmd_output);
-
+
sprintf(atcmd_output, msg_txt(1242), monster->lv, monster->status.max_hp, base_exp, job_exp, MOB_HIT(monster), MOB_FLEE(monster)); // Lv:%d HP:%d Base EXP:%u Job EXP:%u HIT:%d FLEE:%d
clif->message(fd, atcmd_output);
-
+
sprintf(atcmd_output, msg_txt(1243), // DEF:%d MDEF:%d STR:%d AGI:%d VIT:%d INT:%d DEX:%d LUK:%d
monster->status.def, monster->status.mdef, monster->status.str, monster->status.agi,
monster->status.vit, monster->status.int_, monster->status.dex, monster->status.luk);
clif->message(fd, atcmd_output);
+
+#ifdef RENEWAL
+ sprintf(atcmd_output, msg_txt(1291), // ATK : %d~%d MATK : %d~%d Range : %d~%d~%d Size : %s Race : %s Element : %s(Lv : %d)
+ MOB_ATK1(monster), MOB_ATK2(monster), MOB_MATK1(monster), MOB_MATK2(monster), monster->status.rhw.range,
+#else
sprintf(atcmd_output, msg_txt(1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d)
monster->status.rhw.atk, monster->status.rhw.atk2, monster->status.rhw.range,
+#endif
monster->range2 , monster->range3, msize[monster->status.size],
mrace[monster->status.race], melement[monster->status.def_ele], monster->status.ele_lv);
clif->message(fd, atcmd_output);
-
+
// drops
clif->message(fd, msg_txt(1245)); // Drops:
strcpy(atcmd_output, " ");
j = 0;
for (i = 0; i < MAX_MOB_DROP; i++) {
int droprate;
-
+
if (monster->dropitem[i].nameid <= 0 || monster->dropitem[i].p < 1 || (item_data = itemdb->exists(monster->dropitem[i].nameid)) == NULL)
continue;
-
+
droprate = monster->dropitem[i].p;
#ifdef RENEWAL_DROP
if( battle_config.atcommand_mobinfo_type ) {
droprate = droprate * pc->level_penalty_mod(monster->lv - sd->status.base_level, monster->status.race, monster->status.mode, 2) / 100;
-
+
if (droprate <= 0 && !battle_config.drop_rate0item)
droprate = 1;
}
#endif
-
+
if (item_data->slot)
sprintf(atcmd_output2, " - %s[%d] %02.02f%%", item_data->jname, item_data->slot, (float)droprate / 100);
else
sprintf(atcmd_output2, " - %s %02.02f%%", item_data->jname, (float)droprate / 100);
-
+
strcat(atcmd_output, atcmd_output2);
-
+
if (++j % 3 == 0) {
clif->message(fd, atcmd_output);
strcpy(atcmd_output, " ");
}
}
-
+
if (j == 0)
clif->message(fd, msg_txt(1246)); // This monster has no drops.
else if (j % 3 != 0)
@@ -6625,7 +6618,7 @@ ACMD(mobinfo)
if (monster->mexp) {
sprintf(atcmd_output, msg_txt(1247), monster->mexp); // MVP Bonus EXP:%u
clif->message(fd, atcmd_output);
-
+
strcpy(atcmd_output, msg_txt(1248)); // MVP Items:
j = 0;
for (i = 0; i < MAX_MVP_DROP; i++) {
@@ -6659,7 +6652,7 @@ ACMD(showmobs)
int mob_id;
int number = 0;
struct s_mapiterator* it;
-
+
if( sscanf(message, "%99[^\n]", mob_name) < 0 ) {
clif->message(fd, msg_txt(546)); // Please enter a mob name/id (usage: @showmobs <mob name/id>)
return false;
@@ -6679,27 +6672,28 @@ ACMD(showmobs)
clif->message(fd, atcmd_output);
return false;
}
-
- if(mob->db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)){ // If player group does not have access to boss mobs.
+
+ if (mob->db(mob_id)->status.mode&MD_BOSS && !pc_has_permission(sd, PC_PERM_SHOW_BOSS)) {
+ // If player group does not have access to boss mobs.
clif->message(fd, msg_txt(1251)); // Can't show boss mobs!
return false;
}
-
+
if(mob_id == atoi(mob_name) && mob->db(mob_id)->jname)
strcpy(mob_name,mob->db(mob_id)->jname); // --ja--
//strcpy(mob_name,mob_db(mob_id)->name); // --en--
-
+
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1252), // Mob Search... %s %s
mob_name, mapindex_id2name(sd->mapindex));
clif->message(fd, atcmd_output);
-
+
it = mapit_geteachmob();
for(;;)
{
TBL_MOB* md = (TBL_MOB*)mapit->next(it);
if( md == NULL )
break;// no more mobs
-
+
if( md->bl.m != sd->bl.m )
continue;
if( mob_id != -1 && md->class_ != mob_id )
@@ -6708,12 +6702,12 @@ ACMD(showmobs)
continue; // hide slaves and player summoned mobs
if( md->spawn_timer != INVALID_TIMER )
continue; // hide mobs waiting for respawn
-
+
++number;
clif->viewpoint(sd, 1, 0, md->bl.x, md->bl.y, number, 0xFFFFFF);
}
mapit->free(it);
-
+
return true;
}
@@ -6724,19 +6718,19 @@ ACMD(homlevel) {
TBL_HOM * hd;
int level = 0;
enum homun_type htype;
-
+
if( !message || !*message || ( level = atoi(message) ) < 1 ) {
clif->message(fd, msg_txt(1253)); // Please enter a level adjustment (usage: @homlevel <number of levels>).
return false;
}
-
+
if( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
hd = sd->hd;
-
+
if( (htype = homun->class2type(hd->homunculus.class_)) == HT_INVALID ) {
ShowError("atcommand_homlevel: invalid homun class %d (player %s)\n", hd->homunculus.class_,sd->status.name);
return false;
@@ -6762,12 +6756,11 @@ ACMD(homlevel) {
ShowError("atcommand_homlevel: unknown htype '%d'\n",htype);
return false;
}
-
-
+
do {
hd->homunculus.exp += hd->exp_next;
} while( hd->homunculus.level < level && homun->levelup(hd) );
-
+
status_calc_homunculus(hd,SCO_NONE);
status_percent_heal(&hd->bl, 100, 100);
clif->specialeffect(&hd->bl,568,AREA);
@@ -6783,7 +6776,7 @@ ACMD(homevolution)
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
if ( !homun->evolve(sd->hd) ) {
clif->message(fd, msg_txt(1255)); // Your homunculus doesn't evolve.
return false;
@@ -6795,21 +6788,21 @@ ACMD(homevolution)
ACMD(hommutate) {
int homun_id;
enum homun_type m_class, m_id;
-
+
if( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
if( !message || !*message ) {
homun_id = 6048 + (rnd() % 4);
} else {
homun_id = atoi(message);
}
-
+
m_class = homun->class2type(sd->hd->homunculus.class_);
- m_id = homun->class2type(homun_id);
-
+ m_id = homun->class2type(homun_id);
+
if( m_class != HT_INVALID && m_id != HT_INVALID && m_class == HT_EVO && m_id == HT_S && sd->hd->homunculus.level >= 99 ) {
homun->mutate(sd->hd, homun_id);
} else {
@@ -6823,14 +6816,14 @@ ACMD(hommutate) {
*------------------------------------------*/
ACMD(makehomun) {
int homunid;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1256)); // Please enter a homunculus ID (usage: @makehomun <homunculus id>).
return false;
}
-
+
homunid = atoi(message);
-
+
if( homunid == -1 && sd->status.hom_id && !(sd->hd && homun_alive(sd->hd)) ) {
if( !sd->hd )
homun->call(sd);
@@ -6840,18 +6833,18 @@ ACMD(makehomun) {
homun->call(sd);
return true;
}
-
+
if ( sd->status.hom_id ) {
clif->message(fd, msg_txt(450));
return false;
}
-
+
if( homunid < HM_CLASS_BASE || homunid > HM_CLASS_BASE + MAX_HOMUNCULUS_CLASS - 1 )
{
clif->message(fd, msg_txt(1257)); // Invalid Homunculus ID.
return false;
}
-
+
homun->creation_request(sd,homunid);
return true;
}
@@ -6862,20 +6855,20 @@ ACMD(makehomun) {
ACMD(homfriendly)
{
int friendly = 0;
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1258)); // Please enter a friendly value (usage: @homfriendly <friendly value [0-1000]>).
return false;
}
-
+
friendly = atoi(message);
friendly = cap_value(friendly, 0, 1000);
-
+
sd->hd->homunculus.intimacy = friendly * 100 ;
clif->send_homdata(sd,SP_INTIMATE,friendly);
return true;
@@ -6887,20 +6880,20 @@ ACMD(homfriendly)
ACMD(homhungry)
{
int hungry = 0;
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1259)); // Please enter a hunger value (usage: @homhungry <hunger value [0-100]>).
return false;
}
-
+
hungry = atoi(message);
hungry = cap_value(hungry, 0, 100);
-
+
sd->hd->homunculus.hunger = hungry;
clif->send_homdata(sd,SP_HUNGRY,hungry);
return true;
@@ -6912,31 +6905,31 @@ ACMD(homhungry)
ACMD(homtalk)
{
char mes[100],temp[100];
-
+
if ( battle_config.min_chat_delay ) {
if( DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0 )
return true;
sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
}
-
+
if (sd->sc.count && //no "chatting" while muted.
(sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
if (!message || !*message || sscanf(message, "%99[^\n]", mes) < 1) {
clif->message(fd, msg_txt(1260)); // Please enter a message (usage: @homtalk <message>).
return false;
}
-
+
snprintf(temp, sizeof temp ,"%s : %s", sd->hd->homunculus.name, mes);
clif->disp_overhead(&sd->hd->bl, temp);
-
+
return true;
}
@@ -6946,34 +6939,34 @@ ACMD(homtalk)
ACMD(hominfo) {
struct homun_data *hd;
struct status_data *st;
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
hd = sd->hd;
st = status->get_status_data(&hd->bl);
clif->message(fd, msg_txt(1261)); // Homunculus stats:
-
+
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1262), // HP: %d/%d - SP: %d/%d
st->hp, st->max_hp, st->sp, st->max_sp);
clif->message(fd, atcmd_output);
-
+
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1263), // ATK: %d - MATK: %d~%d
st->rhw.atk2 +st->batk, st->matk_min, st->matk_max);
clif->message(fd, atcmd_output);
-
+
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1264), // Hungry: %d - Intimacy: %u
hd->homunculus.hunger, hd->homunculus.intimacy/100);
clif->message(fd, atcmd_output);
-
+
snprintf(atcmd_output, sizeof(atcmd_output) ,
msg_txt(1265), // Stats: Str %d / Agi %d / Vit %d / Int %d / Dex %d / Luk %d
st->str, st->agi, st->vit,
st->int_, st->dex, st->luk);
clif->message(fd, atcmd_output);
-
+
return true;
}
@@ -6983,75 +6976,75 @@ ACMD(homstats)
struct s_homunculus_db *db;
struct s_homunculus *hom;
int lv, min, max, evo;
-
+
if ( !homun_alive(sd->hd) ) {
clif->message(fd, msg_txt(1254)); // You do not have a homunculus.
return false;
}
-
+
hd = sd->hd;
-
+
hom = &hd->homunculus;
db = hd->homunculusDB;
lv = hom->level;
-
+
snprintf(atcmd_output, sizeof(atcmd_output) ,
msg_txt(1266), lv, db->name); // Homunculus growth stats (Lv %d %s):
clif->message(fd, atcmd_output);
lv--; //Since the first increase is at level 2.
-
+
evo = (hom->class_ == db->evo_class);
min = db->base.HP +lv*db->gmin.HP +(evo?db->emin.HP:0);
max = db->base.HP +lv*db->gmax.HP +(evo?db->emax.HP:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1267), hom->max_hp, min, max); // Max HP: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
min = db->base.SP +lv*db->gmin.SP +(evo?db->emin.SP:0);
max = db->base.SP +lv*db->gmax.SP +(evo?db->emax.SP:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1268), hom->max_sp, min, max); // Max SP: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
min = db->base.str +lv*(db->gmin.str/10) +(evo?db->emin.str:0);
max = db->base.str +lv*(db->gmax.str/10) +(evo?db->emax.str:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1269), hom->str/10, min, max); // Str: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
min = db->base.agi +lv*(db->gmin.agi/10) +(evo?db->emin.agi:0);
max = db->base.agi +lv*(db->gmax.agi/10) +(evo?db->emax.agi:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1270), hom->agi/10, min, max); // Agi: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
min = db->base.vit +lv*(db->gmin.vit/10) +(evo?db->emin.vit:0);
max = db->base.vit +lv*(db->gmax.vit/10) +(evo?db->emax.vit:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1271), hom->vit/10, min, max); // Vit: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
min = db->base.int_ +lv*(db->gmin.int_/10) +(evo?db->emin.int_:0);
max = db->base.int_ +lv*(db->gmax.int_/10) +(evo?db->emax.int_:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1272), hom->int_/10, min, max); // Int: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
min = db->base.dex +lv*(db->gmin.dex/10) +(evo?db->emin.dex:0);
max = db->base.dex +lv*(db->gmax.dex/10) +(evo?db->emax.dex:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1273), hom->dex/10, min, max); // Dex: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
min = db->base.luk +lv*(db->gmin.luk/10) +(evo?db->emin.luk:0);
max = db->base.luk +lv*(db->gmax.luk/10) +(evo?db->emax.luk:0);;
snprintf(atcmd_output, sizeof(atcmd_output) ,msg_txt(1274), hom->luk/10, min, max); // Luk: %d (%d~%d)
clif->message(fd, atcmd_output);
-
+
return true;
}
-ACMD(homshuffle) {
-
+ACMD(homshuffle)
+{
if(!sd->hd)
return false; // nothing to do
-
+
if(!homun->shuffle(sd->hd))
return false;
-
+
clif->message(sd->fd, msg_txt(1275)); // Homunculus stats altered.
atcommand_homstats(fd, sd, command, message, info); //Print out the new stats
return true;
@@ -7065,19 +7058,19 @@ ACMD(iteminfo)
{
struct item_data *item_data, *item_array[MAX_SEARCH];
int i, count = 1;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1276)); // Please enter an item name/ID (usage: @ii/@iteminfo <item name/ID>).
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
-
+
if (!count) {
- clif->message(fd, msg_txt(19)); // Invalid item ID or name.
+ clif->message(fd, msg_txt(19)); // Invalid item ID or name.
return false;
}
-
+
if (count > MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches
clif->message(fd, atcmd_output);
@@ -7091,10 +7084,10 @@ ACMD(iteminfo)
(item_data->script==NULL)? msg_txt(1278) : msg_txt(1279) // None / With script
);
clif->message(fd, atcmd_output);
-
+
sprintf(atcmd_output, msg_txt(1280), item_data->value_buy, item_data->value_sell, item_data->weight/10. ); // NPC Buy:%dz, Sell:%dz | Weight: %.1f
clif->message(fd, atcmd_output);
-
+
if (item_data->maxchance == -1)
strcpy(atcmd_output, msg_txt(1281)); // - Available in the shops only.
else if ( !battle_config.atcommand_mobinfo_type ) {
@@ -7104,7 +7097,7 @@ ACMD(iteminfo)
strcpy(atcmd_output, msg_txt(1283)); // - Monsters don't drop this item.
}
clif->message(fd, atcmd_output);
-
+
}
return true;
}
@@ -7116,19 +7109,19 @@ ACMD(whodrops)
{
struct item_data *item_data, *item_array[MAX_SEARCH];
int i,j, count = 1;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1284)); // Please enter item name/ID (usage: @whodrops <item name/ID>).
return false;
}
if ((item_array[0] = itemdb->exists(atoi(message))) == NULL)
count = itemdb->search_name_array(item_array, MAX_SEARCH, message, 0);
-
+
if (!count) {
- clif->message(fd, msg_txt(19)); // Invalid item ID or name.
+ clif->message(fd, msg_txt(19)); // Invalid item ID or name.
return false;
}
-
+
if (count > MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count); // Displaying first %d out of %d matches
clif->message(fd, atcmd_output);
@@ -7138,14 +7131,14 @@ ACMD(whodrops)
item_data = item_array[i];
sprintf(atcmd_output, msg_txt(1285), item_data->jname,item_data->slot); // Item: '%s'[%d]
clif->message(fd, atcmd_output);
-
+
if (item_data->mob[0].chance == 0) {
strcpy(atcmd_output, msg_txt(1286)); // - Item is not dropped by mobs.
clif->message(fd, atcmd_output);
} else {
sprintf(atcmd_output, msg_txt(1287), MAX_SEARCH); // - Common mobs with highest drop chance (only max %d are listed):
clif->message(fd, atcmd_output);
-
+
for (j=0; j < MAX_SEARCH && item_data->mob[j].chance > 0; j++)
{
sprintf(atcmd_output, "- %s (%02.02f%%)", mob->db(item_data->mob[j].id)->jname, item_data->mob[j].chance/100.);
@@ -7161,12 +7154,12 @@ ACMD(whereis)
struct mob_db *monster, *mob_array[MAX_SEARCH];
int count;
int i, j, k;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1288)); // Please enter a monster name/ID (usage: @whereis <monster_name_or_monster_ID>).
return false;
}
-
+
// If monster identifier/name argument is a name
if ((i = mob->db_checkid(atoi(message))))
{
@@ -7174,12 +7167,12 @@ ACMD(whereis)
count = 1;
} else
count = mob->db_searchname_array(mob_array, MAX_SEARCH, message, 0);
-
+
if (!count) {
clif->message(fd, msg_txt(40)); // Invalid monster ID or name.
return false;
}
-
+
if (count > MAX_SEARCH) {
sprintf(atcmd_output, msg_txt(269), MAX_SEARCH, count);
clif->message(fd, atcmd_output);
@@ -7189,7 +7182,7 @@ ACMD(whereis)
monster = mob_array[k];
snprintf(atcmd_output, sizeof atcmd_output, msg_txt(1289), monster->jname); // %s spawns in:
clif->message(fd, atcmd_output);
-
+
for (i = 0; i < ARRAYLENGTH(monster->spawn) && monster->spawn[i].qty; i++) {
j = map->mapindex2mapid(monster->spawn[i].mapindex);
if (j < 0) continue;
@@ -7199,7 +7192,7 @@ ACMD(whereis)
if (i == 0)
clif->message(fd, msg_txt(1290)); // This monster does not spawn normally.
}
-
+
return true;
}
@@ -7217,15 +7210,15 @@ ACMD(version) {
*------------------------------------------*/
int atcommand_mutearea_sub(struct block_list *bl,va_list ap)
{ // As it is being used [ACMD(mutearea)] there's no need to be a bool, but if there's need to reuse it, it's better to be this way
-
+
int time, id;
struct map_session_data *pl_sd = (struct map_session_data *)bl;
if (pl_sd == NULL)
return 0;
-
+
id = va_arg(ap, int);
time = va_arg(ap, int);
-
+
if (id != bl->id && !pc_get_group_level(pl_sd)) {
pl_sd->status.manner -= time;
if (pl_sd->status.manner < 0)
@@ -7238,18 +7231,18 @@ int atcommand_mutearea_sub(struct block_list *bl,va_list ap)
ACMD(mutearea) {
int time;
-
+
if (!message || !*message) {
clif->message(fd, msg_txt(1297)); // Please enter a time in minutes (usage: @mutearea/@stfu <time in minutes>).
return false;
}
-
+
time = atoi(message);
-
+
map->foreachinarea(atcommand->mutearea_sub,sd->bl.m,
sd->bl.x-AREA_SIZE, sd->bl.y-AREA_SIZE,
sd->bl.x+AREA_SIZE, sd->bl.y+AREA_SIZE, BL_PC, sd->bl.id, time);
-
+
return true;
}
@@ -7257,9 +7250,9 @@ ACMD(mutearea) {
ACMD(rates)
{
char buf[CHAT_SIZE_MAX];
-
+
memset(buf, '\0', sizeof(buf));
-
+
snprintf(buf, CHAT_SIZE_MAX, msg_txt(1298), // Experience rates: Base %.2fx / Job %.2fx
battle_config.base_exp_rate/100., battle_config.job_exp_rate/100.);
clif->message(fd, buf);
@@ -7272,7 +7265,7 @@ ACMD(rates)
snprintf(buf, CHAT_SIZE_MAX, msg_txt(1301), // Other Drop Rates: MvP %.2fx / Card-Based %.2fx / Treasure %.2fx
battle_config.item_rate_mvp/100., battle_config.item_rate_adddrop/100., battle_config.item_rate_treasure/100.);
clif->message(fd, buf);
-
+
return true;
}
@@ -7283,25 +7276,24 @@ ACMD(rates)
ACMD(me)
{
char tempmes[CHAT_SIZE_MAX];
-
+
memset(tempmes, '\0', sizeof(tempmes));
memset(atcmd_output, '\0', sizeof(atcmd_output));
-
+
if (sd->sc.count && //no "chatting" while muted.
(sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) ||
(sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT)))
return false;
-
+
if (!message || !*message || sscanf(message, "%199[^\n]", tempmes) < 0) {
clif->message(fd, msg_txt(1302)); // Please enter a message (usage: @me <message>).
return false;
}
-
- sprintf(atcmd_output, msg_txt(270), sd->status.name, tempmes); // *%s %s*
+
+ sprintf(atcmd_output, msg_txt(270), sd->status.name, tempmes); // *%s %s*
clif->disp_overhead(&sd->bl, atcmd_output);
-
+
return true;
-
}
/*==========================================
@@ -7311,20 +7303,20 @@ ACMD(me)
ACMD(size)
{
int size = 0;
-
- size = cap_value(atoi(message),SZ_MEDIUM,SZ_BIG);
-
+
+ size = cap_value(atoi(message),SZ_SMALL,SZ_BIG);
+
if(sd->state.size) {
- sd->state.size = SZ_MEDIUM;
+ sd->state.size = SZ_SMALL;
pc->setpos(sd, sd->mapindex, sd->bl.x, sd->bl.y, CLR_TELEPORT);
}
-
+
sd->state.size = size;
- if( size == SZ_SMALL )
+ if( size == SZ_MEDIUM )
clif->specialeffect(&sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&sd->bl,422,AREA);
-
+
clif->message(fd, msg_txt(1303)); // Size change applied.
return true;
}
@@ -7334,27 +7326,27 @@ ACMD(sizeall)
int size;
struct map_session_data *pl_sd;
struct s_mapiterator* iter;
-
+
size = atoi(message);
size = cap_value(size,0,2);
-
+
iter = mapit_getallusers();
for( pl_sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); pl_sd = (TBL_PC*)mapit->next(iter) ) {
if( pl_sd->state.size != size ) {
if( pl_sd->state.size ) {
- pl_sd->state.size = SZ_MEDIUM;
+ pl_sd->state.size = SZ_SMALL;
pc->setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
}
-
+
pl_sd->state.size = size;
- if( size == SZ_SMALL )
+ if( size == SZ_MEDIUM )
clif->specialeffect(&pl_sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&pl_sd->bl,422,AREA);
}
}
mapit->free(iter);
-
+
clif->message(fd, msg_txt(1303)); // Size change applied.
return true;
}
@@ -7365,36 +7357,36 @@ ACMD(sizeguild)
char guild_name[NAME_LENGTH];
struct map_session_data *pl_sd;
struct guild *g;
-
+
memset(guild_name, '\0', sizeof(guild_name));
-
+
if( !message || !*message || sscanf(message, "%d %23[^\n]", &size, guild_name) < 2 ) {
clif->message(fd, msg_txt(1304)); // Please enter guild name/ID (usage: @sizeguild <size> <guild name/ID>).
return false;
}
-
+
if( (g = guild->searchname(guild_name)) == NULL && (g = guild->search(atoi(guild_name))) == NULL ) {
clif->message(fd, msg_txt(94)); // Incorrect name/ID, or no one from the guild is online.
return false;
}
-
- size = cap_value(size,SZ_MEDIUM,SZ_BIG);
-
+
+ size = cap_value(size,SZ_SMALL,SZ_BIG);
+
for( i = 0; i < g->max_member; i++ ) {
if( (pl_sd = g->member[i].sd) && pl_sd->state.size != size ) {
if( pl_sd->state.size ) {
- pl_sd->state.size = SZ_MEDIUM;
+ pl_sd->state.size = SZ_SMALL;
pc->setpos(pl_sd, pl_sd->mapindex, pl_sd->bl.x, pl_sd->bl.y, CLR_TELEPORT);
}
-
+
pl_sd->state.size = size;
- if( size == SZ_SMALL )
+ if( size == SZ_MEDIUM )
clif->specialeffect(&pl_sd->bl,420,AREA);
else if( size == SZ_BIG )
clif->specialeffect(&pl_sd->bl,422,AREA);
}
}
-
+
clif->message(fd, msg_txt(1303)); // Size change applied.
return true;
}
@@ -7403,8 +7395,8 @@ ACMD(sizeguild)
* @monsterignore
* => Makes monsters ignore you. [Valaris]
*------------------------------------------*/
-ACMD(monsterignore) {
-
+ACMD(monsterignore)
+{
if (!sd->state.monster_ignore) {
sd->state.monster_ignore = 1;
clif->message(sd->fd, msg_txt(1305)); // You are now immune to attacks.
@@ -7412,15 +7404,15 @@ ACMD(monsterignore) {
sd->state.monster_ignore = 0;
clif->message(sd->fd, msg_txt(1306)); // Returned to normal state.
}
-
+
return true;
}
/*==========================================
* @fakename
* => Gives your character a fake name. [Valaris]
*------------------------------------------*/
-ACMD(fakename){
-
+ACMD(fakename)
+{
if( !message || !*message )
{
if( sd->fakename[0] )
@@ -7432,23 +7424,23 @@ ACMD(fakename){
clif->message(sd->fd, msg_txt(1307)); // Returned to real name.
return true;
}
-
+
clif->message(sd->fd, msg_txt(1308)); // You must enter a name.
return false;
}
-
+
if( strlen(message) < 2 )
{
clif->message(sd->fd, msg_txt(1309)); // Fake name must be at least two characters.
return false;
}
-
+
safestrncpy(sd->fakename, message, sizeof(sd->fakename));
clif->charnameack(0, &sd->bl);
if( sd->disguise ) // Another packet should be sent so the client updates the name for sd
clif->charnameack(sd->fd, &sd->bl);
clif->message(sd->fd, msg_txt(1310)); // Fake name enabled.
-
+
return true;
}
@@ -7470,7 +7462,7 @@ ACMD(mapflag) {
short flag=0,i;
memset(flag_name, '\0', sizeof(flag_name));
-
+
if (!message || !*message || (sscanf(message, "%99s %hd", flag_name, &flag) < 1)) {
clif->message(sd->fd,msg_txt(1311)); // Enabled Mapflags in this map:
clif->message(sd->fd,"----------------------------------");
@@ -7493,7 +7485,7 @@ ACMD(mapflag) {
return true;
}
for (i = 0; flag_name[i]; i++) flag_name[i] = TOLOWER(flag_name[i]); //lowercase
-
+
if ( strcmp( flag_name , "gvg" ) == 0 ) {
if( flag && !map->list[sd->bl.m].flag.gvg )
map->zone_change2(sd->bl.m,strdb_get(map->zone_db, MAP_ZONE_GVG_NAME));
@@ -7510,7 +7502,7 @@ ACMD(mapflag) {
else if ( !flag && map->list[sd->bl.m].flag.battleground )
map->zone_change2(sd->bl.m,map->list[sd->bl.m].prev_zone);
}
-
+
SETFLAG(autotrade); SETFLAG(allowks); SETFLAG(nomemo); SETFLAG(noteleport);
SETFLAG(noreturn); SETFLAG(monster_noteleport); SETFLAG(nosave); SETFLAG(nobranch);
SETFLAG(noexppenalty); SETFLAG(pvp); SETFLAG(pvp_noparty); SETFLAG(pvp_noguild);
@@ -7524,7 +7516,7 @@ ACMD(mapflag) {
SETFLAG(nodrop); SETFLAG(novending); SETFLAG(loadevent);
SETFLAG(nochat); SETFLAG(partylock); SETFLAG(guildlock); SETFLAG(src4instance);
SETFLAG(notomb); SETFLAG(nocashshop);
-
+
clif->message(sd->fd,msg_txt(1314)); // Invalid flag name or flag.
clif->message(sd->fd,msg_txt(1312)); // Usage: "@mapflag monster_noteleport 1" (0=Off | 1=On)
clif->message(sd->fd,msg_txt(1315)); // Available Flags:
@@ -7536,10 +7528,9 @@ ACMD(mapflag) {
clif->message(sd->fd,"fog, fireworks, sakura, leaves, nobaseexp, nojobexp, nomobloot,");
clif->message(sd->fd,"nomvploot, nightenabled, nodrop, novending, loadevent, nochat, partylock,");
clif->message(sd->fd,"guildlock, src4instance, notomb, nocashshop");
-
#undef CHECKFLAG
#undef SETFLAG
-
+
return true;
}
@@ -7553,7 +7544,7 @@ ACMD(showexp)
clif->message(fd, msg_txt(1316)); // Gained exp will not be shown.
return true;
}
-
+
sd->state.showexp = 1;
clif->message(fd, msg_txt(1317)); // Gained exp is now shown.
return true;
@@ -7566,7 +7557,7 @@ ACMD(showzeny)
clif->message(fd, msg_txt(1318)); // Gained zeny will not be shown.
return true;
}
-
+
sd->state.showzeny = 1;
clif->message(fd, msg_txt(1319)); // Gained zeny is now shown.
return true;
@@ -7579,7 +7570,7 @@ ACMD(showdelay)
clif->message(fd, msg_txt(1320)); // Skill delay failures will not be shown.
return true;
}
-
+
sd->state.showdelay = 1;
clif->message(fd, msg_txt(1321)); // Skill delay failures are now shown.
return true;
@@ -7597,34 +7588,33 @@ ACMD(showdelay)
ACMD(invite) {
unsigned int did = sd->duel_group;
struct map_session_data *target_sd = map->nick2sd((char *)message);
-
+
if(did == 0)
{
// "Duel: @invite without @duel."
clif->message(fd, msg_txt(350));
return false;
}
-
+
if(duel->list[did].max_players_limit > 0 &&
duel->list[did].members_count >= duel->list[did].max_players_limit) {
-
// "Duel: Limit of players is reached."
clif->message(fd, msg_txt(351));
return false;
}
-
+
if(target_sd == NULL) {
// "Duel: Player not found."
clif->message(fd, msg_txt(352));
return false;
}
-
+
if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) {
// "Duel: Player already in duel."
clif->message(fd, msg_txt(353));
return false;
}
-
+
if(battle_config.duel_only_on_same_map && target_sd->bl.m != sd->bl.m)
{
// "Duel: You can't invite %s because he/she isn't in the same map."
@@ -7632,7 +7622,7 @@ ACMD(invite) {
clif->message(fd, atcmd_output);
return false;
}
-
+
duel->invite(did, sd, target_sd);
// "Duel: Invitation has been sent."
clif->message(fd, msg_txt(354));
@@ -7641,18 +7631,18 @@ ACMD(invite) {
ACMD(duel) {
unsigned int maxpl = 0;
-
+
if(sd->duel_group > 0) {
duel->showinfo(sd->duel_group, sd);
return true;
}
-
+
if(sd->duel_invite > 0) {
// "Duel: @duel without @reject."
clif->message(fd, msg_txt(355));
return false;
}
-
+
if(!duel->checktime(sd)) {
char output[CHAT_SIZE_MAX];
// "Duel: You can take part in duel only one time per %d minutes."
@@ -7660,7 +7650,7 @@ ACMD(duel) {
clif->message(fd, output);
return false;
}
-
+
if( message[0] ) {
if(sscanf(message, "%d", &maxpl) >= 1) {
if(maxpl < 2 || maxpl > 65535) {
@@ -7674,7 +7664,7 @@ ACMD(duel) {
if(target_sd != NULL) {
unsigned int newduel;
if((newduel = duel->create(sd, 2)) != -1) {
- if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) {
+ if(target_sd->duel_group > 0 || target_sd->duel_invite > 0) {
clif->message(fd, msg_txt(353)); // "Duel: Player already in duel."
return false;
}
@@ -7689,7 +7679,7 @@ ACMD(duel) {
}
} else
duel->create(sd, 0);
-
+
return true;
}
@@ -7700,7 +7690,6 @@ ACMD(leave) {
clif->message(fd, msg_txt(358));
return false;
}
-
duel->leave(sd->duel_group, sd);
clif->message(fd, msg_txt(359)); // "Duel: You left the duel."
return true;
@@ -7714,20 +7703,20 @@ ACMD(accept) {
clif->message(fd, output);
return false;
}
-
+
if(sd->duel_invite <= 0) {
// "Duel: @accept without invitation."
clif->message(fd, msg_txt(360));
return false;
}
-
+
if( duel->list[sd->duel_invite].max_players_limit > 0
&& duel->list[sd->duel_invite].members_count >= duel->list[sd->duel_invite].max_players_limit ) {
// "Duel: Limit of players is reached."
clif->message(fd, msg_txt(351));
return false;
}
-
+
duel->accept(sd->duel_invite, sd);
// "Duel: Invitation has been accepted."
clif->message(fd, msg_txt(361));
@@ -7740,7 +7729,7 @@ ACMD(reject) {
clif->message(fd, msg_txt(362));
return false;
}
-
+
duel->reject(sd->duel_invite, sd);
// "Duel: Invitation has been rejected."
clif->message(fd, msg_txt(363));
@@ -7755,12 +7744,12 @@ ACMD(cash)
char output[128];
int value;
int ret=0;
-
+
if( !message || !*message || (value = atoi(message)) == 0 ) {
clif->message(fd, msg_txt(1322)); // Please enter an amount.
return false;
}
-
+
if( !strcmpi(info->command,"cash") ) {
if( value > 0 ) {
if( (ret=pc->getcash(sd, value, 0)) >= 0){
@@ -7796,7 +7785,7 @@ ACMD(cash)
clif->message(fd, msg_txt(41)); // Unable to decrease the number/value.
}
}
-
+
return true;
}
@@ -7804,22 +7793,22 @@ ACMD(cash)
ACMD(clone) {
int x=0,y=0,flag=0,master=0,i=0;
struct map_session_data *pl_sd=NULL;
-
+
if (!message || !*message) {
clif->message(sd->fd,msg_txt(1323)); // You must enter a player name or ID.
return false;
}
-
+
if((pl_sd=map->nick2sd((char *)message)) == NULL && (pl_sd=map->charid2sd(atoi(message))) == NULL) {
- clif->message(fd, msg_txt(3)); // Character not found.
+ clif->message(fd, msg_txt(3)); // Character not found.
return false;
}
-
+
if(pc_get_group_level(pl_sd) > pc_get_group_level(sd)) {
- clif->message(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself.
+ clif->message(fd, msg_txt(126)); // Cannot clone a player of higher GM level than yourself.
return false;
}
-
+
if (strcmpi(info->command, "clone") == 0)
flag = 1;
else if (strcmpi(info->command, "slaveclone") == 0) {
@@ -7832,26 +7821,26 @@ ACMD(clone) {
master = sd->bl.id;
if (battle_config.atc_slave_clone_limit
&& mob->countslave(&sd->bl) >= battle_config.atc_slave_clone_limit) {
- clif->message(fd, msg_txt(127)); // You've reached your slave clones limit.
+ clif->message(fd, msg_txt(127)); // You've reached your slave clones limit.
return false;
}
}
-
+
do {
x = sd->bl.x + (rnd() % 10 - 5);
y = sd->bl.y + (rnd() % 10 - 5);
} while (map->getcell(sd->bl.m,x,y,CELL_CHKNOPASS) && i++ < 10);
-
+
if (i >= 10) {
x = sd->bl.x;
y = sd->bl.y;
}
-
+
if((x = mob->clone_spawn(pl_sd, sd->bl.m, x, y, "", master, 0, flag?1:0, 0)) > 0) {
- clif->message(fd, msg_txt(128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned.
+ clif->message(fd, msg_txt(128+flag*2)); // Evil Clone spawned. Clone spawned. Slave clone spawned.
return true;
}
- clif->message(fd, msg_txt(129+flag*2)); // Unable to spawn evil clone. Unable to spawn clone. Unable to spawn slave clone.
+ clif->message(fd, msg_txt(129+flag*2)); // Unable to spawn evil clone. Unable to spawn clone. Unable to spawn slave clone.
return false;
}
@@ -7868,7 +7857,7 @@ ACMD(noask)
clif->message(fd, msg_txt(390)); // Autorejecting is activated.
sd->state.noask = 1;
}
-
+
return true;
}
@@ -7879,14 +7868,14 @@ ACMD(noask)
ACMD(request)
{
if (!message || !*message) {
- clif->message(sd->fd,msg_txt(277)); // Usage: @request <petition/message to online GMs>.
+ clif->message(sd->fd,msg_txt(277)); // Usage: @request <petition/message to online GMs>.
return false;
}
-
- sprintf(atcmd_output, msg_txt(278), message); // (@request): %s
+
+ sprintf(atcmd_output, msg_txt(278), message); // (@request): %s
intif->wis_message_to_gm(sd->status.name, PC_PERM_RECEIVE_REQUESTS, atcmd_output);
clif_disp_onlyself(sd, atcmd_output, strlen(atcmd_output));
- clif->message(sd->fd,msg_txt(279)); // @request sent.
+ clif->message(sd->fd,msg_txt(279)); // @request sent.
return true;
}
@@ -7897,7 +7886,7 @@ ACMD(feelreset)
{
pc->resetfeel(sd);
clif->message(fd, msg_txt(1324)); // Reset 'Feeling' maps.
-
+
return true;
}
@@ -7905,14 +7894,14 @@ ACMD(feelreset)
* AUCTION SYSTEM
*------------------------------------------*/
ACMD(auction) {
-
+
if( !battle_config.feature_auction ) {
clif->colormes(sd->fd,COLOR_RED,msg_txt(1484));
return false;
}
-
+
clif->auction_openwindow(sd);
-
+
return true;
}
@@ -7950,8 +7939,8 @@ ACMD(ksprotection)
/*==========================================
* Map Kill Steal Protection Setting
*------------------------------------------*/
-ACMD(allowks) {
-
+ACMD(allowks)
+{
if( map->list[sd->bl.m].flag.allowks ) {
map->list[sd->bl.m].flag.allowks = 0;
clif->message(fd, msg_txt(1330)); // [ Map K.S Protection Active ]
@@ -7962,16 +7951,16 @@ ACMD(allowks) {
return true;
}
-ACMD(resetstat) {
-
+ACMD(resetstat)
+{
pc->resetstate(sd);
sprintf(atcmd_output, msg_txt(207), sd->status.name);
clif->message(fd, atcmd_output);
return true;
}
-ACMD(resetskill) {
-
+ACMD(resetskill)
+{
pc->resetskill(sd,1);
sprintf(atcmd_output, msg_txt(206), sd->status.name);
clif->message(fd, atcmd_output);
@@ -7990,7 +7979,7 @@ ACMD(itemlist)
const struct item* items;
int size;
StringBuf buf;
-
+
if( strcmpi(info->command, "storagelist") == 0 ) {
location = "storage";
items = sd->status.storage.items;
@@ -8005,34 +7994,34 @@ ACMD(itemlist)
size = MAX_INVENTORY;
} else
return false;
-
+
StrBuf->Init(&buf);
-
+
count = 0; // total slots occupied
counter = 0; // total items found
for( i = 0; i < size; ++i )
{
const struct item* it = &items[i];
struct item_data* itd;
-
+
if( it->nameid == 0 || (itd = itemdb->exists(it->nameid)) == NULL )
continue;
-
+
counter += it->amount;
count++;
-
+
if( count == 1 )
{
StrBuf->Printf(&buf, msg_txt(1332), location, sd->status.name); // ------ %s items list of '%s' ------
clif->message(fd, StrBuf->Value(&buf));
StrBuf->Clear(&buf);
}
-
+
if( it->refine )
StrBuf->Printf(&buf, "%d %s %+d (%s, id: %d)", it->amount, itd->jname, it->refine, itd->name, it->nameid);
else
StrBuf->Printf(&buf, "%d %s (%s, id: %d)", it->amount, itd->jname, itd->name, it->nameid);
-
+
if( it->equip ) {
char equipstr[CHAT_SIZE_MAX];
strcpy(equipstr, msg_txt(1333)); // | equipped:
@@ -8068,10 +8057,10 @@ ACMD(itemlist)
equipstr[strlen(equipstr) - 2] = '\0';
StrBuf->AppendStr(&buf, equipstr);
}
-
+
clif->message(fd, StrBuf->Value(&buf));
StrBuf->Clear(&buf);
-
+
if( it->card[0] == CARD0_PET ) {
// pet egg
if (it->card[3])
@@ -8108,22 +8097,21 @@ ACMD(itemlist)
if( counter2 > 0 )
StrBuf->AppendStr(&buf, ")");
}
-
+
if( StrBuf->Length(&buf) > 0 )
clif->message(fd, StrBuf->Value(&buf));
StrBuf->Clear(&buf);
}
-
+
if( count == 0 )
StrBuf->Printf(&buf, msg_txt(1353), location); // No item found in this player's %s.
else
StrBuf->Printf(&buf, msg_txt(1354), counter, count, location); // %d item(s) found in %d %s slots.
-
+
clif->message(fd, StrBuf->Value(&buf));
-
+
StrBuf->Destroy(&buf);
-
return true;
}
@@ -8154,10 +8142,10 @@ ACMD(stats)
{ "JobChangeLvl (3rd) - %d", 0 },
{ NULL, 0 }
};
-
+
memset(job_jobname, '\0', sizeof(job_jobname));
memset(output, '\0', sizeof(output));
-
+
//direct array initialization with variables is not standard C compliant.
output_table[0].value = sd->status.base_level;
output_table[1].format = job_jobname;
@@ -8176,17 +8164,16 @@ ACMD(stats)
output_table[13].value = sd->status.skill_point;
output_table[14].value = sd->change_level_2nd;
output_table[15].value = sd->change_level_3rd;
-
+
sprintf(job_jobname, "Job - %s %s", pc->job_name(sd->status.class_), "(level %d)");
sprintf(output, msg_txt(53), sd->status.name); // '%s' stats:
-
+
clif->message(fd, output);
-
+
for (i = 0; output_table[i].format != NULL; i++) {
sprintf(output, output_table[i].format, output_table[i].value);
clif->message(fd, output);
}
-
return true;
}
@@ -8194,13 +8181,13 @@ ACMD(delitem) {
char item_name[100];
int nameid, amount = 0, total, idx;
struct item_data* id;
-
+
if( !message || !*message || ( sscanf(message, "\"%99[^\"]\" %d", item_name, &amount) < 2 && sscanf(message, "%99s %d", item_name, &amount) < 2 ) || amount < 1 )
{
clif->message(fd, msg_txt(1355)); // Please enter an item name/ID, a quantity, and a player name (usage: #delitem <player> <item_name_or_ID> <quantity>).
return false;
}
-
+
if( ( id = itemdb->search_name(item_name) ) != NULL || ( id = itemdb->exists(atoi(item_name)) ) != NULL )
{
nameid = id->nameid;
@@ -8210,26 +8197,26 @@ ACMD(delitem) {
clif->message(fd, msg_txt(19)); // Invalid item ID or name.
return false;
}
-
+
total = amount;
-
+
// delete items
while (amount && (idx = pc->search_inventory(sd, nameid)) != INDEX_NOT_FOUND) {
int delamount = ( amount < sd->status.inventory[idx].amount ) ? amount : sd->status.inventory[idx].amount;
-
+
if( sd->inventory_data[idx]->type == IT_PETEGG && sd->status.inventory[idx].card[0] == CARD0_PET )
{// delete pet
intif->delete_petdata(MakeDWord(sd->status.inventory[idx].card[1], sd->status.inventory[idx].card[2]));
}
pc->delitem(sd, idx, delamount, 0, 0, LOG_TYPE_COMMAND);
-
+
amount-= delamount;
}
-
+
// notify target
sprintf(atcmd_output, msg_txt(113), total-amount); // %d item(s) removed by a GM.
clif->message(sd->fd, atcmd_output);
-
+
// notify source
if( amount == total )
{
@@ -8245,7 +8232,6 @@ ACMD(delitem) {
sprintf(atcmd_output, msg_txt(114), total); // %d item(s) removed from the player.
clif->message(fd, atcmd_output);
}
-
return true;
}
@@ -8254,7 +8240,7 @@ ACMD(delitem) {
*------------------------------------------*/
ACMD(font) {
int font_id;
-
+
font_id = atoi(message);
if( font_id == 0 )
{
@@ -8280,7 +8266,7 @@ ACMD(font) {
}
else
clif->message(fd, msg_txt(1361)); // Already using this font.
-
+
return true;
}
@@ -8294,15 +8280,15 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand
AtCommandInfo* cmd;
DBIterator *iter = db_iterator(atcommand->db);
int count = 0;
-
+
memset(line_buff,' ',CHATBOX_SIZE);
line_buff[CHATBOX_SIZE-1] = 0;
-
+
clif->message(fd, msg_txt(273)); // "Available commands:"
-
+
for (cmd = dbi_first(iter); dbi_exists(iter); cmd = dbi_next(iter)) {
size_t slen;
-
+
switch( type ) {
case COMMAND_CHARCOMMAND:
if( cmd->char_groups[pcg->get_idx(sd->group)] == 0 )
@@ -8315,10 +8301,9 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand
default:
continue;
}
-
-
+
slen = strlen(cmd->command);
-
+
// flush the text buffer if this command won't fit into it
if ( slen + cur - line_buff >= CHATBOX_SIZE )
{
@@ -8327,18 +8312,18 @@ void atcommand_commands_sub(struct map_session_data* sd, const int fd, AtCommand
memset(line_buff,' ',CHATBOX_SIZE);
line_buff[CHATBOX_SIZE-1] = 0;
}
-
+
memcpy(cur,cmd->command,slen);
cur += slen+(10-slen%10);
-
+
count++;
}
dbi_destroy(iter);
clif->message(fd,line_buff);
-
+
sprintf(atcmd_output, msg_txt(274), count); // "%d commands found."
clif->message(fd, atcmd_output);
-
+
return;
}
@@ -8360,15 +8345,15 @@ ACMD(charcommands)
return true;
}
/* for new mounts */
-ACMD(mount2) {
-
- if( sd->sc.option&(OPTION_WUGRIDER|OPTION_RIDING|OPTION_DRAGON|OPTION_MADOGEAR) ) {
+ACMD(cashmount)
+{
+ 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 {
@@ -8380,18 +8365,17 @@ ACMD(mount2) {
ACMD(accinfo) {
char query[NAME_LENGTH];
-
+
if (!message || !*message || strlen(message) > NAME_LENGTH ) {
clif->message(fd, msg_txt(1365)); // Usage: @accinfo/@accountinfo <account_id/char name>
clif->message(fd, msg_txt(1366)); // You may search partial name by making use of '%' in the search, ex. "@accinfo %Mario%" lists all characters whose name contains "Mario".
return false;
}
-
+
//remove const type
safestrncpy(query, message, NAME_LENGTH);
-
intif->request_accinfo( sd->fd, sd->bl.id, pc_get_group_level(sd), query );
-
+
return true;
}
@@ -8402,7 +8386,7 @@ ACMD(set) {
int toset = 0;
bool is_str = false;
size_t len;
-
+
if( !message || !*message || (toset = sscanf(message, "%31s %128[^\n]s", reg, val)) < 1 ) {
clif->message(fd, msg_txt(1367)); // Usage: @set <variable name> <value>
clif->message(fd, msg_txt(1368)); // Usage: ex. "@set PoringCharVar 50"
@@ -8410,7 +8394,7 @@ ACMD(set) {
clif->message(fd, msg_txt(1370)); // Usage: ex. "@set PoringCharVarSTR$" outputs its value, Super Duper String.
return false;
}
-
+
/* disabled variable types (they require a proper script state to function, so allowing them would crash the server) */
if( reg[0] == '.' ) {
clif->message(fd, msg_txt(1371)); // NPC variables may not be used with @set.
@@ -8419,29 +8403,26 @@ ACMD(set) {
clif->message(fd, msg_txt(1372)); // Instance variables may not be used with @set.
return false;
}
-
+
is_str = ( reg[strlen(reg) - 1] == '$' ) ? true : false;
-
+
if( ( len = strlen(val) ) > 1 ) {
if( val[0] == '"' && val[len-1] == '"') {
val[len-1] = '\0'; //Strip quotes.
memmove(val, val+1, len-1);
}
}
-
+
if( toset >= 2 ) {/* we only set the var if there is an val, otherwise we only output the value */
if( is_str )
script->set_var(sd, reg, (void*) val);
else
script->set_var(sd, reg, (void*)h64BPTRSIZE((atoi(val))));
-
}
-
+
CREATE(data, struct script_data,1);
-
-
+
if( is_str ) {// string variable
-
switch( reg[0] ) {
case '@':
data->u.str = pc->readregstr(sd, script->add_str(reg));
@@ -8459,7 +8440,6 @@ ACMD(set) {
data->u.str = pc_readglobalreg_str(sd, script->add_str(reg));
break;
}
-
if( data->u.str == NULL || data->u.str[0] == '\0' ) {// empty string
data->type = C_CONSTSTR;
data->u.str = "";
@@ -8467,9 +8447,7 @@ ACMD(set) {
data->type = C_STR;
data->u.str = aStrdup(data->u.str);
}
-
} else {// integer variable
-
data->type = C_INT;
switch( reg[0] ) {
case '@':
@@ -8488,10 +8466,8 @@ ACMD(set) {
data->u.num = pc_readglobalreg(sd, script->add_str(reg));
break;
}
-
}
-
-
+
switch( data->type ) {
case C_INT:
sprintf(atcmd_output,msg_txt(1373),reg,data->u.num); // %s value is now :%d
@@ -8506,11 +8482,9 @@ ACMD(set) {
sprintf(atcmd_output,msg_txt(1376),reg,data->type); // %s data type is not supported :%u
break;
}
-
clif->message(fd, atcmd_output);
-
+
aFree(data);
-
return true;
}
ACMD(reloadquestdb) {
@@ -8522,7 +8496,7 @@ ACMD(addperm) {
int perm_size = pcg->permission_count;
bool add = (strcmpi(info->command, "addperm") == 0) ? true : false;
int i;
-
+
if( !message || !*message ) {
sprintf(atcmd_output, msg_txt(1378),command); // Usage: %s <permission_name>
clif->message(fd, atcmd_output);
@@ -8533,9 +8507,8 @@ ACMD(addperm) {
}
return false;
}
-
+
ARR_FIND(0, perm_size, i, strcmpi(pcg->permissions[i].name, message) == 0);
-
if( i == perm_size ) {
sprintf(atcmd_output,msg_txt(1380),message); // '%s' is not a known permission.
clif->message(fd, atcmd_output);
@@ -8546,7 +8519,7 @@ ACMD(addperm) {
}
return false;
}
-
+
if( add && (sd->extra_temp_permissions&pcg->permissions[i].permission) ) {
sprintf(atcmd_output, msg_txt(1381),sd->status.name,pcg->permissions[i].name); // User '%s' already possesses the '%s' permission.
clif->message(fd, atcmd_output);
@@ -8562,28 +8535,26 @@ ACMD(addperm) {
clif->message(fd, atcmd_output);
}
}
-
return false;
}
-
+
if( add )
sd->extra_temp_permissions |= pcg->permissions[i].permission;
else
sd->extra_temp_permissions &=~ pcg->permissions[i].permission;
-
-
+
sprintf(atcmd_output, msg_txt(1384),sd->status.name); // User '%s' permissions updated successfully. The changes are temporary.
clif->message(fd, atcmd_output);
-
+
return true;
}
-ACMD(unloadnpcfile) {
-
+ACMD(unloadnpcfile)
+{
if( !message || !*message ) {
clif->message(fd, msg_txt(1385)); // Usage: @unloadnpcfile <file name>
return false;
}
-
+
if( npc->unloadfile(message) )
clif->message(fd, msg_txt(1386)); // File unloaded. Be aware that mapflags and monsters spawned directly are not removed.
else {
@@ -8598,39 +8569,39 @@ ACMD(cart) {
sd->status.skill[idx].lv = (x)?1:0; \
sd->status.skill[idx].flag = (x)?1:0; \
} while(0)
-
+
int val = atoi(message);
bool need_skill = pc->checkskill(sd, MC_PUSHCART) ? false : true;
unsigned int index = skill->get_index(MC_PUSHCART);
-
+
if( !message || !*message || val < 0 || val > MAX_CARTS ) {
sprintf(atcmd_output, msg_txt(1390),command,MAX_CARTS); // Unknown Cart (usage: %s <0-%d>).
clif->message(fd, atcmd_output);
return false;
}
-
+
if( val == 0 && !pc_iscarton(sd) ) {
clif->message(fd, msg_txt(1391)); // You do not possess a cart to be removed
return false;
}
-
+
if( need_skill ) {
MC_CART_MDFY(1,index);
}
-
+
if( pc->setcart(sd, val) ) {
if( need_skill ) {
MC_CART_MDFY(0,index);
}
return false;/* @cart failed */
}
-
+
if( need_skill ) {
MC_CART_MDFY(0,index);
}
-
+
clif->message(fd, msg_txt(1392)); // Cart Added
-
+
return true;
#undef MC_CART_MDFY
}
@@ -8638,20 +8609,20 @@ ACMD(cart) {
ACMD(join) {
struct hChSysCh *channel = NULL;
char name[HCHSYS_NAME_LENGTH], pass[HCHSYS_NAME_LENGTH];
-
+
if (!message || !*message || sscanf(message, "%19s %19s", name, pass) < 1) {
sprintf(atcmd_output, msg_txt(1399),command); // Unknown Channel (usage: %s <#channel_name>)
clif->message(fd, atcmd_output);
return false;
}
- if( hChSys.local && strcmpi(name + 1, hChSys.local_name) == 0 ) {
+ if (clif->hChSys->local && strcmpi(name + 1, clif->hChSys->local_name) == 0) {
if( !map->list[sd->bl.m].channel ) {
clif->chsys_mjoin(sd);
if( map->list[sd->bl.m].channel ) /* join might have refused, map has chatting capabilities disabled */
return true;
} else
channel = map->list[sd->bl.m].channel;
- } else if( hChSys.ally && sd->status.guild_id && strcmpi(name + 1, hChSys.ally_name) == 0 ) {
+ } else if (clif->hChSys->ally && sd->status.guild_id && strcmpi(name + 1, clif->hChSys->ally_name) == 0) {
struct guild *g = sd->guild;
if( !g ) return false;/* unlikely, but we wont let it crash anyway. */
channel = g->channel;
@@ -8660,14 +8631,13 @@ ACMD(join) {
clif->message(fd, atcmd_output);
return false;
}
-
+
if( !channel ) {
sprintf(atcmd_output, msg_txt(1400),name,command); // Unknown Channel '%s' (usage: %s <#channel_name>)
clif->message(fd, atcmd_output);
return false;
}
-
-
+
if( idb_exists(channel->users, sd->status.char_id) ) {
sprintf(atcmd_output, msg_txt(1436),name); // You're already in the '%s' channel
clif->message(fd, atcmd_output);
@@ -8682,14 +8652,14 @@ ACMD(join) {
return false;
}
}
-
+
if( channel->banned && idb_exists(channel->banned, sd->status.account_id) ) {
sprintf(atcmd_output, msg_txt(1438),name); // You cannot join the '%s' channel because you've been banned from it
clif->message(fd, atcmd_output);
return false;
}
-
- if( !( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) {
+
+ if (!(channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) {
sprintf(atcmd_output, msg_txt(1403),name); // You're now in the '%s' channel
clif->message(fd, atcmd_output);
}
@@ -8705,7 +8675,7 @@ ACMD(join) {
}
}
clif->chsys_join(channel,sd);
-
+
return true;
}
/* [Ind/Hercules] */
@@ -8757,7 +8727,6 @@ static inline void atcmd_channel_help(int fd, const char *command, bool can_crea
clif->message(fd, atcmd_output);
clif->message(fd, msg_txt(1463));// - adds or removes <option name> with <option value> to <channel name> channel
}
-
}
/* [Ind/Hercules] */
ACMD(channel) {
@@ -8765,13 +8734,13 @@ ACMD(channel) {
char subcmd[HCHSYS_NAME_LENGTH], sub1[HCHSYS_NAME_LENGTH], sub2[HCHSYS_NAME_LENGTH], sub3[HCHSYS_NAME_LENGTH];
unsigned char k = 0;
sub1[0] = sub2[0] = sub3[0] = '\0';
-
+
if (!message || !*message || sscanf(message, "%19s %19s %19s %19s", subcmd, sub1, sub2, sub3) < 1) {
- atcmd_channel_help(fd,command,( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ));
+ atcmd_channel_help(fd,command, (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)));
return true;
}
-
- if (strcmpi(subcmd,"create") == 0 && (hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) {
+
+ if (strcmpi(subcmd,"create") == 0 && (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN))) {
// sub1 = channel name; sub2 = password; sub3 = unused
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
@@ -8784,38 +8753,37 @@ ACMD(channel) {
clif->message(fd, msg_txt(1408)); // Channel password may not contain spaces
return false;
}
- if (strcmpi(sub1 + 1,hChSys.local_name) == 0 || strcmpi(sub1 + 1,hChSys.ally_name) == 0 || strdb_exists(clif->channel_db, sub1 + 1)) {
+ if (strcmpi(sub1 + 1, clif->hChSys->local_name) == 0 || strcmpi(sub1 + 1, clif->hChSys->ally_name) == 0 || strdb_exists(clif->channel_db, sub1 + 1)) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
-
+
CREATE( channel, struct hChSysCh, 1 );
-
clif->chsys_create(channel,sub1 + 1,sub2,0);
-
+
channel->owner = sd->status.char_id;
channel->type = hChSys_PRIVATE;
-
+
if( !( channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) {
sprintf(atcmd_output, msg_txt(1403),sub1); // You're now in the '%s' channel
clif->message(fd, atcmd_output);
}
-
+
clif->chsys_join(channel,sd);
} else if (strcmpi(subcmd,"list") == 0) {
// sub1 = list type; sub2 = unused; sub3 = unused
if (sub1[0] != '\0' && strcmpi(sub1,"colors") == 0) {
char mout[40];
- for (k = 0; k < hChSys.colors_count; k++) {
+ for (k = 0; k < clif->hChSys->colors_count; k++) {
unsigned short msg_len = 1;
- msg_len += sprintf(mout, "[ %s list colors ] : %s",command,hChSys.colors_name[k]);
-
+ msg_len += sprintf(mout, "[ %s list colors ] : %s", command, clif->hChSys->colors_name[k]);
+
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = msg_len + 12;
WFIFOL(fd,4) = 0;
- WFIFOL(fd,8) = hChSys.colors[k];
+ WFIFOL(fd,8) = clif->hChSys->colors[k];
safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
WFIFOSET(fd, msg_len + 12);
}
@@ -8823,14 +8791,14 @@ ACMD(channel) {
DBIterator *iter = db_iterator(clif->channel_db);
bool show_all = pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ? true : false;
clif->message(fd, msg_txt(1410)); // -- Public Channels
- if (hChSys.local) {
- sprintf(atcmd_output, msg_txt(1409), hChSys.local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
+ if (clif->hChSys->local) {
+ sprintf(atcmd_output, msg_txt(1409), clif->hChSys->local_name, map->list[sd->bl.m].channel ? db_size(map->list[sd->bl.m].channel->users) : 0);// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
- if (hChSys.ally && sd->status.guild_id) {
+ if (clif->hChSys->ally && sd->status.guild_id) {
struct guild *g = sd->guild;
if( !g ) { dbi_destroy(iter); return false; }
- sprintf(atcmd_output, msg_txt(1409), hChSys.ally_name, db_size(g->channel->users));// - #%s ( %d users )
+ sprintf(atcmd_output, msg_txt(1409), clif->hChSys->ally_name, db_size(g->channel->users));// - #%s ( %d users )
clif->message(fd, atcmd_output);
}
for (channel = dbi_first(iter); dbi_exists(iter); channel = dbi_next(iter)) {
@@ -8847,30 +8815,30 @@ ACMD(channel) {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
-
+
if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
-
+
if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
-
- for (k = 0; k < hChSys.colors_count; k++) {
- if (strcmpi(sub2, hChSys.colors_name[k]) == 0)
+
+ for (k = 0; k < clif->hChSys->colors_count; k++) {
+ if (strcmpi(sub2, clif->hChSys->colors_name[k]) == 0)
break;
}
- if (k == hChSys.colors_count) {
+ if (k == clif->hChSys->colors_count) {
sprintf(atcmd_output, msg_txt(1411), sub2);// Unknown color '%s'
clif->message(fd, atcmd_output);
return false;
}
channel->color = k;
- sprintf(atcmd_output, msg_txt(1413),sub1,hChSys.colors_name[k]);// '%s' channel color updated to '%s'
+ sprintf(atcmd_output, msg_txt(1413), sub1, clif->hChSys->colors_name[k]);// '%s' channel color updated to '%s'
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"leave") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
@@ -8907,7 +8875,7 @@ ACMD(channel) {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
-
+
for (k = 0; k < sd->channel_count; k++) {
if (strcmpi(sub1+1,sd->channels[k]->name) == 0)
break;
@@ -8917,7 +8885,7 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
return false;
}
-
+
sd->gcbind = sd->channels[k];
sprintf(atcmd_output, msg_txt(1431),sub1); // Your global chat is now bound to the '%s' channel
clif->message(fd, atcmd_output);
@@ -8927,34 +8895,34 @@ ACMD(channel) {
clif->message(fd, msg_txt(1432));// Your global chat is not bound to any channel
return false;
}
-
+
sprintf(atcmd_output, msg_txt(1433),sd->gcbind->name); // Your global chat is no longer bound to the '#%s' channel
clif->message(fd, atcmd_output);
-
+
sd->gcbind = NULL;
} else if (strcmpi(subcmd,"ban") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
struct map_session_data *pl_sd = NULL;
struct hChSysBanEntry *entry = NULL;
char sub4[NAME_LENGTH]; ///< player name
-
+
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
-
+
if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
-
+
if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
-
+
if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) {
sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
@@ -8966,59 +8934,53 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
return false;
}
-
+
if (pc_has_permission(pl_sd, PC_PERM_HCHSYS_ADMIN)) {
clif->message(fd, msg_txt(1464)); // Ban failed, not possible to ban this user.
return false;
}
-
+
if (channel->banned && idb_exists(channel->banned,pl_sd->status.account_id)) {
sprintf(atcmd_output, msg_txt(1465), pl_sd->status.name);// Player '%s' is already banned from this channel
clif->message(fd, atcmd_output);
return false;
}
-
+
if (!channel->banned)
channel->banned = idb_alloc(DB_OPT_BASE|DB_OPT_ALLOW_NULL_DATA|DB_OPT_RELEASE_DATA);
-
+
CREATE(entry, struct hChSysBanEntry, 1);
-
safestrncpy(entry->name, pl_sd->status.name, NAME_LENGTH);
-
idb_put(channel->banned, pl_sd->status.account_id, entry);
-
+
clif->chsys_left(channel,pl_sd);
-
+
sprintf(atcmd_output, msg_txt(1437),pl_sd->status.name,sub1); // Player '%s' has now been banned from '%s' channel
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"unban") == 0) {
// sub1 = channel name; sub2 = unused; sub3 = unused
struct map_session_data *pl_sd = NULL;
char sub4[NAME_LENGTH]; ///< player name
-
+
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
-
if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
-
if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
-
if (!channel->banned) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
return false;
}
-
if (!message || !*message || sscanf(message, "%19s %19s %23[^\n]", subcmd, sub1, sub4) < 3) {
sprintf(atcmd_output, msg_txt(1434), sub4);// Player '%s' was not found
clif->message(fd, atcmd_output);
@@ -9030,20 +8992,18 @@ ACMD(channel) {
clif->message(fd, atcmd_output);
return false;
}
-
if (!idb_exists(channel->banned,pl_sd->status.account_id)) {
sprintf(atcmd_output, msg_txt(1440), pl_sd->status.name);// Player '%s' is not banned from this channel
clif->message(fd, atcmd_output);
return false;
}
-
+
idb_remove(channel->banned, pl_sd->status.account_id);
-
if (!db_size(channel->banned)) {
db_destroy(channel->banned);
channel->banned = NULL;
}
-
+
sprintf(atcmd_output, msg_txt(1441),pl_sd->status.name,sub1); // Player '%s' has now been unbanned from the '%s' channel
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"unbanall") == 0) {
@@ -9052,28 +9012,24 @@ ACMD(channel) {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
-
if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
-
if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
-
if (!channel->banned) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
return false;
}
-
db_destroy(channel->banned);
channel->banned = NULL;
-
+
sprintf(atcmd_output, msg_txt(1442),sub1); // Removed all bans from '%s' channel
clif->message(fd, atcmd_output);
} else if (strcmpi(subcmd,"banlist") == 0) {
@@ -9086,19 +9042,16 @@ ACMD(channel) {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
-
if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
-
if (channel->owner != sd->status.char_id && !isA) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
-
if (!channel->banned) {
sprintf(atcmd_output, msg_txt(1439), sub1);// Channel '%s' has no banned players
clif->message(fd, atcmd_output);
@@ -9106,22 +9059,19 @@ ACMD(channel) {
}
sprintf(atcmd_output, msg_txt(1443), channel->name);// -- '%s' ban list
clif->message(fd, atcmd_output);
-
+
iter = db_iterator(channel->banned);
-
for (data = iter->first(iter,&key); iter->exists(iter); data = iter->next(iter,&key)) {
struct hChSysBanEntry * entry = DB->data2ptr(data);
-
+
if (!isA)
sprintf(atcmd_output, msg_txt(1444), entry->name);// - %s %s
else
sprintf(atcmd_output, msg_txt(1445), entry->name, key.i);// - %s (%d)
-
+
clif->message(fd, atcmd_output);
}
-
dbi_destroy(iter);
-
} else if (strcmpi(subcmd,"setopt") == 0) {
// sub1 = channel name; sub2 = option name; sub3 = value
const char* opt_str[3] = {
@@ -9129,34 +9079,28 @@ ACMD(channel) {
"JoinAnnounce",
"MessageDelay",
};
-
if (sub1[0] != '#') {
clif->message(fd, msg_txt(1405));// Channel name must start with a '#'
return false;
}
-
if (!(channel = strdb_get(clif->channel_db, sub1 + 1))) {
sprintf(atcmd_output, msg_txt(1407), sub1);// Channel '%s' is not available
clif->message(fd, atcmd_output);
return false;
}
-
if (channel->owner != sd->status.char_id && !pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)) {
sprintf(atcmd_output, msg_txt(1412), sub1);// You're not the owner of channel '%s'
clif->message(fd, atcmd_output);
return false;
}
-
if (sub2[0] == '\0') {
clif->message(fd, msg_txt(1446));// You need to input a option
return false;
}
-
for (k = 1; k < 3; k++) {
if (strcmpi(sub2,opt_str[k]) == 0)
break;
}
-
if (k == 3) {
sprintf(atcmd_output, msg_txt(1447), sub2);// '%s' is not a known channel option
clif->message(fd, atcmd_output);
@@ -9167,7 +9111,6 @@ ACMD(channel) {
}
return false;
}
-
if (sub3[0] == '\0') {
if (k == hChSys_OPT_MSG_DELAY) {
sprintf(atcmd_output, msg_txt(1466), opt_str[k]);// For '%s' you need the amount of seconds (from 0 to 10)
@@ -9228,12 +9171,10 @@ ACMD(channel) {
}
}
}
-
}
} else {
- atcmd_channel_help(fd,command,( hChSys.allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN) ));
+ atcmd_channel_help(fd, command, (clif->hChSys->allow_user_channel_creation || pc_has_permission(sd, PC_PERM_HCHSYS_ADMIN)));
}
-
return true;
}
/* debug only, delete after */
@@ -9243,50 +9184,50 @@ ACMD(fontcolor) {
char mout[40];
if( !message || !*message ) {
- for( k = 0; k < hChSys.colors_count; k++ ) {
- msg_len += sprintf(mout, "[ %s ] : %s",command,hChSys.colors_name[k]);
-
+ for( k = 0; k < clif->hChSys->colors_count; k++ ) {
+ msg_len += sprintf(mout, "[ %s ] : %s", command, clif->hChSys->colors_name[k]);
+
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = msg_len + 12;
WFIFOL(fd,4) = 0;
- WFIFOL(fd,8) = hChSys.colors[k];
+ WFIFOL(fd,8) = clif->hChSys->colors[k];
safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
WFIFOSET(fd, msg_len + 12);
}
return false;
}
-
+
if( message[0] == '0' ) {
sd->fontcolor = 0;
return true;
}
-
- for( k = 0; k < hChSys.colors_count; k++ ) {
- if( strcmpi(message,hChSys.colors_name[k]) == 0 )
+
+ for( k = 0; k < clif->hChSys->colors_count; k++ ) {
+ if (strcmpi(message, clif->hChSys->colors_name[k]) == 0)
break;
}
- if( k == hChSys.colors_count ) {
+ if( k == clif->hChSys->colors_count ) {
sprintf(atcmd_output, msg_txt(1411), message);// Unknown color '%s'
clif->message(fd, atcmd_output);
return false;
}
-
+
sd->fontcolor = k + 1;
- msg_len += sprintf(mout, "Color changed to '%s'",hChSys.colors_name[k]);
-
+ msg_len += sprintf(mout, "Color changed to '%s'", clif->hChSys->colors_name[k]);
+
WFIFOHEAD(fd,msg_len + 12);
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = msg_len + 12;
WFIFOL(fd,4) = 0;
- WFIFOL(fd,8) = hChSys.colors[k];
+ WFIFOL(fd,8) = clif->hChSys->colors[k];
safestrncpy((char*)WFIFOP(fd,12), mout, msg_len);
WFIFOSET(fd, msg_len + 12);
return true;
}
ACMD(searchstore){
int val = atoi(message);
-
+
switch( val ) {
case 0://EFFECTTYPE_NORMAL
case 1://EFFECTTYPE_CASH
@@ -9297,7 +9238,6 @@ ACMD(searchstore){
}
searchstore->open(sd, 99, val);
-
return true;
}
ACMD(costume){
@@ -9320,7 +9260,7 @@ ACMD(costume){
#endif
};
unsigned short k = 0, len = ARRAYLENGTH(names);
-
+
if( !message || !*message ) {
for( k = 0; k < len; k++ ) {
if( sd->sc.data[name2id[k]] ) {
@@ -9330,7 +9270,6 @@ ACMD(costume){
return true;
}
}
-
clif->message(sd->fd,msg_txt(1472));
for( k = 0; k < len; k++ ) {
sprintf(atcmd_output,msg_txt(1471),names[k]);//-- %s
@@ -9338,7 +9277,7 @@ ACMD(costume){
}
return false;
}
-
+
for( k = 0; k < len; k++ ) {
if( sd->sc.data[name2id[k]] ) {
sprintf(atcmd_output,msg_txt(1470),names[k]);// You're already with a '%s' costume, type '@costume' to remove it.
@@ -9346,7 +9285,7 @@ ACMD(costume){
return false;
}
}
-
+
for( k = 0; k < len; k++ ) {
if( strcmpi(message,names[k]) == 0 )
break;
@@ -9356,9 +9295,9 @@ ACMD(costume){
clif->message(sd->fd,atcmd_output);
return false;
}
-
+
sc_start(NULL,&sd->bl, name2id[k], 100, 0, -1);
-
+
return true;
}
/* for debugging purposes (so users can easily provide us with debug info) */
@@ -9636,7 +9575,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),
@@ -9645,17 +9584,17 @@ void atcommand_basecommands(void) {
ACMD_DEF(skdebug),
};
int i;
-
+
for( i = 0; i < ARRAYLENGTH(atcommand_base); i++ ) {
if(!atcommand->add(atcommand_base[i].command,atcommand_base[i].func,false)) { // Should not happen if atcommand_base[] array is OK
ShowDebug("atcommand_basecommands: duplicate ACMD_DEF for '%s'.\n", atcommand_base[i].command);
continue;
}
}
-
+
/* @commands from plugins */
HPM_map_atcommands();
-
+
return;
}
#undef ACMD_DEF
@@ -9671,12 +9610,12 @@ bool atcommand_add(char *name,AtCommandFunc func, bool replace) {
CREATE(cmd, AtCommandInfo, 1);
strdb_put(atcommand->db, name, cmd);
}
-
+
safestrncpy(cmd->command, name, sizeof(cmd->command));
cmd->func = func;
cmd->help = NULL;
cmd->log = true;
-
+
return true;
}
@@ -9870,7 +9809,7 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
if( battle_config.idletime_criteria & BCIDLE_ATCOMMAND )
sd->idletime = sockt->last_tick;
-
+
//Clearing these to be used once more.
memset(command, '\0', sizeof(command));
memset(params, '\0', sizeof(params));
@@ -9896,7 +9835,7 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
) {
// Check if self or character invoking; if self == character invoked, then self invoke.
bool invokeFlag = ((*atcmd_msg == atcommand->at_symbol) ? 1 : 0);
-
+
// Check if the command initiated is a character command
if (*message == atcommand->char_symbol
&& (ssd = map->nick2sd(charname)) == NULL
@@ -9906,10 +9845,10 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
clif->message(fd, output);
return true;
}
-
+
if( binding->log ) /* log only if this command should be logged [Ind/Hercules] */
logs->atcommand(sd, atcmd_msg);
-
+
npc->do_atcmd_event((invokeFlag ? sd : ssd), command, params, binding->npc_event);
return true;
}
@@ -9947,7 +9886,7 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
}
}
}
-
+
// Check if target is valid only if confirmed that player can use command.
if (*message == atcommand->char_symbol
&& (ssd = map->nick2sd(charname)) == NULL
@@ -9961,8 +9900,7 @@ bool atcommand_exec(const int fd, struct map_session_data *sd, const char *messa
//Attempt to use the command
if ( (info->func(fd, (*atcmd_msg == atcommand->at_symbol) ? sd : ssd, command, params,info) != true) ) {
#ifdef AUTOTRADE_PERSISTENCY
- // Autotrade was successful if standalone is set
- if( ((*atcmd_msg == atcommand->at_symbol) ? sd->state.standalone : ssd->state.standalone) )
+ if( info->func == atcommand_autotrade ) /** autotrade deletes caster, so we got nothing more to do here **/
return true;
#endif
sprintf(output,msg_txt(154), command); // %s failed.
@@ -10023,7 +9961,7 @@ void atcommand_config_read(const char* config_filename) {
if (config_setting_type(command) != CONFIG_TYPE_ARRAY)
continue;
commandname = config_setting_name(command);
- if ( !( commandinfo = atcommand_exists(commandname) ) ) {
+ if ( !( commandinfo = atcommand->exists(commandname) ) ) {
ShowConfigWarning(command, "atcommand_config_read: can not set alias for non-existent command %s", commandname);
continue;
}
@@ -10050,22 +9988,22 @@ void atcommand_config_read(const char* config_filename) {
if (nolog != NULL) {
int i = 0;
int count = libconfig->setting_length(nolog);
-
+
for (i = 0; i < count; ++i) {
config_setting_t *command;
const char *commandname = NULL;
AtCommandInfo *commandinfo = NULL;
-
+
command = libconfig->setting_get_elem(nolog, i);
commandname = config_setting_name(command);
- if ( !( commandinfo = atcommand_exists(commandname) ) ) {
+ if ( !( commandinfo = atcommand->exists(commandname) ) ) {
ShowConfigWarning(command, "atcommand_config_read: can not disable logging for non-existent command %s", commandname);
continue;
}
commandinfo->log = false;
}
}
-
+
// Commands help
// We only check if all commands exist
help = libconfig->lookup(&atcommand_config, "help");
@@ -10080,7 +10018,7 @@ void atcommand_config_read(const char* config_filename) {
command = libconfig->setting_get_elem(help, i);
commandname = config_setting_name(command);
- if ( !( commandinfo = atcommand_exists(commandname) ) )
+ if ( !( commandinfo = atcommand->exists(commandname) ) )
ShowConfigWarning(command, "atcommand_config_read: command %s does not exist", commandname);
else {
if( commandinfo->help == NULL ) {
@@ -10094,7 +10032,7 @@ void atcommand_config_read(const char* config_filename) {
}
ShowStatus("Done reading '"CL_WHITE"%d"CL_RESET"' command aliases in '"CL_WHITE"%s"CL_RESET"'.\n", num_aliases, config_filename);
-
+
libconfig->destroy(&atcommand_config);
return;
}
@@ -10127,7 +10065,7 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command
config_setting_t *commands = commands_[i];
int result = 0;
int idx = -1;
-
+
if (group == NULL) {
ShowError("atcommand_db_load_groups: group is NULL\n");
continue;
@@ -10138,12 +10076,12 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command
ShowError("atcommand_db_load_groups: index (%d) out of bounds [0,%"PRIuS"]\n", idx, sz - 1);
continue;
}
-
+
if (pcg->has_permission(group, PC_PERM_USE_ALL_COMMANDS)) {
atcmd->at_groups[idx] = atcmd->char_groups[idx] = 1;
continue;
}
-
+
if (commands != NULL) {
config_setting_t *cmd = NULL;
@@ -10173,28 +10111,28 @@ void atcommand_db_load_groups(GroupSettings **groups, config_setting_t **command
bool atcommand_can_use(struct map_session_data *sd, const char *command) {
AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command + 1));
-
+
if (info == NULL)
return false;
-
+
if ((*command == atcommand->at_symbol && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
(*command == atcommand->char_symbol && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
return true;
}
-
+
return false;
}
bool atcommand_can_use2(struct map_session_data *sd, const char *command, AtCommandType type) {
AtCommandInfo *info = atcommand->get_info_byname(atcommand->check_alias(command));
-
+
if (info == NULL)
return false;
-
+
if ((type == COMMAND_ATCOMMAND && info->at_groups[pcg->get_idx(sd->group)] != 0) ||
(type == COMMAND_CHARCOMMAND && info->char_groups[pcg->get_idx(sd->group)] != 0) ) {
return true;
}
-
+
return false;
}
bool atcommand_hp_add(char *name, AtCommandFunc func) {
@@ -10204,7 +10142,7 @@ bool atcommand_hp_add(char *name, AtCommandFunc func) {
ShowDebug("atcommand_hp_add: Commands can't be added after server is ready, skipping '%s'...\n",name);
return false;
}
-
+
return HPM_map_add_atcommand(name,func);
}
@@ -10249,7 +10187,7 @@ void do_init_atcommand(bool minimal) {
atcommand->at_symbol = '@';
atcommand->char_symbol = '#';
atcommand->binding_count = 0;
-
+
atcommand->doload();
}
@@ -10259,15 +10197,15 @@ void do_final_atcommand(void) {
void atcommand_defaults(void) {
atcommand = &atcommand_s;
-
+
atcommand->db = NULL;
atcommand->alias_db = NULL;
-
+
memset(atcommand->msg_table, 0, sizeof(atcommand->msg_table));
-
+
atcommand->init = do_init_atcommand;
atcommand->final = do_final_atcommand;
-
+
atcommand->exec = atcommand_exec;
atcommand->create = atcommand_hp_add;
atcommand->can_use = atcommand_can_use;
diff --git a/src/map/battle.c b/src/map/battle.c
index fc159c921..ddad2c705 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -218,11 +218,11 @@ 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);
@@ -239,7 +239,7 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
status_fix_damage(target, target, dat->damage, dat->delay);
map->freeblock_unlock();
}
-
+
if( src && src->type == BL_PC && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) {
((TBL_PC*)src)->state.hold_recalc = 0;
status_calc_pc(((TBL_PC*)src),SCO_FORCE);
@@ -252,12 +252,16 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) {
int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct block_list *target, int attack_type, uint16 skill_id, uint16 skill_lv, int64 damage, enum damage_lv dmg_lv, int ddelay, bool additional_effects) {
struct delay_damage *dat;
struct status_change *sc;
+ struct block_list *d_tbl = NULL;
nullpo_ret(src);
nullpo_ret(target);
sc = status->get_sc(target);
- if( sc && sc->data[SC_DEVOTION] && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD )
+ if (sc && sc->data[SC_DEVOTION] && sc->data[SC_DEVOTION]->val1)
+ d_tbl = map->id2bl(sc->data[SC_DEVOTION]->val1);
+
+ if( d_tbl && check_distance_bl(target, d_tbl, sc->data[SC_DEVOTION]->val3) && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD )
damage = 0;
if ( !battle_config.delay_battle_damage || amotion <= 1 ) {
@@ -279,7 +283,7 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct
dat->damage = damage;
dat->dmg_lv = dmg_lv;
dat->delay = ddelay;
- dat->distance = distance_bl(src, target)+10; //Attack should connect regardless unless you teleported.
+ dat->distance = distance_bl(src, target) + (battle_config.snap_dodge ? 10 : battle_config.area_size);
dat->additional_effects = additional_effects;
dat->src_type = src->type;
if (src->type != BL_PC && amotion > 1000)
@@ -288,7 +292,7 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct
if( src->type == BL_PC ) {
((TBL_PC*)src)->delayed_damage++;
}
-
+
timer->add(tick+amotion, battle->delay_damage_sub, 0, (intptr_t)dat);
return 0;
@@ -397,24 +401,7 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d
break;
}
} //end tsc check
- if( src && src->type == BL_PC ){
- struct map_session_data *sd = BL_CAST(BL_PC, src);
- int s;
-
- ARR_FIND(1, 6, s, sd->charm[s] > 0);
-
- if( s < 5 && atk_elem == s )
- ratio += sd->charm[s] * 2; // +2% custom value
- }
- if( target && target->type == BL_PC ) {
- struct map_session_data *tsd = BL_CAST(BL_PC, target);
- int t;
- ARR_FIND(1, 6, t, tsd->charm[t] > 0);
-
- if( t < 5 && atk_elem == t )
- damage -= damage * ( tsd->charm[t] * 3 ) / 100;// -3% custom value
- }
if( ratio < 100 )
return damage - (damage * (100 - ratio) / 100);
else
@@ -433,13 +420,13 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
sd = BL_CAST(BL_PC, src);
damage = status->get_weapon_atk(src, watk, flag);
-
+
if( sd ){
if( type == EQI_HAND_R )
damage = battle->calc_sizefix(sd, damage, EQI_HAND_R, size, flag&8);
else
damage = battle->calc_sizefix(sd, damage, EQI_HAND_L, size, flag&8);
-
+
if( flag&2 && sd->bonus.arrow_atk )
damage += sd->bonus.arrow_atk;
@@ -447,15 +434,18 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
eatk = sd->base_status.equip_atk;
}
+ if ( skill_id == TF_POISON )
+ eatk += 15 * skill_lv;
+
if( sc && sc->count ){
if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 )
eatk += 200;
- #ifdef RENEWAL_EDP
+#ifdef RENEWAL_EDP
if( sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ){
eatk = eatk * (sc->data[SC_EDP]->val4 / 100 - 1);
damage = damage * (sc->data[SC_EDP]->val4 / 100);
}
- #endif
+#endif
}
if( skill_id != ASC_METEORASSAULT ){
@@ -475,7 +465,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
// attacker side
damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 2|(type == EQI_HAND_L), flag2);
-
+
// target side
damage = battle->calc_cardfix(BF_WEAPON, src, bl, nk, s_ele, s_ele_, damage, 0, flag2);
@@ -500,14 +490,23 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u
int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) {
int64 damage, batk;
struct status_data *st = status->get_status_data(src);
-
- batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, status->get_sc(src), st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag);
+ struct status_change *sc = status->get_sc(src);
+
+ if (src->type == BL_PC){
+ // Property from mild wind bypasses it
+ if (sc && sc->data[SC_TK_SEVENWIND])
+ batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, s_ele, s_ele_, false, flag);
+ else
+ batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag);
+ if (type == EQI_HAND_L)
+ damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4;
+ else
+ damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2);
+ }
+ else{
+ damage = st->batk + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2);
+ }
- if( type == EQI_HAND_L )
- damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4;
- else
- damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2);
-
return damage;
}
int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, struct status_change *sc, unsigned short t_size, struct map_session_data *sd, int flag) {
@@ -654,10 +653,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);
@@ -717,14 +716,14 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
nullpo_ret(src);
nullpo_ret(target);
-
+
sc = status->get_sc(src);
sd = BL_CAST(BL_PC, src);
tstatus = status->get_status_data(target);
if ( !sd )
return damage;
-
+
damage = battle->add_mastery(sd, target, damage, left);
switch( skill_id ){ // specific skill masteries
@@ -759,7 +758,7 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
damage += 40 * pc->checkskill(sd, RA_RESEARCHTRAP);
break;
}
-
+
if( sc ){ // sc considered as masteries
if(sc->data[SC_GN_CARTBOOST])
damage += 10 * sc->data[SC_GN_CARTBOOST]->val1;
@@ -771,25 +770,27 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
if(sc->data[SC_IMPOSITIO])
damage += sc->data[SC_IMPOSITIO]->val2;
if(sc->data[SC_DRUMBATTLE]){
- if(tstatus->size == SZ_MEDIUM)
+ if(tstatus->size == SZ_SMALL)
damage += sc->data[SC_DRUMBATTLE]->val2;
- else if(tstatus->size == SZ_SMALL)
+ else if(tstatus->size == SZ_MEDIUM)
damage += 10 * sc->data[SC_DRUMBATTLE]->val1;
//else no bonus for large target
}
if(sc->data[SC_GS_MADNESSCANCEL])
damage += 100;
if(sc->data[SC_GS_GATLINGFEVER]){
- if(tstatus->size == SZ_MEDIUM)
+ if(tstatus->size == SZ_SMALL)
damage += 10 * sc->data[SC_GS_GATLINGFEVER]->val1;
- else if(tstatus->size == SZ_SMALL)
+ else if(tstatus->size == SZ_MEDIUM)
damage += -5 * sc->data[SC_GS_GATLINGFEVER]->val1;
else
damage += sc->data[SC_GS_GATLINGFEVER]->val1;
}
- //if(sc->data[SC_SPECIALZONE])
- // damage += sc->data[SC_SPECIALZONE]->val2 >> 4;
-#endif
+#if 0
+ if(sc->data[SC_SPECIALZONE])
+ damage += sc->data[SC_SPECIALZONE]->val2 >> 4;
+#endif // 0
+#endif // RENEWAL
}
// general skill masteries
@@ -841,12 +842,12 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target,
*------------------------------------------*/
int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){
struct status_data *tstatus;
-
+
nullpo_ret(src);
nullpo_ret(target);
tstatus = status->get_status_data(target);
-
+
if( (nk&NK_NO_ELEFIX) || n_ele )
return damage;
@@ -865,12 +866,12 @@ int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint
damage += battle->attr_fix(src,target,50*skill_lv,ELE_NEUTRAL,tstatus->def_ele, tstatus->ele_lv);
}
}
-
+
#ifndef RENEWAL
{
struct status_data *sstatus;
struct status_change *sc;
-
+
sstatus = status->get_status_data(src);
sc = status->get_sc(src);
@@ -889,8 +890,8 @@ int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint
/*==========================================
* Calculates card bonuses damage adjustments.
* cflag(cardfix flag):
- * &1 - calc for left hand.
- * &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON).
+ * &1 - calc for left hand.
+ * &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON).
*------------------------------------------*/
int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag){
struct map_session_data *sd, *tsd;
@@ -900,7 +901,7 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
if( !damage )
return 0;
-
+
nullpo_ret(src);
nullpo_ret(target);
@@ -911,7 +912,7 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
sstatus = status->get_status_data(src);
tstatus = status->get_status_data(target);
s_race2 = status->get_race2(src);
-
+
switch(attack_type){
case BF_MAGIC:
if ( sd && !(nk&NK_NO_CARDFIX_ATK) ) {
@@ -1124,7 +1125,7 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_
}
}
cardfix = cardfix * (100-tsd->subsize[sstatus->size]) / 100;
- cardfix = cardfix * (100-tsd->subrace2[s_race2]) / 100;
+ cardfix = cardfix * (100-tsd->subrace2[s_race2]) / 100;
cardfix = cardfix * (100-tsd->subrace[sstatus->race]) / 100;
cardfix = cardfix * (100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100;
if( sstatus->race != RC_DEMIHUMAN )
@@ -1202,13 +1203,13 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
struct map_session_data *sd, *tsd;
struct status_change *sc, *tsc;
int i;
-
+
if( !damage )
return 0;
-
+
nullpo_ret(src);
nullpo_ret(target);
-
+
sd = BL_CAST(BL_PC, src);
tsd = BL_CAST(BL_PC, target);
sstatus = status->get_status_data(src);
@@ -1219,10 +1220,10 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
switch(attack_type){
case BF_WEAPON:
{
- /** Take note in RE
- * def1 = equip def
- * def2 = status def
- **/
+ /* Take note in RE
+ * def1 = equip def
+ * def2 = status def
+ */
defType def1 = status->get_def(target); //Don't use tstatus->def1 due to skill timer reductions.
short def2 = tstatus->def2, vit_def;
#ifdef RENEWAL
@@ -1233,14 +1234,16 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
def2 = status->calc_def2(target, tsc, def2, false); // status def(RE)
#endif
- if( sd ){
- i = sd->ignore_def[is_boss(target)?RC_BOSS:RC_NONBOSS];
+ if ( sd ) {
+ i = sd->ignore_def[is_boss(target) ? RC_BOSS : RC_NONBOSS];
i += sd->ignore_def[tstatus->race];
- if( i ){
- if( i > 100 ) i = 100;
+ if ( i ) {
+ if ( i > 100 ) i = 100;
def1 -= def1 * i / 100;
def2 -= def2 * i / 100;
}
+ if ( sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] > 0 ) // hidden from status window
+ def1 += 10 * def1 * sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] / 100;
}
if( sc && sc->data[SC_EXPIATIO] ){
@@ -1248,7 +1251,7 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
def1 -= def1 * i / 100;
def2 -= def2 * i / 100;
}
-
+
if( battle_config.vit_penalty_type && battle_config.vit_penalty_target&target->type ) {
unsigned char target_count; //256 max targets should be a sane max
target_count = unit->counttargeted(target);
@@ -1267,8 +1270,8 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
if(def2 < 1) def2 = 1;
}
//Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def
- if (tsd) //Sd vit-eq
- {
+ if (tsd) {
+ //Sd vit-eq
#ifndef RENEWAL
//[VIT*0.5] + rnd([VIT*0.3], max([VIT*0.3],[VIT^2/150]-1))
vit_def = def2*(def2-15)/150;
@@ -1292,7 +1295,7 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
vit_def = def2;
#endif
}
-
+
if (battle_config.weapon_defense_type) {
vit_def += def1*battle_config.weapon_defense_type;
def1 = 0;
@@ -1316,7 +1319,6 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
else
damage = (int)((100.0f - def1 / (def1 + 400.0f) * 90.0f) / 100.0f * damage - vit_def);
}
-
#else
if( def1 > 100 ) def1 = 100;
if( !(flag&1) ){
@@ -1332,7 +1334,7 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
break;
case BF_MAGIC:
- {
+ {
defType mdef = tstatus->mdef;
short mdef2= tstatus->mdef2;
#ifdef RENEWAL
@@ -1370,7 +1372,7 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
else
damage = damage * (100-mdef)/100 - mdef2;
#endif
- }
+ }
break;
}
return damage;
@@ -1396,7 +1398,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
int i;
struct status_change *sc, *tsc;
struct map_session_data *sd, *tsd;
- struct status_data *st, *tst;
+ struct status_data *st, *tst, *bst;
nullpo_ret(src);
nullpo_ret(target);
@@ -1406,6 +1408,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
sc = status->get_sc(src);
tsc = status->get_sc(target);
st = status->get_status_data(src);
+ bst = status->get_base_status(src);
tst = status->get_status_data(target);
switch(attack_type){
@@ -1452,9 +1455,9 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case WZ_FIREPILLAR:
if (skill_lv > 10)
- skillratio += 100;
+ skillratio += 2300; //200% MATK each hit
else
- skillratio -= 80;
+ skillratio += -60 + 20*skill_lv; //20% MATK each hit
break;
case WZ_SIGHTRASHER:
skillratio += 20 * skill_lv;
@@ -1479,20 +1482,38 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case NJ_KOUENKA:
skillratio -= 10;
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 )
+ skillratio += 20 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE];
break;
case NJ_KAENSIN:
skillratio -= 50;
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 )
+ skillratio += 10 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE];
break;
case NJ_BAKUENRYU:
- skillratio += 50 * (skill_lv-1);
+ skillratio += 50 * (skill_lv - 1);
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE] > 0 )
+ skillratio += 15 * sd->spiritcharm[SPIRITS_TYPE_CHARM_FIRE];
break;
+#ifdef RENEWAL
+ case NJ_HYOUSENSOU:
+ skillratio -= 30;
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER] > 0 )
+ skillratio += 5 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER];
+#endif
case NJ_HYOUSYOURAKU:
skillratio += 50 * skill_lv;
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER] > 0 )
+ skillratio += 25 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WATER];
break;
case NJ_RAIGEKISAI:
skillratio += 60 + 40 * skill_lv;
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 )
+ skillratio += 15 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND];
break;
case NJ_KAMAITACHI:
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 )
+ skillratio += 10 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND];
case NPC_ENERGYDRAIN:
skillratio += 100 * skill_lv;
break;
@@ -1505,19 +1526,21 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 25;
break;
case WZ_VERMILION:
- {
- int interval = 0, per = interval, ratio = per;
- while( (per++) < skill_lv ){
- ratio += interval;
- if(per%3==0) interval += 20;
- }
- if( skill_lv > 9 )
- ratio -= 10;
- skillratio += ratio;
+ {
+ int interval = 0, per = interval, ratio = per;
+ while( (per++) < skill_lv ){
+ ratio += interval;
+ if(per%3==0) interval += 20;
}
+ if( skill_lv > 9 )
+ ratio -= 10;
+ skillratio += ratio;
+ }
break;
case NJ_HUUJIN:
skillratio += 50;
+ if ( sd && sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND] > 0 )
+ skillratio += 20 * sd->spiritcharm[SPIRITS_TYPE_CHARM_WIND];
break;
#else
case WZ_VERMILION:
@@ -1739,12 +1762,12 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 100 * skill_lv;
break;
case KO_KAIHOU:
- if( sd ){
- ARR_FIND(1, 6, i, sd->charm[i] > 0);
- if( i < 5 ){
- skillratio += -100 + 200 * sd->charm[i];
+ if ( sd ) {
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
+ if ( i < SPIRITS_TYPE_SPHERE ) {
+ skillratio += -100 + 200 * sd->spiritcharm[i];
RE_LVL_DMOD(100);
- pc->del_charm(sd, sd->charm[i], i);
+ pc->del_charm(sd, sd->spiritcharm[i], i);
}
}
break;
@@ -1903,7 +1926,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
#ifndef RENEWAL
case MO_EXTREMITYFIST:
- { //Overflow check. [Skotlex]
+ {
+ //Overflow check. [Skotlex]
unsigned int ratio = skillratio + 100*(8 + st->sp/10);
//You'd need something like 6K SP to reach this max, so should be fine for most purposes.
if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased.
@@ -2054,11 +2078,6 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case NJ_KIRIKAGE:
skillratio += 100 * (skill_lv-1);
break;
-#ifdef RENEWAL
- case NJ_KUNAI:
- skillratio += 50 + 150 * skill_lv;
- break;
-#endif
case KN_CHARGEATK:
{
int k = (flag-1)/3; //+100% every 3 cells of distance
@@ -2072,10 +2091,10 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case MO_BALKYOUNG:
skillratio += 200;
break;
- case HFLI_MOON: //[orn]
+ case HFLI_MOON: //[orn]
skillratio += 10 + 110 * skill_lv;
break;
- case HFLI_SBR44: //[orn]
+ case HFLI_SBR44: //[orn]
skillratio += 100 * (skill_lv-1);
break;
case NPC_VAMPIRE_GIFT:
@@ -2196,17 +2215,17 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case NC_VULCANARM:
skillratio = 70 * skill_lv + status_get_dex(src);
- RE_LVL_DMOD(100);
+ RE_LVL_DMOD(120);
break;
case NC_FLAMELAUNCHER:
case NC_COLDSLOWER:
- skillratio += 200 + 100 * skill_lv + status_get_str(src);
- RE_LVL_DMOD(100);
+ skillratio += 200 + 300 * skill_lv;
+ RE_LVL_DMOD(150);
break;
case NC_ARMSCANNON:
switch( tst->size ) {
- case SZ_MEDIUM: skillratio = 300 + 350 * skill_lv; break; // Medium
- case SZ_SMALL: skillratio = 300 + 400 * skill_lv; break; // Small
+ case SZ_SMALL: skillratio = 300 + 350 * skill_lv; break; // Medium
+ case SZ_MEDIUM: skillratio = 300 + 400 * skill_lv; break; // Small
case SZ_BIG: skillratio = 300 + 300 * skill_lv; break; // Large
}
RE_LVL_DMOD(120);
@@ -2228,17 +2247,20 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
if( st->rhw.ele == ELE_WIND )
skillratio = skillratio * 125 / 100;
- if ( distance_bl(src, target) > 2 ) // Will deal 75% damage outside of 5x5 area.
+ if ( distance_bl(src, target) > 2 ) // Will deal 75% damage outside of 5x5 area.
skillratio = skillratio * 75 / 100;
break;
case SC_FATALMENACE:
- skillratio = 100 * (skill_lv+1) * status->get_lv(src) / 100;
+ skillratio = 100 * (skill_lv+1);
+ RE_LVL_DMOD(100);
break;
case SC_TRIANGLESHOT:
- skillratio = ( 300 + (skill_lv-1) * status_get_agi(src)/2 ) * status->get_lv(src) / 120;
+ skillratio = ( 300 + (skill_lv-1) * status_get_agi(src)/2 );
+ RE_LVL_DMOD(120);
break;
case SC_FEINTBOMB:
- skillratio = (skill_lv+1) * (st->dex/2) * (sd?sd->status.job_level:50)/10 * status->get_lv(src) / 120;
+ skillratio = (skill_lv+1) * (st->dex/2) * (sd?sd->status.job_level:50)/10;
+ RE_LVL_DMOD(120);
break;
case LG_CANNONSPEAR:
skillratio = (50 + st->str) * skill_lv;
@@ -2282,15 +2304,15 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case LG_OVERBRAND:
- skillratio += -100 + 50 * (((sd) ? pc->checkskill(sd,CR_SPEARQUICKEN) : 1) + 8 * skill_lv);
- RE_LVL_DMOD(150);
+ skillratio += -100 + 400 * skill_lv + 50 * ((sd) ? pc->checkskill(sd,CR_SPEARQUICKEN) : 1);
+ RE_LVL_DMOD(100);
break;
case LG_OVERBRAND_BRANDISH:
skillratio += -100 + 300 * skill_lv + status_get_str(src) + status_get_dex(src);
- RE_LVL_DMOD(150);
+ RE_LVL_DMOD(100);
break;
case LG_OVERBRAND_PLUSATK:
- skillratio += -100 + 100 * skill_lv;
+ skillratio = 200 * skill_lv + rnd_value( 10, 100);
RE_LVL_DMOD(100);
break;
case LG_RAYOFGENESIS:
@@ -2306,7 +2328,14 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(100);
break;
case LG_HESPERUSLIT:
- skillratio += 120 * skill_lv - 100;
+ skillratio = 120 * skill_lv;
+ if( sc && sc->data[SC_BANDING] )
+ skillratio += 200 * sc->data[SC_BANDING]->val2;
+ if( sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 5 )
+ skillratio = skillratio * 150 / 100;
+ if( sc && sc->data[SC_INSPIRATION] )
+ skillratio += 600;
+ RE_LVL_DMOD(100);
break;
case SR_DRAGONCOMBO:
skillratio += 40 * skill_lv;
@@ -2334,7 +2363,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case SR_FALLENEMPIRE:// ATK [(Skill Level x 150 + 100) x Caster Base Level / 150] %
skillratio += 150 *skill_lv;
RE_LVL_DMOD(150);
- break;
+ break;
case SR_TIGERCANNON:// ATK [((Caster consumed HP + SP) / 4) x Caster Base Level / 100] %
{
int hp = status_get_max_hp(src) * (10 + 2 * skill_lv) / 100,
@@ -2411,9 +2440,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
break;
case GN_CART_TORNADO:
{
- int strbonus = st->str; // FIXME Supposed to take only base STR, but current code wont allow that. So well just take STR for now. [Rytech]
- if ( strbonus > 130 ) // Max base stat limit on official is 130. So well allow no higher then 125 STR here. This limit prevents
- strbonus = 130; // the division from going any lower then 30 so the server wont divide by 0 if someone has 150 STR.
+ int strbonus = bst->str;
skillratio = 50 * skill_lv + (sd ? sd->cart_weight : battle_config.max_cart_weight) / 10 / (150 - strbonus) + 50 * (sd ? pc->checkskill(sd, GN_REMODELING_CART) : 5);
}
break;
@@ -2489,6 +2516,7 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
RE_LVL_DMOD(120);
if( tsc && tsc->data[SC_KO_JYUMONJIKIRI] )
skillratio += status->get_lv(src) * skill_lv;
+ break;
case KO_HUUMARANKA:
skillratio += -100 + 150 * skill_lv + status_get_agi(src) + status_get_dex(src) + 100 * (sd ? pc->checkskill(sd, NJ_HUUMA) : 0);
break;
@@ -2496,11 +2524,6 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += -100 + 100 * skill_lv;
RE_LVL_DMOD(100);
break;
- case KO_BAKURETSU:
- skillratio += -100 + (50 + status_get_dex(src) / 4) * skill_lv * (sd?pc->checkskill(sd,NJ_TOBIDOUGU):10) * 4 / 100;
- RE_LVL_DMOD(120);
- skillratio += 10 * (sd ? sd->status.job_level : 0);
- break;
case MH_NEEDLE_OF_PARALYZE:
skillratio += 600 + 100 * skill_lv;
break;
@@ -2689,14 +2712,11 @@ 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 )
- {
+ if ((sce=sc->data[SC_AUTOGUARD]) && flag&BF_WEAPON && !(skill->get_nk(skill_id)&NK_NO_CARDFIX_ATK) && rnd()%100 < sce->val2) {
int delay;
- clif->skill_nodamage(bl,bl,CR_AUTOGUARD,sce->val1,1);
+ struct block_list *d_bl = NULL;
+ struct status_change_entry *sce_d = sc->data[SC_DEVOTION];
+
// different delay depending on skill level [celest]
if (sce->val1 <= 5)
delay = 300;
@@ -2704,12 +2724,31 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
delay = 200;
else
delay = 100;
- unit->set_walkdelay(bl, timer->gettick(), delay, 1);
- if(sc->data[SC_CR_SHRINK] && rnd()%100<5*sce->val1)
- skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0);
- d->dmg_lv = ATK_MISS;
- return 0;
+ if (sce_d) {
+ // If the target is too far away from the devotion caster, autoguard has no effect
+ // Autoguard will be disabled later on
+ if ((d_bl = map->id2bl(sce_d->val1)) && check_distance_bl(bl, d_bl, sce_d->val3)
+ && ((d_bl->type == BL_MER && ((TBL_MER*)d_bl)->master && ((TBL_MER*)d_bl)->master->bl.id == bl->id)
+ || (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce_d->val2] == bl->id))
+ ) {
+ // if player is target of devotion, show guard effect on the devotion caster rather than the target
+ clif->skill_nodamage(d_bl, d_bl, CR_AUTOGUARD, sce->val1, 1);
+ unit->set_walkdelay(d_bl, timer->gettick(), delay, 1);
+
+ d->dmg_lv = ATK_MISS;
+ return 0;
+ }
+ } else {
+ clif->skill_nodamage(bl, bl, CR_AUTOGUARD, sce->val1, 1);
+ unit->set_walkdelay(bl, timer->gettick(), delay, 1);
+
+ if(sc->data[SC_CR_SHRINK] && rnd()%100<5*sce->val1)
+ skill->blown(bl,src,skill->get_blewcount(CR_SHRINK,1),-1,0);
+
+ d->dmg_lv = ATK_MISS;
+ return 0;
+ }
}
if( (sce = sc->data[SC_MILLENNIUMSHIELD]) && sce->val2 > 0 && damage > 0 ) {
@@ -2745,14 +2784,14 @@ 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)
return 0;
- if((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2)
- { //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries.
+ if ((sce=sc->data[SC_KAUPE]) && rnd()%100 < sce->val2) {
+ //Kaupe blocks damage (skill or otherwise) from players, mobs, homuns, mercenaries.
clif->specialeffect(bl, 462, AREA);
//Shouldn't end until Breaker's non-weapon part connects.
if (skill_id != ASC_BREAKER || !(flag&BF_WEAPON))
@@ -2786,7 +2825,11 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
}
//Now damage increasing effects
- if( sc->data[SC_LEXAETERNA] && skill_id != PF_SOULBURN )
+ if( sc->data[SC_LEXAETERNA] && skill_id != PF_SOULBURN
+#ifdef RENEWAL
+ && skill_id != CR_ACIDDEMONSTRATION
+#endif
+ )
{
if( src->type != BL_MER || skill_id == 0 )
damage <<= 1; // Lex Aeterna only doubles damage of regular attacks from mercenaries
@@ -2862,14 +2905,21 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
if(flag&BF_SKILL) { //25% reduction
if ( !(skill->get_inf(skill_id)&INF_GROUND_SKILL) && !(skill->get_nk(skill_id)&NK_SPLASH) )
damage -= 25*damage/100;
- }
- else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON))
+ } else if ((flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON)) {
damage >>= 2; //75% reduction
+ }
}
if ( sc->data[SC_WATER_BARRIER] )
damage = damage * ( 100 - 20 ) / 100;
+ if( sc->data[SC_FIRE_EXPANSION_SMOKE_POWDER] ) {
+ if( (flag&(BF_SHORT|BF_WEAPON)) == (BF_SHORT|BF_WEAPON) )
+ damage -= 15 * damage / 100;//15% reduction to physical melee attacks
+ else if( (flag&(BF_LONG|BF_WEAPON)) == (BF_LONG|BF_WEAPON) )
+ damage -= 50 * damage / 100;//50% reduction to physical ranged attacks
+ }
+
// Compressed code, fixed by map.h [Epoque]
if (src->type == BL_MOB) {
int i;
@@ -3044,10 +3094,10 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam
status->change_spread(src, bl);
if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0)
skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY );
- if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
- TBL_HOM *hd = BL_CAST(BL_HOM,bl);
- if (hd) homun->addspiritball(hd, 10);
- }
+ if (sc->data[SC_STYLE_CHANGE] && rnd()%2) {
+ TBL_HOM *hd = BL_CAST(BL_HOM,bl);
+ if (hd) homun->addspiritball(hd, 10);
+ }
}
/* no data claims these settings affect anything other than players */
if( damage && sd && bl->type == BL_PC ) {
@@ -3124,7 +3174,7 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64
if( bl->type == BL_MOB ) {
struct mob_data* md = BL_CAST(BL_MOB, bl);
-
+
if( flag&BF_SKILL && (md->class_ == MOBID_BLUE_CRYST || md->class_ == MOBID_PINK_CRYST) )
return 0; // Crystal cannot receive skill damage on battlegrounds
}
@@ -3148,8 +3198,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;
@@ -3181,7 +3232,6 @@ int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64
*/
break;
}
-
return damage;
}
@@ -3247,11 +3297,10 @@ int battle_adjust_skill_damage(int m, unsigned short skill_id) {
if( map->list[m].skill_count ) {
int i;
ARR_FIND(0, map->list[m].skill_count, i, map->list[m].skills[i]->skill_id == skill_id );
-
+
if( i < map->list[m].skill_count ) {
return map->list[m].skills[i]->modifier;
}
-
}
return 0;
@@ -3275,17 +3324,17 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) {
struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) {
int i, nk;
short s_ele = 0;
- unsigned int skillratio = 100; //Skill dmg modifiers.
+ unsigned int skillratio = 100; //Skill dmg modifiers.
- TBL_PC *sd;
+ TBL_PC *sd;
struct status_change *sc;
struct Damage ad;
struct status_data *sstatus = status->get_status_data(src);
struct status_data *tstatus = status->get_status_data(target);
struct {
- unsigned imdef : 1;
+ unsigned imdef : 2;
unsigned infdef : 1;
- } flag;
+ } flag;
memset(&ad,0,sizeof(ad));
memset(&flag,0,sizeof(flag));
@@ -3313,9 +3362,9 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
if (s_ele == -1){ // pl=-1 : the skill takes the weapon's element
s_ele = sstatus->rhw.ele;
- if( sd ){ //Summoning 10 charm will endow your weapon
- ARR_FIND(1, 6, i, sd->charm[i] >= 10);
- if( i < 5 ) s_ele = i;
+ if( sd ){ //Summoning 10 spiritcharm will endow your weapon
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] >= MAX_SPIRITCHARM);
+ if( i < SPIRITS_TYPE_SPHERE ) s_ele = i;
}
}else if (s_ele == -2) //Use status element
s_ele = status_get_attack_sc_element(src,status->get_sc(src));
@@ -3345,11 +3394,10 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
switch(skill_id) {
case MG_FIREWALL:
- case NJ_KAENSIN:
- ad.dmotion = 0; //No flinch animation.
if ( tstatus->def_ele == ELE_FIRE || battle->check_undead(tstatus->race, tstatus->def_ele) )
ad.blewcount = 0; //No knockback
break;
+ case NJ_KAENSIN:
case PR_SANCTUARY:
ad.dmotion = 0; //No flinch animation.
break;
@@ -3359,8 +3407,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
break;
case KO_KAIHOU:
if( sd ){
- ARR_FIND(1, 6, i, sd->charm[i] > 0);
- if( i < 5 )
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
+ if( i < SPIRITS_TYPE_SPHERE )
s_ele = i;
}
break;
@@ -3368,7 +3416,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
case CR_ACIDDEMONSTRATION:
case ASC_BREAKER:
case HW_MAGICCRASHER:
- flag.imdef = 1;
+ flag.imdef = 2;
break;
#endif
}
@@ -3385,8 +3433,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
//Adds an absolute value to damage. 100 = +100 damage
#define MATK_ADD( a ) ( ad.damage+= (a) )
- switch (skill_id)
- { //Calc base damage according to skill
+ switch (skill_id) {
+ //Calc base damage according to skill
case AL_HEAL:
case PR_BENEDICTIO:
case PR_SANCTUARY:
@@ -3405,7 +3453,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
case PR_TURNUNDEAD:
//Undead check is on skill_castend_damageid code.
i = 20*skill_lv + sstatus->luk + sstatus->int_ + status->get_lv(src)
- + 200 - 200*tstatus->hp/tstatus->max_hp; // there is no changed in success chance in renewal. [malufett]
+ + 200 - 200*tstatus->hp/tstatus->max_hp; // there is no changed in success chance in renewal. [malufett]
if(i > 700) i = 700;
if(rnd()%1000 < i && !(tstatus->mode&MD_BOSS))
ad.damage = tstatus->hp;
@@ -3429,7 +3477,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
break;
default: {
MATK_ADD( status->get_matk(src, 2) );
-
+
if (nk&NK_SPLASHSPLIT) { // Divide MATK in case of multiple targets skill
if(mflag>0)
ad.damage/= mflag;
@@ -3456,7 +3504,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
}
//Constant/misc additions from skills
if (skill_id == WZ_FIREPILLAR)
- MATK_ADD(50);
+ MATK_ADD(100+50*skill_lv);
if( sd && ( sd->status.class_ == JOB_ARCH_BISHOP_T || sd->status.class_ == JOB_ARCH_BISHOP ) &&
(i=pc->checkskill(sd,AB_EUCHARISTICA)) > 0 &&
(tstatus->race == RC_DEMON || tstatus->def_ele == ELE_DARK) )
@@ -3526,11 +3574,11 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
))
flag.imdef = 1;
}
-
- ad.damage = battle->calc_defense(BF_MAGIC, src, target, skill_id, skill_lv, ad.damage, (flag.imdef?1:0), 0);
-
- if (skill_id == NPC_EARTHQUAKE)
- { //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex]
+
+ ad.damage = battle->calc_defense(BF_MAGIC, src, target, skill_id, skill_lv, ad.damage, flag.imdef, 0);
+
+ if (skill_id == NPC_EARTHQUAKE) {
+ //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex]
//Also divide the extra bonuses from atk2 based on the number in range [Kevin]
if(mflag>0)
ad.damage+= (sstatus->rhw.atk2*skillratio/100)/mflag;
@@ -3574,7 +3622,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
}
}
#ifndef RENEWAL
- ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
+ ad.damage = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, ad.damage, 0, ad.flag);
#endif
}
@@ -3582,8 +3630,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list
if (flag.infdef && ad.damage)
ad.damage = ad.damage>0?1:-1;
-
- ad.damage=battle->calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv);
+ if (skill_id != ASC_BREAKER)
+ ad.damage = battle->calc_damage(src, target, &ad, ad.damage, skill_id, skill_lv);
if( map_flag_gvg2(target->m) )
ad.damage=battle->calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag);
else if( map->list[target->m].flag.battleground )
@@ -3621,7 +3669,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
#ifdef RENEWAL
struct status_change *sc = status->get_sc(src);
#endif
-
+
memset(&md,0,sizeof(md));
nullpo_retr(md, src);
@@ -3742,7 +3790,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
}*/
}else{
float vitfactor = 0.0f, ftemp;
-
+
if( (vitfactor=(status_get_vit(target)-120.0f)) > 0)
vitfactor = (vitfactor * (matk + atk) / 10) / status_get_vit(target);
ftemp = max(0, vitfactor) + (targetVit * (matk + atk)) / 10;
@@ -3751,6 +3799,10 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage >>= 1;
}
md.damage -= totaldef;
+ if( tsc && tsc->data[SC_LEXAETERNA] ) {
+ md.damage <<= 1;
+ status_change_end(target, SC_LEXAETERNA, INVALID_TIMER);
+ }
}
#else
// updated the formula based on a Japanese formula found to be exact [Reddozen]
@@ -3764,8 +3816,8 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
if( md.damage < 0 )
md.damage = 0;
if( md.damage > INT_MAX>>1 )
- //Overflow prevention, will anyone whine if I cap it to a few billion?
- //Not capped to INT_MAX to give some room for further damage increase.
+ //Overflow prevention, will anyone whine if I cap it to a few billion?
+ //Not capped to INT_MAX to give some room for further damage increase.
md.damage = INT_MAX>>1;
break;
@@ -3787,7 +3839,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
case GS_FLING:
md.damage = sd?sd->status.job_level:status->get_lv(src);
break;
- case HVAN_EXPLOSION: //[orn]
+ case HVAN_EXPLOSION: //[orn]
md.damage = sstatus->max_hp * (50 + 50 * skill_lv) / 100;
break ;
case ASC_BREAKER:
@@ -3800,7 +3852,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
int64 matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage;
short totaldef = status->get_total_def(target) + status->get_total_mdef(target);
int64 atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag);
-
+
if( sc && sc->data[SC_EDP] )
ratio >>= 1;
md.damage = (matk + atk) * ratio / 100;
@@ -3827,7 +3879,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
**/
case RA_CLUSTERBOMB:
case RA_FIRINGTRAP:
- case RA_ICEBOUNDTRAP:
+ case RA_ICEBOUNDTRAP:
md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ;
RE_LVL_TMDMOD();
if(sd)
@@ -3867,19 +3919,21 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
md.damage = 100 + 200 * skill_lv + sstatus->int_;
break;
case GN_HELLS_PLANT_ATK:
- md.damage = skill_lv * status->get_lv(src) * 10 + sstatus->int_ * 7 / 2 * (18 + (sd ? sd->status.job_level : 0) / 4) * (5 / (10 - (sd ? pc->checkskill(sd, AM_CANNIBALIZE) : 0)));
+ md.damage = skill_lv * status->get_lv(target) * 10 + sstatus->int_ * 7 / 2 * (18 + (sd ? sd->status.job_level : 0) / 4) * (5 / (10 - (sd ? pc->checkskill(sd, AM_CANNIBALIZE) : 0)));
md.damage = md.damage*(1000 + tstatus->mdef) / (1000 + tstatus->mdef * 10) - tstatus->mdef2;
break;
case KO_HAPPOKUNAI:
{
- struct Damage wd = battle->calc_weapon_attack(src,target,skill_id,skill_lv,mflag);
+ struct Damage wd = battle->calc_weapon_attack(src, target, 0, 1, mflag);
#ifdef RENEWAL
short totaldef = status->get_total_def(target);
#else
short totaldef = tstatus->def2 + (short)status->get_def(target);
#endif
- md.damage = 3 * wd.damage * (5 + skill_lv) / 5;
+ if ( sd ) wd.damage += sd->bonus.arrow_atk;
+ md.damage = (int)(3 * (1 + wd.damage) * (5 + skill_lv) / 5.0f);
md.damage -= totaldef;
+
}
break;
}
@@ -3927,7 +3981,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
#endif
if( skill_id == KO_MUCHANAGE )
hitrate = (int)((10 - ((float)1 / (status_get_dex(src) + status_get_luk(src))) * 500) * ((float)skill_lv / 2 + 5));
-
+
hitrate = cap_value(hitrate, battle_config.min_hitrate, battle_config.max_hitrate);
if(rnd()%100 < hitrate)
@@ -3957,7 +4011,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
}
}
#endif
- md.damage = battle->calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag);
+ md.damage = battle->calc_cardfix(BF_MISC, src, target, nk, s_ele, 0, md.damage, 0, md.flag);
if(skill_id){
uint16 rskill;/* redirect skill id */
switch(skill_id){
@@ -4001,7 +4055,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
switch( skill_id ) {
case RA_FIRINGTRAP:
- case RA_ICEBOUNDTRAP:
+ case RA_ICEBOUNDTRAP:
if( md.damage == 1 ) break;
case RA_CLUSTERBOMB:
{
@@ -4027,7 +4081,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *
*------------------------------------------*/
struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag)
{
- unsigned int skillratio = 100; //Skill dmg modifiers.
+ unsigned int skillratio = 100; //Skill dmg modifiers.
short temp=0;
short s_ele, s_ele_;
int i, nk;
@@ -4040,21 +4094,21 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
struct status_data *sstatus = status->get_status_data(src);
struct status_data *tstatus = status->get_status_data(target);
struct {
- unsigned hit : 1; //the attack Hit? (not a miss)
- unsigned cri : 1; //Critical hit
- unsigned idef : 1; //Ignore defense
- unsigned idef2 : 1; //Ignore defense (left weapon)
- unsigned pdef : 2; //Pierces defense (Investigate/Ice Pick)
- unsigned pdef2 : 2; //1: Use def+def2/100, 2: Use def+def2/50
- unsigned infdef : 1; //Infinite defense (plants)
- unsigned arrow : 1; //Attack is arrow-based
- unsigned rh : 1; //Attack considers right hand (wd.damage)
- unsigned lh : 1; //Attack considers left hand (wd.damage2)
- unsigned weapon : 1; //It's a weapon attack (consider VVS, and all that)
+ unsigned hit : 1; ///< the attack Hit? (not a miss)
+ unsigned cri : 1; ///< Critical hit
+ unsigned idef : 1; ///< Ignore defense
+ unsigned idef2 : 1; ///< Ignore defense (left weapon)
+ unsigned pdef : 2; ///< Pierces defense (Investigate/Ice Pick)
+ unsigned pdef2 : 2; ///< 1: Use def+def2/100, 2: Use def+def2/50
+ unsigned infdef : 1; ///< Infinite defense (plants)
+ unsigned arrow : 1; ///< Attack is arrow-based
+ unsigned rh : 1; ///< Attack considers right hand (wd.damage)
+ unsigned lh : 1; ///< Attack considers left hand (wd.damage2)
+ unsigned weapon : 1; ///< It's a weapon attack (consider VVS, and all that)
#ifdef RENEWAL
- unsigned tdef : 1; //Total defense reduction
+ unsigned tdef : 1; ///< Total defense reduction
#endif
- } flag;
+ } flag;
memset(&wd,0,sizeof(wd));
memset(&flag,0,sizeof(flag));
@@ -4083,7 +4137,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.blewcount=skill->get_blewcount(skill_id,skill_lv);
wd.flag = BF_WEAPON; //Initial Flag
wd.flag |= (skill_id||wflag)?BF_SKILL:BF_NORMAL; // Baphomet card's splash damage is counted as a skill. [Inkfish]
- wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later
+ wd.dmg_lv=ATK_DEF; //This assumption simplifies the assignation later
nk = skill->get_nk(skill_id);
if( !skill_id && wflag ) //If flag, this is splash damage from Baphomet Card and it always hits.
nk |= NK_NO_CARDFIX_ATK|NK_IGNORE_FLEE;
@@ -4165,25 +4219,35 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case LK_SPIRALPIERCE:
if (!sd) wd.flag=(wd.flag&~(BF_RANGEMASK|BF_WEAPONMASK))|BF_LONG|BF_MISC;
break;
-
+
+ //When in banding, the number of hits is equal to the number of Royal Guards in banding.
+ case LG_HESPERUSLIT:
+ if( sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 3 )
+ wd.div_ = sc->data[SC_BANDING]->val2;
+ break;
+
case MO_INVESTIGATE:
flag.pdef = flag.pdef2 = 2;
break;
-
+
case RA_AIMEDBOLT:
if( tsc && (tsc->data[SC_WUGBITE] || tsc->data[SC_ANKLESNARE] || tsc->data[SC_ELECTRICSHOCKER]) )
wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 );
break;
#ifdef RENEWAL
+ case NJ_KUNAI:
case HW_MAGICCRASHER:
+ case NJ_SYURIKEN:
+ case GS_MAGICALBULLET:
+ case KO_BAKURETSU:
flag.tdef = 1;
break;
#endif
}
} else //Range for normal attacks.
wd.flag |= flag.arrow?BF_LONG:BF_SHORT;
- if ( (!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2 )
- { //Check for Lucky Dodge
+ if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) {
+ //Check for Lucky Dodge
wd.type=0x0b;
wd.dmg_lv=ATK_LUCKY;
if (wd.div_ < 0) wd.div_*=-1;
@@ -4195,9 +4259,9 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
{ //Take weapon's element
s_ele = sstatus->rhw.ele;
s_ele_ = sstatus->lhw.ele;
- if( sd ){ //Summoning 10 charm will endow your weapon.
- ARR_FIND(1, 6, i, sd->charm[i] >= 10);
- if( i < 5 ) s_ele = s_ele_ = i;
+ if( sd ){ //Summoning 10 spiritcharm will endow your weapon.
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] >= MAX_SPIRITCHARM);
+ if( i < SPIRITS_TYPE_SPHERE ) s_ele = s_ele_ = i;
}
if( flag.arrow && sd && sd->bonus.arrow_ele )
s_ele = sd->bonus.arrow_ele;
@@ -4216,6 +4280,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case LK_SPIRALPIERCE:
if (!sd) n_ele = false; //forced neutral for monsters
break;
+ case LG_HESPERUSLIT:
+ if ( sc && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 == 5 )
+ s_ele = ELE_HOLY; // Banding with 5 RGs: change atk element to Holy.
+ break;
}
if (!(nk & NK_NO_ELEFIX) && !n_ele)
@@ -4226,8 +4294,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
n_ele = false;
}
- if(!skill_id)
- { //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
+ if(!skill_id) {
+ //Skills ALWAYS use ONLY your right-hand weapon (tested on Aegis 10.2)
if (sd && sd->weapontype1 == 0 && sd->weapontype2 > 0)
{
flag.rh=0;
@@ -4237,11 +4305,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
flag.lh=1;
}
- if( sd && !skill_id ) { //Check for double attack.
- if( ( ( skill_lv = pc->checkskill(sd,TF_DOUBLE) ) > 0 && sd->weapontype1 == W_DAGGER )
- || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) //Will fail bare-handed
- || ( sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST )) // Need confirmation
- { //Success chance is not added, the higher one is used [Skotlex]
+ if (sd && !skill_id) {
+ //Check for double attack.
+ if (( (skill_lv=pc->checkskill(sd,TF_DOUBLE)) > 0 && sd->weapontype1 == W_DAGGER )
+ || ( sd->bonus.double_rate > 0 && sd->weapontype1 != W_FIST ) //Will fail bare-handed
+ || ( sc && sc->data[SC_KAGEMUSYA] && sd->weapontype1 != W_FIST ) // Need confirmation
+ ) {
+ //Success chance is not added, the higher one is used [Skotlex]
if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) )
{
wd.div_ = skill->get_num(TF_DOUBLE,skill_lv?skill_lv:1);
@@ -4343,7 +4413,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
flag.idef = flag.idef2 =
#endif
flag.hit = 1;
- } else { //Check for Perfect Hit
+ } else {
+ //Check for Perfect Hit
if(sd && sd->bonus.perfect_hit > 0 && rnd()%100 < sd->bonus.perfect_hit)
flag.hit = 1;
if (sc && sc->data[SC_FUSION]) {
@@ -4366,14 +4437,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
flag.hit = 1;
}
- if (!flag.hit)
- { //Hit/Flee calculation
- short
- flee = tstatus->flee,
+ if (!flag.hit) {
+ //Hit/Flee calculation
+ short flee = tstatus->flee;
#ifdef RENEWAL
- hitrate = 0; //Default hitrate
+ short hitrate = 0; //Default hitrate
#else
- hitrate = 80; //Default hitrate
+ short hitrate = 80; //Default hitrate
#endif
if(battle_config.agi_penalty_type && battle_config.agi_penalty_target&target->type) {
@@ -4400,9 +4470,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( sd ) //in Renewal hit bonus from Vultures Eye is not anymore shown in status window
hitrate += pc->checkskill(sd,AC_VULTURE);
#endif
- if(skill_id)
- switch(skill_id)
- { //Hit skill modifiers
+ switch(skill_id) {
+ //Hit skill modifiers
//It is proven that bonus is applied on final hitrate, not hit.
case SM_BASH:
case MS_BASH:
@@ -4473,10 +4542,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
else
flag.hit = 1;
- } //End hit/miss calculation
+ } //End hit/miss calculation
- if (flag.hit && !flag.infdef) //No need to do the math for plants
- { //Hitting attack
+ if (flag.hit && !flag.infdef) { //No need to do the math for plants
+ //Hitting attack
//Assuming that 99% of the cases we will not need to check for the flag.rh... we don't.
//ATK_RATE scales the damage. 100 = no change. 50 is halved, 200 is doubled, etc
@@ -4494,8 +4563,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#define GET_NORMAL_ATTACK( f ) ( wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (f), wd.flag) )
#define GET_NORMAL_ATTACK2( f ) ( wd.damage2 = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (f), wd.flag) )
#endif
- switch (skill_id)
- { //Calc base damage according to skill
+ switch (skill_id) {
+ //Calc base damage according to skill
case PA_SACRIFICE:
wd.damage = sstatus->max_hp* 9/100;
wd.damage2 = 0;
@@ -4521,15 +4590,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(-totaldef);
if( is_boss(target) )
ATK_RATE(50);
- RE_SKILL_REDUCTION();
}
break;
case NJ_SYURIKEN: // [malufett]
GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
- wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon) - status->get_total_def(target);
- RE_SKILL_REDUCTION();
+ wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon);
break;
- case MO_EXTREMITYFIST: // [malufett]
+ case MO_EXTREMITYFIST: // [malufett]
{
short totaldef = status->get_total_def(target);
GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|8 );
@@ -4537,7 +4604,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage = (250 + 150 * skill_lv) + (10 * (status_get_sp(src)+1) * wd.damage / 100) + (8 * wd.damage);
ATK_ADD(-totaldef);
}
- RE_SKILL_REDUCTION();
}
#endif
break;
@@ -4559,10 +4625,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
i*=i;
ATK_ADD(i); //Add str bonus.
switch (tstatus->size) { //Size-fix. Is this modified by weapon perfection?
- case SZ_MEDIUM: //Medium: 125%
+ case SZ_SMALL: //Small: 125%
ATK_RATE(125);
break;
- //case SZ_SMALL: //Medium: 100%
+ //case SZ_MEDIUM: //Medium: 100%
case SZ_BIG: //Large: 75%
ATK_RATE(75);
break;
@@ -4582,7 +4648,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
} else
ATK_ADD(sstatus->rhw.atk2); //Else use Atk2
break;
- case HFLI_SBR44: //[orn]
+ case HFLI_SBR44: //[orn]
if(src->type == BL_HOM) {
wd.damage = ((TBL_HOM*)src)->homunculus.intimacy ;
break;
@@ -4648,7 +4714,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#endif
}
break;
- } //End default case
+ } //End default case
} //End switch(skill_id)
if( sc && skill_id != PA_SACRIFICE && sc->data[SC_UNLIMIT] && (wd.flag&(BF_LONG|BF_MAGIC)) == BF_LONG) {
@@ -4667,18 +4733,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
status_change_end(src, SC_EXEEDBREAK, INVALID_TIMER);
}
-
- #ifdef RENEWAL
- if( sd && skill_id == NJ_KUNAI ){
- flag.tdef = 1;
- ATK_ADD( sd->bonus.arrow_atk );
- }
- #endif
switch(skill_id){
case SR_GATEOFHELL:
- #ifdef RENEWAL
- RE_SKILL_REDUCTION();
- #endif // RENEWAL
if (wd.dmg_lv != ATK_FLEE)
ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
else
@@ -4694,14 +4750,14 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
wd.damage = wd.damage * 70 / 100;
//n_ele = true; // FIXME: This is has no effect if it's after GET_NORMAL_ATTACK (was this intended, or was it supposed to be put above?)
-
+
if (sd && index >= 0 &&
sd->inventory_data[index] &&
sd->inventory_data[index]->type == IT_WEAPON)
ATK_ADD(sd->inventory_data[index]->weight * 7 / 100);
-
+
switch (tstatus->size) {
- case SZ_MEDIUM: //Medium: 115%
+ case SZ_SMALL: //Small: 115%
ATK_RATE(115);
break;
case SZ_BIG: //Large: 85%
@@ -4710,6 +4766,17 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon);
}
#endif
+
+ case KO_BAKURETSU:
+ {
+#ifdef RENEWAL
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0));
+#endif
+ skillratio = skill_lv * (50 + status_get_dex(src) / 4);
+ skillratio = (int)(skillratio * (sd ? pc->checkskill(sd, NJ_TOBIDOUGU) : 10) * 40.f / 100.0f * status->get_lv(src) / 120);
+ ATK_RATE(skillratio + 10 * (sd ? sd->status.job_level : 0));
+ }
+ break;
default:
ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
}
@@ -4739,7 +4806,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD( status->get_matk(src, 2) );
#else
ATK_ADD( battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage );
- flag.tdef = 1;
#endif
#ifndef RENEWAL
case NJ_SYURIKEN:
@@ -4811,14 +4877,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( sc->data[SC_TRUESIGHT] )
ATK_ADDRATE(2*sc->data[SC_TRUESIGHT]->val1);
#endif
-
#ifndef RENEWAL_EDP
if( sc->data[SC_EDP] ){
switch(skill_id){
- case AS_SPLASHER:
- case AS_GRIMTOOTH:
+ case AS_SPLASHER: // Needs more info
case ASC_BREAKER:
- case AS_VENOMKNIFE:
case ASC_METEORASSAULT: break;
default:
ATK_ADDRATE(sc->data[SC_EDP]->val3);
@@ -4916,8 +4979,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
}
- if (skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS)
- { //Ignore Defense?
+ if (skill_id != CR_GRANDCROSS && skill_id != NPC_GRANDDARKNESS) {
+ //Ignore Defense?
if (!flag.idef && (
sd->right_weapon.ignore_def_ele & (1<<tstatus->def_ele) ||
sd->right_weapon.ignore_def_race & (1<<tstatus->race) ||
@@ -4959,8 +5022,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
damage_div_fix(wd.damage, wd.div_);
#endif
//Post skill/vit reduction damage increases
- if( sc )
- { //SC skill damages
+ if (sc) {
+ //SC skill damages
if(sc->data[SC_AURABLADE]
#ifndef RENEWAL
&& skill_id != LK_SPIRALPIERCE && skill_id != ML_SPIRALPIERCE
@@ -4972,7 +5035,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#endif
ATK_ADD(20*lv);
}
-
+
if( !skill_id ) {
if( sc->data[SC_ENCHANTBLADE] ) {
//[( ( Skill Lv x 20 ) + 100 ) x ( casterBaseLevel / 150 )] + casterInt
@@ -4984,7 +5047,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( sc->data[SC_GIANTGROWTH] && rnd()%100 < 15 )
ATK_ADDRATE(200); // Triple Damage
}
-
}
#ifndef RENEWAL
//Refine bonus
@@ -5014,14 +5076,12 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADDRATE(40);
#endif
} //Here ends flag.hit section, the rest of the function applies to both hitting and missing attacks
- else if(wd.div_ < 0) //Since the attack missed...
+ else if(wd.div_ < 0) //Since the attack missed...
wd.div_ *= -1;
#ifndef RENEWAL
if(sd && (temp=pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0)
ATK_ADD(temp*2);
#endif
- if(skill_id==TF_POISON)
- ATK_ADD(15*skill_lv);
#ifndef RENEWAL
wd.damage = battle->calc_elefix(src, target, skill_id, skill_lv, wd.damage, nk, n_ele, s_ele, s_ele_, false, flag.arrow);
@@ -5051,7 +5111,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
#endif
-#ifndef RENEWAL
+#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);
@@ -5062,9 +5122,9 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
//Card Fix, sd side
- wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag);
- if( flag.lh )
- wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag);
+ wd.damage = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 2, wd.flag);
+ if( flag.lh )
+ wd.damage2 = battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage2, 3, wd.flag);
if( skill_id == CR_SHIELDBOOMERANG || skill_id == PA_SHIELDCHAIN )
{ //Refine bonus applies after cards and elements.
@@ -5073,11 +5133,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(10*sd->status.inventory[index].refine);
}
}
- //Card Fix, tsd side
- if(tsd){ //if player on player then it was already measured above
+#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);
}
-#endif
if( flag.infdef ) { //Plants receive 1 damage when hit
short class_ = status->get_class(target);
if( flag.hit || wd.damage > 0 )
@@ -5101,12 +5161,14 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
if (sd) {
- if (!flag.rh && flag.lh) { //Move lh damage to the rh
+ if (!flag.rh && flag.lh) {
+ //Move lh damage to the rh
wd.damage = wd.damage2;
wd.damage2 = 0;
flag.rh=1;
flag.lh=0;
- } else if(flag.rh && flag.lh) { //Dual-wield
+ } else if(flag.rh && flag.lh) {
+ //Dual-wield
if (wd.damage) {
temp = pc->checkskill(sd,AS_RIGHT) * 10;
if( (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO )
@@ -5186,23 +5248,32 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if( wd.damage + wd.damage2 ) { //There is a total damage value
int64 damage = wd.damage + wd.damage2;
-
- if(!wd.damage2) {
- wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv);
+
+ if (!wd.damage2) {
+#ifdef RENEWAL
+ if (skill_id != ASC_BREAKER)
+#endif
+ wd.damage = battle->calc_damage(src, target, &wd, wd.damage, skill_id, skill_lv);
if( map_flag_gvg2(target->m) )
wd.damage=battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag);
else if( map->list[target->m].flag.battleground )
wd.damage=battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag);
- } else if(!wd.damage) {
- wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv);
- if( map_flag_gvg2(target->m) )
- wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag);
- else if( map->list[target->m].flag.battleground )
- wd.damage = battle->calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag);
+ }
+ else if (!wd.damage) {
+#ifdef RENEWAL
+ if (skill_id != ASC_BREAKER)
+#endif
+ wd.damage2 = battle->calc_damage(src, target, &wd, wd.damage2, skill_id, skill_lv);
+ if (map_flag_gvg2(target->m))
+ wd.damage2 = battle->calc_gvg_damage(src, target, wd.damage2, wd.div_, skill_id, skill_lv, wd.flag);
+ else if (map->list[target->m].flag.battleground)
+ wd.damage = battle->calc_bg_damage(src, target, wd.damage2, wd.div_, skill_id, skill_lv, wd.flag);
} else {
#ifdef RENEWAL
- wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv);
- wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv);
+ if( skill_id != ASC_BREAKER ){
+ wd.damage = battle->calc_damage(src, target, &wd, wd.damage, skill_id, skill_lv);
+ wd.damage2 = battle->calc_damage(src, target, &wd, wd.damage2, skill_id, skill_lv);
+ }
#else
int64 d1 = wd.damage + wd.damage2,d2 = wd.damage2;
wd.damage = battle->calc_damage(src,target,&wd,d1,skill_id,skill_lv);
@@ -5217,9 +5288,9 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.damage-=wd.damage2;
#endif
}
-
- if( src != target ) { // Don't reflect your own damage (Grand Cross)
+
+ if( src != target ) { // Don't reflect your own damage (Grand Cross)
if( wd.dmg_lv == ATK_MISS || wd.dmg_lv == ATK_BLOCK ) {
int64 prev1 = wd.damage, prev2 = wd.damage2;
@@ -5233,9 +5304,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
} else
battle->reflect_damage(target, src, &wd, skill_id);
-
}
-
}
//Reject Sword bugreport:4493 by Daegaladh
if(wd.damage && tsc && tsc->data[SC_SWORDREJECT] &&
@@ -5253,7 +5322,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
status_change_end(target, SC_SWORDREJECT, INVALID_TIMER);
}
#ifndef RENEWAL
- if(skill_id == ASC_BREAKER) { //Breaker's int-based damage (a misc attack?)
+ if(skill_id == ASC_BREAKER) {
+ //Breaker's int-based damage (a misc attack?)
struct Damage md = battle->calc_misc_attack(src, target, skill_id, skill_lv, wflag);
wd.damage += md.damage;
}
@@ -5278,7 +5348,7 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl
memset(&d,0,sizeof(d));
break;
}
-
+
#ifdef HMAP_ZONE_DAMAGE_CAP_TYPE
if( target && skill_id ) {
int i;
@@ -5299,7 +5369,7 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl
}
}
#endif
-
+
if( d.damage + d.damage2 < 1 ) { //Miss/Absorbed
//Weapon attacks should go through to cause additional effects.
if (d.dmg_lv == ATK_DEF /*&& attack_type&(BF_MAGIC|BF_MISC)*/) // Isn't it that additional effects don't apply if miss?
@@ -5410,9 +5480,18 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st
if( wd->dmg_lv >= ATK_BLOCK ) {/* yes block still applies, somehow gravity thinks it makes sense. */
if( sc ) {
- if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION ) {
- NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
+ struct status_change_entry *sce_d = sc->data[SC_DEVOTION];
+ struct block_list *d_bl = NULL;
+
+ if (sce_d && sce_d->val1)
+ d_bl = map->id2bl(sce_d->val1);
+
+ if( sc->data[SC_REFLECTSHIELD] && skill_id != WS_CARTTERMINATION && skill_id != GS_DESPERADO
+ && !(d_bl && !(wd->flag&BF_SKILL)) // It should not be a basic attack if the target is under devotion
+ && !(d_bl && sce_d && !check_distance_bl(target, d_bl, sce_d->val3)) // It should not be out of range if the target is under devotion
+ ) {
+ NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100);
#ifndef RENEWAL
rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4);
#else
@@ -5622,7 +5701,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
{
int index = sd->equip_index[EQI_AMMO];
if (index<0) {
- clif->arrow_fail(sd,0);
+ if (sd->weapontype1 > W_KATAR || sd->weapontype1 < W_HUUMA)
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
+ else
+ clif->arrow_fail(sd, 0);
return ATK_NONE;
}
//Ammo check by Ishizu-chan
@@ -5639,13 +5721,13 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t
case W_GATLING:
case W_SHOTGUN:
if (sd->inventory_data[index]->look != A_BULLET) {
- clif->arrow_fail(sd,0);
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
return ATK_NONE;
}
break;
case W_GRENADE:
if (sd->inventory_data[index]->look != A_GRENADE) {
- clif->arrow_fail(sd,0);
+ clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0);
return ATK_NONE;
}
break;
@@ -5750,6 +5832,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);
}
@@ -6033,7 +6116,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if (flag&BCT_ENEMY && ( map->getcell(m,src->x,src->y,CELL_CHKBASILICA) || map->getcell(m,target->x,target->y,CELL_CHKBASILICA) ) ) {
return -1;
}
-
+
//t_bl/s_bl hold the 'master' of the attack, while src/target are the actual
//objects involved.
if( (t_bl = battle->get_master(target)) == NULL )
@@ -6072,7 +6155,8 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres
(((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras
s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == 4 && t_bl->id != s_bl->id)) //Zanzoe
- { //Targetable by players
+ {
+ //Targetable by players
state |= BCT_ENEMY;
strip_enemy = 0;
}
@@ -6082,7 +6166,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:
@@ -6129,8 +6213,10 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
su->group->skill_id == GN_WALLOFTHORN) {
state |= BCT_ENEMY;
strip_enemy = 0;
- } else //Excepting traps and icewall, you should not be able to target skills.
+ } else {
+ //Excepting traps and icewall, you should not be able to target skills.
return 0;
+ }
}
break;
//Valid targets with no special checks here.
@@ -6141,7 +6227,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
//All else not specified is an invalid target.
default:
return 0;
- } //end switch actual target
+ } //end switch actual target
switch( t_bl->type ) { //Checks on target master
case BL_PC:
@@ -6181,6 +6267,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;
@@ -6191,6 +6278,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:
@@ -6281,7 +6373,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if( flag&(BCT_PARTY|BCT_ENEMY) ) {
int s_party = status->get_party_id(s_bl);
int s_guild = status->get_guild_id(s_bl);
-
+
if( s_party && s_party == status->get_party_id(t_bl)
&& !(map->list[m].flag.pvp && map->list[m].flag.pvp_noparty)
&& !(map_flag_gvg(m) && map->list[m].flag.gvg_noparty && !( s_guild && s_guild == status->get_guild_id(t_bl) ))
@@ -6330,7 +6422,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f
if(s_guild && t_guild && (s_guild == t_guild || (!(flag&BCT_SAMEGUILD) && guild->isallied(s_guild, t_guild))))
state |= BCT_GUILD;
}
- } //end non pvp/gvg chk rivality
+ } //end non pvp/gvg chk rivality
if( !state ) //If not an enemy, nor a guild, nor party, nor yourself, it's neutral.
state = BCT_NEUTRAL;
@@ -6355,8 +6447,7 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range
#ifndef CIRCULAR_AREA
if( src->type == BL_PC ) { // Range for players' attacks and skills should always have a circular check. [Angezerus]
- int dx = src->x - bl->x, dy = src->y - bl->y;
- if( !path->check_distance(dx, dy, range) )
+ if ( !check_distance_client_bl(src, bl, range) )
return false;
} else
#endif
@@ -6394,7 +6485,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, },
@@ -6445,7 +6536,7 @@ static const struct battle_data {
{ "monster_active_enable", &battle_config.monster_active_enable, 1, 0, 1, },
{ "monster_damage_delay_rate", &battle_config.monster_damage_delay_rate, 100, 0, INT_MAX, },
{ "monster_loot_type", &battle_config.monster_loot_type, 0, 0, 1, },
-// { "mob_skill_use", &battle_config.mob_skill_use, 1, 0, 1, }, //Deprecated
+ //{ "mob_skill_use", &battle_config.mob_skill_use, 1, 0, 1, }, //Deprecated
{ "mob_skill_rate", &battle_config.mob_skill_rate, 100, 0, INT_MAX, },
{ "mob_skill_delay", &battle_config.mob_skill_delay, 100, 0, INT_MAX, },
{ "mob_count_rate", &battle_config.mob_count_rate, 100, 0, INT_MAX, },
@@ -6571,7 +6662,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
@@ -6714,7 +6806,7 @@ static const struct battle_data {
{ "invincible.nodamage", &battle_config.invincible_nodamage, 0, 0, 1, },
{ "mob_slave_keep_target", &battle_config.mob_slave_keep_target, 0, 0, 1, },
{ "autospell_check_range", &battle_config.autospell_check_range, 0, 0, 1, },
- { "knockback_left", &battle_config.knockback_left, 1, 0, 1, },
+ { "knockback_left", &battle_config.knockback_left, 1, 0, 1, },
{ "client_reshuffle_dice", &battle_config.client_reshuffle_dice, 0, 0, 1, },
{ "client_sort_storage", &battle_config.client_sort_storage, 0, 0, 1, },
{ "feature.buying_store", &battle_config.feature_buying_store, 1, 0, 1, },
@@ -6726,6 +6818,7 @@ static const struct battle_data {
{ "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, },
{ "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, },
{ "client_emblem_max_blank_percent", &battle_config.client_emblem_max_blank_percent, 100, 0, 100, },
+
// BattleGround Settings
{ "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, },
{ "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, },
@@ -6750,6 +6843,7 @@ static const struct battle_data {
**/
{ "skill_trap_type", &battle_config.skill_trap_type, 0, 0, 1, },
{ "item_restricted_consumption_type", &battle_config.item_restricted_consumption_type,1, 0, 1, },
+ { "unequip_restricted_equipment", &battle_config.unequip_restricted_equipment, 0, 0, 3, },
{ "max_walk_path", &battle_config.max_walk_path, 17, 1, MAX_WALKPATH, },
{ "item_enabled_npc", &battle_config.item_enabled_npc, 1, 0, 1, },
{ "gm_ignore_warpable_area", &battle_config.gm_ignore_warpable_area, 0, 2, 100, },
@@ -6763,8 +6857,15 @@ static const struct battle_data {
{ "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, },
{ "case_sensitive_aegisnames", &battle_config.case_sensitive_aegisnames, 1, 0, 1, },
- { "guild_castle_invite", &battle_config.guild_castle_invite, 0, 0, 1, },
- { "guild_castle_expulsion", &battle_config.guild_castle_expulsion, 0, 0, 1, },
+ { "guild_castle_invite", &battle_config.guild_castle_invite, 0, 0, 1, },
+ { "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, },
+ { "stormgust_knockback", &battle_config.stormgust_knockback, 1, 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
/**
@@ -6805,7 +6906,7 @@ void Hercules_report(char* date, char *time_c) {
/* we get the current time */
time(&curtime);
strftime(timestring, 24, "%Y-%m-%d %H:%M:%S", localtime(&curtime));
-
+
#ifdef CIRCULAR_AREA
config |= C_CIRCULAR_AREA;
#endif
@@ -6817,7 +6918,7 @@ void Hercules_report(char* date, char *time_c) {
#ifdef CONSOLE_INPUT
config |= C_CONSOLE_INPUT;
#endif
-
+
#ifdef SCRIPT_CALLFUNC_CHECK
config |= C_SCRIPT_CALLFUNC_CHECK;
#endif
@@ -6861,7 +6962,7 @@ void Hercules_report(char* date, char *time_c) {
#ifdef PACKETVER_RE
config |= C_PACKETVER_RE;
#endif
-
+
/* non-define part */
if( map->db_use_sql_item_db )
config |= C_SQL_DB_ITEM;
@@ -7008,7 +7109,7 @@ void battle_adjust_conf(void) {
battle_config.feature_search_stores = 0;
}
#endif
-
+
#if PACKETVER < 20130724
if( battle_config.feature_banking ) {
ShowWarning("conf/battle/feature.conf banking is enabled but it requires PACKETVER 2013-07-24 or newer, disabling...\n");
@@ -7016,6 +7117,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");
@@ -7026,8 +7134,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
}
@@ -7094,15 +7202,15 @@ void do_final_battle(void) {
/* initialize the interface */
void battle_defaults(void) {
battle = &battle_s;
-
+
battle->bc = &battle_config;
-
+
memset(battle->attr_fix_table, 0, sizeof(battle->attr_fix_table));
battle->delay_damage_ers = NULL;
-
+
battle->init = do_init_battle;
battle->final = do_final_battle;
-
+
battle->calc_attack = battle_calc_attack;
battle->calc_damage = battle_calc_damage;
battle->calc_gvg_damage = battle_calc_gvg_damage;
diff --git a/src/map/battle.h b/src/map/battle.h
index dfa156796..e80e0091d 100644
--- a/src/map/battle.h
+++ b/src/map/battle.h
@@ -28,23 +28,24 @@ struct status_data;
#define MIN_CLOTH_COLOR (battle->bc->min_cloth_color)
#define MAX_CLOTH_COLOR (battle->bc->max_cloth_color)
-#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru]
+#define is_boss(bl) (status_get_mode(bl)&MD_BOSS) // Can refine later [Aru]
/**
* Enumerations
**/
-enum { // Flag of the final calculation
- BF_WEAPON = 0x0001,
- BF_MAGIC = 0x0002,
- BF_MISC = 0x0004,
- BF_SHORT = 0x0010,
- BF_LONG = 0x0040,
- BF_SKILL = 0x0100,
- BF_NORMAL = 0x0200,
- BF_WEAPONMASK=0x000f,
- BF_RANGEMASK= 0x00f0,
- BF_SKILLMASK= 0x0f00,
+enum {
+ // Flag of the final calculation
+ BF_WEAPON = 0x0001,
+ BF_MAGIC = 0x0002,
+ BF_MISC = 0x0004,
+ BF_SHORT = 0x0010,
+ BF_LONG = 0x0040,
+ BF_SKILL = 0x0100,
+ BF_NORMAL = 0x0200,
+ BF_WEAPONMASK = 0x000f,
+ BF_RANGEMASK = 0x00f0,
+ BF_SKILLMASK = 0x0f00,
};
// state of a single attack attempt; used in flee/def penalty calculations when mobbed
@@ -62,17 +63,17 @@ enum e_battle_check_target { //New definitions [Skotlex]
BCT_SELF = 0x010000,
BCT_ENEMY = 0x020000,
BCT_PARTY = 0x040000,
- BCT_GUILDALLY = 0x080000, // Only allies, NOT guildmates
+ BCT_GUILDALLY = 0x080000, ///< Only allies, NOT guildmates
BCT_NEUTRAL = 0x100000,
- BCT_SAMEGUILD = 0x200000, // No Guild Allies
-
- BCT_GUILD = 0x280000, // Guild AND allies (BCT_SAMEGUILD|BCT_GUILDALLY)
-
- BCT_NOGUILD = 0x170000, // This should be (~BCT_GUILD&BCT_ALL)
- BCT_NOPARTY = 0x3b0000, // This should be (~BCT_PARTY&BCT_ALL)
- BCT_NOENEMY = 0x3d0000, // This should be (~BCT_ENEMY&BCT_ALL)
-
- BCT_ALL = 0x3f0000, // Sum of BCT_NOONE to BCT_SAMEGUILD
+ BCT_SAMEGUILD = 0x200000, ///< No Guild Allies
+
+ BCT_GUILD = 0x280000, ///< Guild AND allies (BCT_SAMEGUILD|BCT_GUILDALLY)
+
+ BCT_NOGUILD = 0x170000, ///< This must be (~BCT_GUILD&BCT_ALL)
+ BCT_NOPARTY = 0x3b0000, ///< This must be (~BCT_PARTY&BCT_ALL)
+ BCT_NOENEMY = 0x3d0000, ///< This must be (~BCT_ENEMY&BCT_ALL)
+
+ BCT_ALL = 0x3f0000, ///< Sum of BCT_NOONE to BCT_SAMEGUILD
};
/**
@@ -86,7 +87,7 @@ struct Damage {
int amotion,dmotion;
int blewcount; //nb of knockback
int flag; //chk BF_* flag, (enum below)
- enum damage_lv dmg_lv; //ATK_LUCKY,ATK_FLEE,ATK_DEF
+ enum damage_lv dmg_lv; //ATK_LUCKY,ATK_FLEE,ATK_DEF
};
struct Battle_Config {
@@ -147,12 +148,12 @@ struct Battle_Config {
int monster_active_enable;
int monster_damage_delay_rate;
int monster_loot_type;
- int mob_skill_rate; //[Skotlex]
- int mob_skill_delay; //[Skotlex]
+ int mob_skill_rate; //[Skotlex]
+ int mob_skill_delay; //[Skotlex]
int mob_count_rate;
int no_spawn_on_player; //[Skotlex]
int force_random_spawn; //[Skotlex]
- int mob_spawn_delay, plant_spawn_delay, boss_spawn_delay; // [Skotlex]
+ int mob_spawn_delay, plant_spawn_delay, boss_spawn_delay; // [Skotlex]
int slaves_inherit_mode;
int slaves_inherit_speed;
int summons_trigger_autospells;
@@ -169,7 +170,7 @@ struct Battle_Config {
int emergency_call;
int guild_aura;
int pc_invincible_time;
-
+
int pet_catch_rate;
int pet_rename;
int pet_friendly_rate;
@@ -178,7 +179,7 @@ struct Battle_Config {
int pet_status_support;
int pet_attack_support;
int pet_damage_support;
- int pet_support_min_friendly; //[Skotlex]
+ int pet_support_min_friendly; //[Skotlex]
int pet_equip_min_friendly;
int pet_support_rate;
int pet_attack_exp_to_master;
@@ -189,7 +190,7 @@ struct Battle_Config {
int pet_max_atk2; //[Skotlex]
int pet_no_gvg; //Disables pets in gvg. [Skotlex]
int pet_equip_required;
-
+
int skill_min_damage;
int finger_offensive_type;
int heal_exp;
@@ -199,11 +200,11 @@ struct Battle_Config {
int shop_exp;
int combo_delay_rate;
int item_check;
- int item_use_interval; //[Skotlex]
+ int item_use_interval; //[Skotlex]
int cashfood_use_interval;
int wedding_modifydisplay;
- int wedding_ignorepalette; //[Skotlex]
- int xmas_ignorepalette; // [Valaris]
+ int wedding_ignorepalette; //[Skotlex]
+ int xmas_ignorepalette; // [Valaris]
int summer_ignorepalette; // [Zephyrus]
int hanbok_ignorepalette;
int natural_healhp_interval;
@@ -212,7 +213,7 @@ struct Battle_Config {
int natural_heal_weight_rate;
int arrow_decrement;
int max_aspd;
- int max_walk_speed; //Maximum walking speed after buffs [Skotlex]
+ int max_walk_speed; //Maximum walking speed after buffs [Skotlex]
int max_hp;
int max_sp;
int max_lv, aura_lv;
@@ -224,8 +225,8 @@ struct Battle_Config {
int save_clothcolor;
int undead_detect_type;
int auto_counter_type;
- int min_hitrate; //[Skotlex]
- int max_hitrate; //[Skotlex]
+ int min_hitrate; //[Skotlex]
+ int max_hitrate; //[Skotlex]
int agi_penalty_target;
int agi_penalty_type;
int agi_penalty_count;
@@ -263,33 +264,33 @@ struct Battle_Config {
int item_rate_mvp, item_rate_common, item_rate_common_boss, item_rate_card, item_rate_card_boss,
item_rate_equip, item_rate_equip_boss, item_rate_heal, item_rate_heal_boss, item_rate_use,
item_rate_use_boss, item_rate_treasure, item_rate_adddrop;
-
+
int logarithmic_drops;
- int item_drop_common_min,item_drop_common_max; // Added by TyrNemesis^
+ int item_drop_common_min,item_drop_common_max; // Added by TyrNemesis^
int item_drop_card_min,item_drop_card_max;
int item_drop_equip_min,item_drop_equip_max;
- int item_drop_mvp_min,item_drop_mvp_max; // End Addition
- int item_drop_heal_min,item_drop_heal_max; // Added by Valatris
- int item_drop_use_min,item_drop_use_max; //End
+ int item_drop_mvp_min,item_drop_mvp_max; // End Addition
+ int item_drop_heal_min,item_drop_heal_max; // Added by Valatris
+ int item_drop_use_min,item_drop_use_max; //End
int item_drop_treasure_min,item_drop_treasure_max; //by [Skotlex]
int item_drop_adddrop_min,item_drop_adddrop_max; //[Skotlex]
-
- int prevent_logout; // Added by RoVeRT
-
- int alchemist_summon_reward; // [Valaris]
+
+ int prevent_logout; // Added by RoVeRT
+
+ int alchemist_summon_reward; // [Valaris]
int drops_by_luk;
int drops_by_luk2;
- int equip_natural_break_rate; //Base Natural break rate for attacks.
+ int equip_natural_break_rate; //Base Natural break rate for attacks.
int equip_self_break_rate; //Natural & Penalty skills break rate
int equip_skill_break_rate; //Offensive skills break rate
int multi_level_up;
int max_exp_gain_rate; //Max amount of exp bar % you can get in one go.
int pk_mode;
int pk_level_range;
-
+
int manner_system; // end additions [Valaris]
int show_mob_info;
-
+
int gx_allhit;
int gx_disptype;
int devotion_level_difference;
@@ -305,13 +306,13 @@ struct Battle_Config {
int bone_drop;
int buyer_name;
int dancing_weaponswitch_fix;
-
+
// eAthena additions
int night_at_start; // added by [Yor]
int day_duration; // added by [Yor]
int night_duration; // added by [Yor]
int ban_hack_trade; // added by [Yor]
-
+
int min_hair_style; // added by [MouseJstr]
int max_hair_style; // added by [MouseJstr]
int min_hair_color; // added by [MouseJstr]
@@ -319,12 +320,12 @@ struct Battle_Config {
int min_cloth_color; // added by [MouseJstr]
int max_cloth_color; // added by [MouseJstr]
int pet_hair_style; // added by [Skotlex]
-
+
int castrate_dex_scale; // added by [MouseJstr]
int area_size; // added by [MouseJstr]
-
+
int max_def, over_def_bonus; //added by [Skotlex]
-
+
int zeny_from_mobs; // [Valaris]
int mobs_level_up; // [Valaris]
int mobs_level_up_exp_rate; // [Valaris]
@@ -344,12 +345,12 @@ struct Battle_Config {
int delay_battle_damage;
int hide_woe_damage;
int display_version;
-
- int display_hallucination; // [Skotlex]
- int use_statpoint_table; // [Skotlex]
-
+
+ int display_hallucination; // [Skotlex]
+ int use_statpoint_table; // [Skotlex]
+
int ignore_items_gender; //[Lupus]
-
+
int copyskill_restrict; // [Aru]
int berserk_cancels_buffs; // [Aru]
int mob_ai; //Configures various mob_ai settings to make them smarter or dumber(official). [Skotlex]
@@ -359,36 +360,37 @@ struct Battle_Config {
int mob_remove_delay; // Dynamic Mobs - delay before removing mobs from a map [Skotlex]
int mob_active_time; //Duration through which mobs execute their Hard AI after players leave their area of sight.
int boss_active_time;
-
- int show_hp_sp_drain, show_hp_sp_gain; //[Skotlex]
-
+
+ int show_hp_sp_drain, show_hp_sp_gain; //[Skotlex]
+
int mob_npc_event_type; //Determines on who the npc_event is executed. [Skotlex]
-
+
int character_size; // if riders have size=2, and baby class riders size=1 [Lupus]
int rare_drop_announce; // chance <= to show rare drops global announces
-
- int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex]
-
+
+ int retaliate_to_master; //Whether when a mob is attacked by another mob, it will retaliate versus the mob or the mob's master. [Skotlex]
+
int duel_allow_pvp; // [LuzZza]
int duel_allow_gvg; // [LuzZza]
int duel_allow_teleport; // [LuzZza]
int duel_autoleave_when_die; // [LuzZza]
int duel_time_interval; // [LuzZza]
int duel_only_on_same_map; // [Toms]
-
+
int skip_teleport_lv1_menu; // possibility to disable (skip) Teleport Lv1 menu, that have only two lines `Random` and `Cancel` [LuzZza]
int mob_max_skilllvl;
int allow_skill_without_day; // [Komurka]
int allow_es_magic_pc; // [Skotlex]
int skill_wall_check; // [Skotlex]
- 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]
int mob_sc_def_rate;
int pc_max_sc_def;
int mob_max_sc_def;
-
+
int sg_angel_skill_ratio;
int sg_miracle_skill_ratio;
int sg_miracle_skill_duration;
@@ -396,9 +398,9 @@ struct Battle_Config {
int override_mob_names; //Enables overriding spawn mob names with the mob_db names. [Skotlex]
int min_chat_delay; //Minimum time between client messages. [Skotlex]
int friend_auto_add; //When accepting friends, both get friended. [Skotlex]
- int hvan_explosion_intimate; // fix [albator]
+ int hvan_explosion_intimate; // fix [albator]
int hom_rename;
- int homunculus_show_growth ; //[orn]
+ int homunculus_show_growth; //[orn]
int homunculus_friendly_rate;
int quest_exp_rate;
int autotrade_mapflag;
@@ -409,13 +411,13 @@ struct Battle_Config {
int ksprotection;
int auction_feeperhour;
int auction_maximumprice;
- int homunculus_auto_vapor; //Keep Homunculus from Vaporizing when master dies. [L0ne_W0lf]
- int display_status_timers; //Show or hide skill buff/delay timers in recent clients [Sara]
- int skill_add_heal_rate; //skills that bHealPower has effect on [Inkfish]
+ int homunculus_auto_vapor; //Keep Homunculus from Vaporizing when master dies. [L0ne_W0lf]
+ int display_status_timers; //Show or hide skill buff/delay timers in recent clients [Sara]
+ int skill_add_heal_rate; //skills that bHealPower has effect on [Inkfish]
int eq_single_target_reflectable;
int invincible_nodamage;
int mob_slave_keep_target;
- int autospell_check_range; //Enable range check for autospell bonus. [L0ne_W0lf]
+ int autospell_check_range; //Enable range check for autospell bonus. [L0ne_W0lf]
int knockback_left;
int client_reshuffle_dice; // Reshuffle /dice
int client_sort_storage;
@@ -430,11 +432,11 @@ struct Battle_Config {
int client_emblem_max_blank_percent;
int hom_max_level;
int hom_S_max_level;
-
+
// [BattleGround Settings]
int bg_update_interval;
int bg_flee_penalty;
-
+
// rAthena
int max_third_parameter;
int max_baby_third_parameter;
@@ -442,29 +444,33 @@ struct Battle_Config {
int atcommand_max_stat_bypass;
int max_third_aspd;
int vcast_stat_scale;
-
+
int mvp_tomb_enabled;
-
+
int atcommand_suggestions_enabled;
int min_npc_vendchat_distance;
int atcommand_mobinfo_type;
-
+
int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95]
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;
int item_restricted_consumption_type;
+ int unequip_restricted_equipment;
int max_walk_path;
int item_enabled_npc;
int packet_obfuscation;
int idletime_criteria;
int gm_ignore_warpable_area;
-
+
int client_accept_chatdori; // [Ai4rei/Mirei]
int snovice_call_type;
int guild_notice_changemap;
-
+
int feature_banking;
int feature_auction;
@@ -473,6 +479,12 @@ struct Battle_Config {
int case_sensitive_aegisnames;
int guild_castle_invite;
int guild_castle_expulsion;
+
+ int song_timer_reset; // [csnv]
+ int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
+ int stormgust_knockback;
+
+ int feature_roulette;
};
extern struct Battle_Config battle_config;
diff --git a/src/map/battleground.c b/src/map/battleground.c
index f7131513d..190f7886d 100644
--- a/src/map/battleground.c
+++ b/src/map/battleground.c
@@ -157,11 +157,11 @@ int bg_team_leave(struct map_session_data *sd, enum bg_team_leave_type flag) {
if( bgd->logout_event[0] && flag )
npc->event(sd, bgd->logout_event, 0);
-
+
if( sd->bg_queue.arena ) {
bg->queue_pc_cleanup(sd);
}
-
+
return bgd->count;
}
@@ -267,11 +267,11 @@ int bg_send_xy_timer(int tid, int64 tick, int id, intptr_t data) {
enum bg_queue_types bg_str2teamtype (const char *str) {
char temp[200], *parse;
enum bg_queue_types type = BGQT_INVALID;
-
+
safestrncpy(temp, str, 200);
-
+
parse = strtok(temp,"|");
-
+
while (parse != NULL) {
normalize_name(parse," ");
if( strcmpi(parse,"all") == 0 )
@@ -287,7 +287,7 @@ enum bg_queue_types bg_str2teamtype (const char *str) {
}
parse = strtok(NULL,"|");
}
-
+
return type;
}
@@ -295,25 +295,24 @@ void bg_config_read(void) {
config_t bg_conf;
config_setting_t *data = NULL;
const char *config_filename = "conf/battlegrounds.conf"; // FIXME hardcoded name
-
+
if (libconfig->read_file(&bg_conf, config_filename))
return;
-
+
data = libconfig->lookup(&bg_conf, "battlegrounds");
-
+
if (data != NULL) {
config_setting_t *settings = libconfig->setting_get_elem(data, 0);
config_setting_t *arenas;
const char *delay_var;
int i, arena_count = 0, offline = 0;
-
+
if( !libconfig->setting_lookup_string(settings, "global_delay_var", &delay_var) )
delay_var = "BG_Delay_Tick";
-
+
safestrncpy(bg->gdelay_var, delay_var, BG_DELAY_VAR_LENGTH);
-
+
libconfig->setting_lookup_int(settings, "maximum_afk_seconds", &bg->mafksec);
-
libconfig->setting_lookup_bool(settings, "feature_off", &offline);
if( offline == 0 )
@@ -332,14 +331,14 @@ void bg_config_read(void) {
int maxDuration;
int fillup_duration = 0, pregame_duration = 0;
enum bg_queue_types allowedTypes;
-
+
bg->arena[i] = NULL;
-
+
if( !libconfig->setting_lookup_string(arena, "name", &aName) ) {
ShowError("bg_config_read: failed to find 'name' for arena #%d\n",i);
continue;
}
-
+
if( !libconfig->setting_lookup_string(arena, "event", &aEvent) ) {
ShowError("bg_config_read: failed to find 'event' for arena #%d\n",i);
continue;
@@ -347,7 +346,7 @@ void bg_config_read(void) {
libconfig->setting_lookup_int(arena, "minLevel", &minLevel);
libconfig->setting_lookup_int(arena, "maxLevel", &maxLevel);
-
+
if( minLevel < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' minLevel\n",minLevel,aName);
minLevel = 0;
@@ -356,16 +355,16 @@ void bg_config_read(void) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' maxLevel\n",maxLevel,aName);
maxLevel = MAX_LEVEL;
}
-
+
if( !(reward = libconfig->setting_get_member(arena, "reward")) ) {
ShowError("bg_config_read: failed to find 'reward' for arena '%s'/#%d\n",aName,i);
continue;
}
-
+
libconfig->setting_lookup_int(reward, "win", &prizeWin);
libconfig->setting_lookup_int(reward, "loss", &prizeLoss);
libconfig->setting_lookup_int(reward, "draw", &prizeDraw);
-
+
if( prizeWin < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' reward:win\n",prizeWin,aName);
prizeWin = 0;
@@ -378,11 +377,11 @@ void bg_config_read(void) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' reward:draw\n",prizeDraw,aName);
prizeDraw = 0;
}
-
+
libconfig->setting_lookup_int(arena, "minPlayers", &minPlayers);
libconfig->setting_lookup_int(arena, "maxPlayers", &maxPlayers);
libconfig->setting_lookup_int(arena, "minTeamPlayers", &minTeamPlayers);
-
+
if( minPlayers < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' minPlayers\n",minPlayers,aName);
minPlayers = 0;
@@ -400,20 +399,19 @@ void bg_config_read(void) {
ShowError("bg_config_read: failed to find 'delay_var' for arena '%s'/#%d\n",aName,i);
continue;
}
-
-
+
if( !libconfig->setting_lookup_string(arena, "allowedTypes", &aTeamTypes) ) {
ShowError("bg_config_read: failed to find 'allowedTypes' for arena '%s'/#%d\n",aName,i);
continue;
}
-
+
libconfig->setting_lookup_int(arena, "maxDuration", &maxDuration);
-
+
if( maxDuration < 0 ) {
ShowWarning("bg_config_read: invalid %d value for arena '%s' maxDuration\n",maxDuration,aName);
maxDuration = 30;
}
-
+
libconfig->setting_lookup_int(arena, "fillDuration", &fillup_duration);
libconfig->setting_lookup_int(arena, "pGameDuration", &pregame_duration);
@@ -428,9 +426,9 @@ void bg_config_read(void) {
}
allowedTypes = bg->str2teamtype(aTeamTypes);
-
+
CREATE( bg->arena[i], struct bg_arena, 1 );
-
+
bg->arena[i]->id = i;
safestrncpy(bg->arena[i]->name, aName, NAME_LENGTH);
safestrncpy(bg->arena[i]->npc_event, aEvent, EVENT_NAME_LENGTH);
@@ -455,7 +453,6 @@ void bg_config_read(void) {
}
bg->arenas = arena_count;
}
-
libconfig->destroy(&bg_conf);
}
}
@@ -493,7 +490,7 @@ void bg_queue_ready_ack (struct bg_arena *arena, struct map_session_data *sd, bo
struct hQueue *queue = &script->hq[arena->queue_id];
int i, count = 0;
sd->bg_queue.ready = 1;
-
+
for( i = 0; i < queue->size; i++ ) {
if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
if( sd->bg_queue.ready == 1 )
@@ -506,10 +503,9 @@ void bg_queue_ready_ack (struct bg_arena *arena, struct map_session_data *sd, bo
arena->begin_timer = INVALID_TIMER;
bg->begin(arena);
}
-
}
-
}
+
void bg_queue_player_cleanup(struct map_session_data *sd) {
if ( sd->bg_queue.client_has_bg_data ) {
if( sd->bg_queue.arena )
@@ -527,14 +523,14 @@ void bg_queue_player_cleanup(struct map_session_data *sd) {
void bg_match_over(struct bg_arena *arena, bool canceled) {
struct hQueue *queue = &script->hq[arena->queue_id];
int i;
-
+
if( !arena->ongoing )
return;
arena->ongoing = false;
for( i = 0; i < queue->size; i++ ) {
struct map_session_data * sd = NULL;
-
+
if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
if( sd->bg_queue.arena ) {
bg->team_leave(sd, 0);
@@ -559,7 +555,7 @@ void bg_begin(struct bg_arena *arena) {
for( i = 0; i < queue->size; i++ ) {
struct map_session_data * sd = NULL;
-
+
if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
if( sd->bg_queue.ready == 1 )
count++;
@@ -575,23 +571,21 @@ void bg_begin(struct bg_arena *arena) {
bg->match_over(arena,true);
} else {
arena->ongoing = true;
-
+
if( bg->afk_timer_id == INVALID_TIMER && bg->mafksec > 0 )
bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0);
-
+
/* TODO: make this a arena-independent var? or just .@? */
mapreg->setreg(script->add_str("$@bg_queue_id"),arena->queue_id);
mapreg->setregstr(script->add_str("$@bg_delay_var$"),bg->gdelay_var);
-
+
count = 0;
for( i = 0; i < queue->size; i++ ) {
struct map_session_data * sd = NULL;
-
+
if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
if( sd->bg_queue.ready == 1 ) {
-
mapreg->setreg(reference_uid(script->add_str("$@bg_member"), count), sd->status.account_id);
-
mapreg->setreg(reference_uid(script->add_str("$@bg_member_group"), count),
sd->bg_queue.type == BGQT_GUILD ? sd->status.guild_id :
sd->bg_queue.type == BGQT_PARTY ? sd->status.party_id :
@@ -607,7 +601,7 @@ void bg_begin(struct bg_arena *arena) {
}
}
mapreg->setreg(script->add_str("$@bg_member_size"),count);
-
+
npc->event_do(arena->npc_event);
}
}
@@ -631,7 +625,7 @@ int bg_afk_timer(int tid, int64 tick, int id, intptr_t data) {
count++;
}
mapit->free(iter);
-
+
if( count )
bg->afk_timer_id = timer->add(timer->gettick()+10000,bg->afk_timer,0,0);
else
@@ -642,10 +636,10 @@ int bg_afk_timer(int tid, int64 tick, int id, intptr_t data) {
void bg_queue_pregame(struct bg_arena *arena) {
struct hQueue *queue = &script->hq[arena->queue_id];
int i;
-
+
for( i = 0; i < queue->size; i++ ) {
struct map_session_data * sd = NULL;
-
+
if( queue->item[i] > 0 && ( sd = map->id2sd(queue->item[i]) ) ) {
clif->bgqueue_battlebegins(sd,arena->id,SELF);
}
@@ -674,17 +668,17 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q
enum BATTLEGROUNDS_QUEUE_ACK result = bg->can_queue(sd,arena,type);
struct hQueue *queue;
int i, count = 0;
-
+
if( arena->begin_timer != INVALID_TIMER || arena->ongoing ) {
clif->bgqueue_ack(sd,BGQA_FAIL_QUEUING_FINISHED,arena->id);
return;
}
-
+
if( result != BGQA_SUCCESS ) {
clif->bgqueue_ack(sd,result,arena->id);
return;
}
-
+
switch( type ) { /* guild/party already validated in can_queue */
case BGQT_PARTY: {
struct party_data *p = party->search(sd->status.party_id);
@@ -705,7 +699,7 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q
count = 1;
break;
}
-
+
if( !(queue = script->queue(arena->queue_id)) || (queue->items+count) > arena->max_players ) {
clif->bgqueue_ack(sd,BGQA_FAIL_PPL_OVERAMOUNT,arena->id);
return;
@@ -746,26 +740,24 @@ void bg_queue_add(struct map_session_data *sd, struct bg_arena *arena, enum bg_q
}
break;
}
-
clif->bgqueue_ack(sd,BGQA_SUCCESS,arena->id);
-
bg->queue_check(arena);
}
enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_arena *arena, enum bg_queue_types type) {
int tick;
unsigned int tsec;
-
+
if( !(arena->allowed_types & type) )
return BGQA_FAIL_TYPE_INVALID;
-
+
if ( sd->status.base_level > arena->max_level || sd->status.base_level < arena->min_level )
return BGQA_FAIL_LEVEL_INCORRECT;
-
+
if ( !(sd->class_&JOBL_2) ) /* TODO: maybe make this a per-arena setting, so users may make custom arenas like baby-only,whatever. */
return BGQA_FAIL_CLASS_INVALID;
-
+
tsec = (unsigned int)time(NULL);
-
+
if ( ( tick = pc_readglobalreg(sd, script->add_str(bg->gdelay_var)) ) && tsec < tick ) {
char response[100];
if( (tick-tsec) > 60 )
@@ -775,7 +767,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
clif->colormes(sd->fd,COLOR_RED,response);
return BGQA_FAIL_DESERTER;
}
-
+
if ( ( tick = pc_readglobalreg(sd, script->add_str(arena->delay_var)) ) && tsec < tick ) {
char response[100];
if( (tick-tsec) > 60 )
@@ -788,7 +780,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
if( sd->bg_queue.arena != NULL )
return BGQA_DUPLICATE_REQUEST;
-
+
switch(type) {
case BGQT_GUILD:
if( !sd->guild || !sd->state.gmaster_flag )
@@ -831,7 +823,7 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
if( !is_leader )
return BGQA_NOT_PARTY_GUILD_LEADER;
-
+
if( count < arena->min_team_players ) {
char response[100];
if( count != p->party.count && p->party.count >= arena->min_team_players )
@@ -841,7 +833,6 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
clif->colormes(sd->fd,COLOR_RED,response);
return BGQA_FAIL_TEAM_COUNT;
}
-
} else
return BGQA_NOT_PARTY_GUILD_LEADER;
}
@@ -852,7 +843,6 @@ enum BATTLEGROUNDS_QUEUE_ACK bg_canqueue(struct map_session_data *sd, struct bg_
ShowDebug("bg_canqueue: unknown/unsupported type %d\n",type);
return BGQA_DUPLICATE_REQUEST;
}
-
return BGQA_SUCCESS;
}
void do_init_battleground(bool minimal) {
@@ -867,22 +857,22 @@ void do_init_battleground(bool minimal) {
void do_final_battleground(void) {
int i;
-
+
db_destroy(bg->team_db);
-
+
for( i = 0; i < bg->arenas; i++ ) {
if( bg->arena[i] )
aFree(bg->arena[i]);
}
-
+
if( bg->arena )
aFree(bg->arena);
}
void battleground_defaults(void) {
bg = &bg_s;
-
+
bg->queue_on = false;
-
+
bg->mafksec = 0;
bg->afk_timer_id = INVALID_TIMER;
bg->arena = NULL;
diff --git a/src/map/buyingstore.c b/src/map/buyingstore.c
index 626d102a3..8efffa342 100644
--- a/src/map/buyingstore.c
+++ b/src/map/buyingstore.c
@@ -169,7 +169,7 @@ void buyingstore_create(struct map_session_data* sd, int zenylimit, unsigned cha
// success
sd->state.buyingstore = true;
- sd->buyer_id = buyingstore_getuid();
+ sd->buyer_id = buyingstore->getuid();
sd->buyingstore.zenylimit = zenylimit;
sd->buyingstore.slots = i; // store actual amount of items
safestrncpy(sd->message, storename, sizeof(sd->message));
@@ -294,8 +294,11 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
return;
}
- if( sd->status.inventory[index].expire_time || (sd->status.inventory[index].bound && !pc_can_give_bound_items(sd)) || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd)) || memcmp(sd->status.inventory[index].card, buyingstore->blankslots, sizeof(buyingstore->blankslots)) )
- {// non-tradable item
+ if (sd->status.inventory[index].expire_time || (sd->status.inventory[index].bound && !pc_can_give_bound_items(sd))
+ || !itemdb_cantrade(&sd->status.inventory[index], pc_get_group_level(sd), pc_get_group_level(pl_sd))
+ || memcmp(sd->status.inventory[index].card, buyingstore->blankslots, sizeof(buyingstore->blankslots))
+ ) {
+ // non-tradable item
clif->buyingstore_trade_failed_seller(sd, BUYINGSTORE_TRADE_SELLER_FAILED, nameid);
return;
}
@@ -367,7 +370,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
chrif->save(sd, 0);
chrif->save(pl_sd, 0);
}
-
+
// check whether or not there is still something to buy
ARR_FIND( 0, pl_sd->buyingstore.slots, i, pl_sd->buyingstore.items[i].amount != 0 );
if( i == pl_sd->buyingstore.slots )
@@ -384,7 +387,7 @@ void buyingstore_trade(struct map_session_data* sd, int account_id, unsigned int
}
// cannot continue buying
- buyingstore_close(pl_sd);
+ buyingstore->close(pl_sd);
// remove auto-trader
if( pl_sd->state.autotrade ) {
@@ -459,7 +462,7 @@ bool buyingstore_searchall(struct map_session_data* sd, const struct s_search_st
}
void buyingstore_defaults(void) {
buyingstore = &buyingstore_s;
-
+
buyingstore->nextid = 0;
memset(buyingstore->blankslots,0,sizeof(buyingstore->blankslots));
/* */
diff --git a/src/map/chat.c b/src/map/chat.c
index cd7b5f811..9c67e0f44 100644
--- a/src/map/chat.c
+++ b/src/map/chat.c
@@ -61,10 +61,10 @@ struct chat_data* chat_createchat(struct block_list* bl, const char* title, cons
}
map->addiddb(&cd->bl);
-
+
if( bl->type != BL_NPC )
cd->kick_list = idb_alloc(DB_OPT_BASE);
-
+
return cd;
}
@@ -156,20 +156,20 @@ bool chat_joinchat(struct map_session_data* sd, int chatid, const char* pass) {
pc_setchatid(sd,cd->bl.id);
- clif->joinchatok(sd, cd); //To the person who newly joined the list of all
- clif->addchat(cd, sd); //Reports To the person who already in the chat
- clif->dispchat(cd, 0); //Reported number of changes to the people around
+ clif->joinchatok(sd, cd); //To the person who newly joined the list of all
+ clif->addchat(cd, sd); //Reports To the person who already in the chat
+ clif->dispchat(cd, 0); //Reported number of changes to the people around
- chat->trigger_event(cd); //Event
+ chat->trigger_event(cd); //Event
- return true;
+ return true;
}
/*==========================================
* Leave a chatroom
* Return
- * 0: User not found in chatroom/Missing data
+ * 0: User not found in chatroom/Missing data
* 1: Success
* 2: Chat room deleted (chat room empty)
* 3: Owner changed (Owner left and a new one as assigned)
@@ -188,8 +188,8 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) {
}
ARR_FIND( 0, cd->users, i, cd->usersd[i] == sd );
- if ( i == cd->users )
- { // Not found in the chatroom?
+ if (i == cd->users) {
+ // Not found in the chatroom?
pc_setchatid(sd, 0);
return 0;
}
@@ -213,7 +213,7 @@ int chat_leavechat(struct map_session_data* sd, bool kicked) {
map->deliddb(&cd->bl);
map->delblock(&cd->bl);
map->freeblock(&cd->bl);
-
+
su = map->find_skill_unit_oncell(&sd->bl, sd->bl.x, sd->bl.y, AL_WARP, NULL, 0);
group = (su != NULL) ? su->group : NULL;
if (group != NULL)
@@ -326,7 +326,7 @@ bool chat_kickchat(struct map_session_data* sd, const char* kickusername) {
nullpo_ret(sd);
cd = (struct chat_data *)map->id2bl(sd->chatID);
-
+
if( cd==NULL || (struct block_list *)sd != cd->owner )
return false;
@@ -336,7 +336,7 @@ bool chat_kickchat(struct map_session_data* sd, const char* kickusername) {
if (pc_has_permission(cd->usersd[i], PC_PERM_NO_CHAT_KICK))
return false; //gm kick protection [Valaris]
-
+
idb_iput(cd->kick_list,cd->usersd[i]->status.char_id,1);
chat->leave(cd->usersd[i],1);
@@ -385,14 +385,14 @@ bool chat_deletenpcchat(struct npc_data* nd) {
cd = (struct chat_data*)map->id2bl(nd->chat_id);
if( cd == NULL )
return false;
-
+
chat->npc_kick_all(cd);
clif->clearchat(cd, 0);
map->deliddb(&cd->bl);
map->delblock(&cd->bl);
map->freeblock(&cd->bl);
nd->chat_id = 0;
-
+
return true;
}
@@ -452,7 +452,7 @@ bool chat_npckickall(struct chat_data* cd)
*-------------------------------------*/
void chat_defaults(void) {
chat = &chat_s;
-
+
/* funcs */
chat->create_pc_chat = chat_createpcchat;
chat->join = chat_joinchat;
diff --git a/src/map/chat.h b/src/map/chat.h
index e055c04ed..6fca018f4 100644
--- a/src/map/chat.h
+++ b/src/map/chat.h
@@ -16,21 +16,21 @@ struct npc_data;
#define MAX_CHAT_USERS 20
struct chat_data {
- struct block_list bl; // data for this map object
- char title[CHATROOM_TITLE_SIZE]; // room title
- char pass[CHATROOM_PASS_SIZE]; // password
- bool pub; // private/public flag
- uint8 users; // current user count
- uint8 limit; // join limit
- uint8 trigger; // number of users needed to trigger event
- uint32 zeny; // required zeny to join
- uint32 minLvl; // minimum base level to join
- uint32 maxLvl; // maximum base level allowed to join
+ struct block_list bl; ///< data for this map object
+ char title[CHATROOM_TITLE_SIZE]; ///< room title
+ char pass[CHATROOM_PASS_SIZE]; ///< password
+ bool pub; ///< private/public flag
+ uint8 users; ///< current user count
+ uint8 limit; ///< join limit
+ uint8 trigger; ///< number of users needed to trigger event
+ uint32 zeny; ///< required zeny to join
+ uint32 minLvl; ///< minimum base level to join
+ uint32 maxLvl; ///< maximum base level allowed to join
struct map_session_data* usersd[MAX_CHAT_USERS];
struct block_list* owner;
char npc_event[EVENT_NAME_LENGTH];
/* isn't this a waste? there is a enormous overhead, wouldn't something like skill_blockpc_start be better here? [Ind] */
- DBMap* kick_list; //DBMap of users who were kicked from this chat
+ DBMap* kick_list; ///< DBMap of users who were kicked from this chat
};
/*=====================================
@@ -39,7 +39,6 @@ struct chat_data {
* created by Susu
*-------------------------------------*/
struct chat_interface {
-
/* funcs */
bool (*create_pc_chat) (struct map_session_data* sd, const char* title, const char* pass, int limit, bool pub);
bool (*join) (struct map_session_data* sd, int chatid, const char* pass);
diff --git a/src/map/chrif.c b/src/map/chrif.c
index 4c8cd747b..a5003ab95 100644
--- a/src/map/chrif.c
+++ b/src/map/chrif.c
@@ -116,7 +116,6 @@ struct auth_node* chrif_search(int account_id) {
struct auth_node* chrif_auth_check(int account_id, int char_id, enum sd_state state) {
struct auth_node *node = chrif->search(account_id);
-
return ( node && node->char_id == char_id && node->state == state ) ? node : NULL;
}
@@ -125,24 +124,23 @@ bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) {
if ( (node = chrif->auth_check(account_id, char_id, state) ) ) {
int fd = node->sd ? node->sd->fd : node->fd;
-
+
if ( session[fd] && session[fd]->session_data == node->sd )
session[fd]->session_data = NULL;
-
+
if ( node->sd ) {
-
if( node->sd->regs.vars )
node->sd->regs.vars->destroy(node->sd->regs.vars, script->reg_destroy);
-
+
if( node->sd->regs.arrays )
node->sd->regs.arrays->destroy(node->sd->regs.arrays, script->array_free_db);
-
+
aFree(node->sd);
}
-
+
ers_free(chrif->auth_db_ers, node);
idb_remove(chrif->auth_db,account_id);
-
+
return true;
}
return false;
@@ -151,52 +149,52 @@ bool chrif_auth_delete(int account_id, int char_id, enum sd_state state) {
//Moves the sd character to the auth_db structure.
bool chrif_sd_to_auth(TBL_PC* sd, enum sd_state state) {
struct auth_node *node;
-
+
if ( chrif->search(sd->status.account_id) )
return false; //Already exists?
node = ers_alloc(chrif->auth_db_ers, struct auth_node);
-
+
memset(node, 0, sizeof(struct auth_node));
-
+
node->account_id = sd->status.account_id;
node->char_id = sd->status.char_id;
node->login_id1 = sd->login_id1;
node->login_id2 = sd->login_id2;
node->sex = sd->status.sex;
node->fd = sd->fd;
- node->sd = sd; //Data from logged on char.
+ node->sd = sd; //Data from logged on char.
node->node_created = timer->gettick(); //timestamp for node timeouts
node->state = state;
sd->state.active = 0;
-
+
idb_put(chrif->auth_db, node->account_id, node);
-
+
return true;
}
-bool chrif_auth_logout(TBL_PC* sd, enum sd_state state) {
-
+bool chrif_auth_logout(TBL_PC* sd, enum sd_state state)
+{
if(sd->fd && state == ST_LOGOUT) { //Disassociate player, and free it after saving ack returns. [Skotlex]
//fd info must not be lost for ST_MAPCHANGE as a final packet needs to be sent to the player.
if ( session[sd->fd] )
session[sd->fd]->session_data = NULL;
sd->fd = 0;
}
-
+
return chrif->sd_to_auth(sd, state);
}
bool chrif_auth_finished(TBL_PC* sd) {
struct auth_node *node= chrif->search(sd->status.account_id);
-
+
if ( node && node->sd == sd && node->state == ST_LOGIN ) {
node->sd = NULL;
-
+
return chrif->auth_delete(node->account_id, node->char_id, ST_LOGIN);
}
-
+
return false;
}
// sets char-server's user id
@@ -221,16 +219,16 @@ void chrif_checkdefaultlogin(void) {
// sets char-server's ip address
bool chrif_setip(const char* ip) {
char ip_str[16];
-
+
if ( !( chrif->ip = host2ip(ip) ) ) {
ShowWarning("Failed to Resolve Char Server Address! (%s)\n", ip);
return false;
}
-
+
safestrncpy(chrif->ip_str, ip, sizeof(chrif->ip_str));
-
+
ShowInfo("Char Server IP Address : '"CL_WHITE"%s"CL_RESET"' -> '"CL_WHITE"%s"CL_RESET"'.\n", ip, ip2str(chrif->ip, ip_str));
-
+
return true;
}
@@ -314,9 +312,9 @@ void chrif_connect(int fd) {
// sends maps to char-server
void chrif_sendmap(int fd) {
int i;
-
+
ShowStatus("Sending maps to char server...\n");
-
+
// Sending normal maps, not instances
WFIFOHEAD(fd, 4 + instance->start_id * 4);
WFIFOW(fd,0) = 0x2afa;
@@ -335,7 +333,7 @@ void chrif_recvmap(int fd) {
for(i = 10, j = 0; i < RFIFOW(fd,2); i += 4, j++) {
map->setipport(RFIFOW(fd,i), ip, port);
}
-
+
if (battle_config.etc_log)
ShowStatus("Received maps from %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
@@ -352,7 +350,7 @@ void chrif_removemap(int fd) {
map->eraseipport(RFIFOW(fd, i), ip, port);
chrif->other_mapserver_count--;
-
+
if(battle_config.etc_log)
ShowStatus("remove map of server %d.%d.%d.%d:%d (%d maps)\n", CONVIP(ip), port, j);
}
@@ -389,7 +387,7 @@ bool chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port)
WFIFOL(chrif->fd,31) = htonl(session[sd->fd]->client_addr);
WFIFOL(chrif->fd,35) = sd->group_id;
WFIFOSET(chrif->fd,39);
-
+
return true;
}
@@ -397,7 +395,7 @@ bool chrif_changemapserver(struct map_session_data* sd, uint32 ip, uint16 port)
/// R 2b06 <account_id>.L <login_id1>.L <login_id2>.L <char_id>.L <map_index>.W <x>.W <y>.W <ip>.L <port>.W
bool chrif_changemapserverack(int account_id, int login_id1, int login_id2, int char_id, short map_index, short x, short y, uint32 ip, uint16 port) {
struct auth_node *node;
-
+
if ( !( node = chrif->auth_check(account_id, char_id, ST_MAPCHANGE) ) )
return false;
@@ -436,7 +434,7 @@ void chrif_connectack(int fd) {
ShowStatus("Event '"CL_WHITE"OnInterIfInitOnce"CL_RESET"' executed with '"CL_WHITE"%d"CL_RESET"' NPCs.\n", npc->event_doall("OnInterIfInitOnce"));
guild->castle_map_init();
}
-
+
sockt->datasync(fd, true);
chrif->skillid2idx(fd);
}
@@ -446,7 +444,7 @@ void chrif_connectack(int fd) {
*/
int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
struct auth_node *node = DB->data2ptr(data);
-
+
switch (node->state) {
case ST_LOGIN:
if ( node->sd ) {//Since there is no way to request the char auth, make it fail.
@@ -463,7 +461,7 @@ int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
struct map_session_data *sd = node->sd;
uint32 ip;
uint16 port;
-
+
if( map->mapname2ipport(sd->mapindex,&ip,&port) == 0 )
chrif->changemapserver(sd, ip, port);
else //too much lag/timeout is the closest explanation for this error.
@@ -471,7 +469,6 @@ int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
break;
}
}
-
return 0;
}
@@ -480,9 +477,9 @@ int chrif_reconnect(DBKey key, DBData *data, va_list ap) {
void chrif_on_ready(void) {
static bool once = false;
ShowStatus("Map Server is now online.\n");
-
+
chrif->state = 2;
-
+
chrif->check_shutdown();
//If there are players online, send them to the char-server. [Skotlex]
@@ -496,7 +493,7 @@ void chrif_on_ready(void) {
//Re-save any guild castles that were modified in the disconnection time.
guild->castle_reconnect(-1, 0, 0);
-
+
if( !once ) {
#ifdef AUTOTRADE_PERSISTENCY
pc->autotrade_load();
@@ -509,23 +506,23 @@ void chrif_on_ready(void) {
/*==========================================
*
*------------------------------------------*/
-void chrif_sendmapack(int fd) {
-
+void chrif_sendmapack(int fd)
+{
if (RFIFOB(fd,2)) {
ShowFatalError("chrif : send map list to char server failed %d\n", RFIFOB(fd,2));
exit(EXIT_FAILURE);
}
memcpy(map->wisp_server_name, RFIFOP(fd,3), NAME_LENGTH);
-
+
chrif->on_ready();
}
/*==========================================
* Request sc_data from charserver [Skotlex]
*------------------------------------------*/
-bool chrif_scdata_request(int account_id, int char_id) {
-
+bool chrif_scdata_request(int account_id, int char_id)
+{
#ifdef ENABLE_SC_SAVING
chrif_check(false);
@@ -535,7 +532,6 @@ bool chrif_scdata_request(int account_id, int char_id) {
WFIFOL(chrif->fd,6) = char_id;
WFIFOSET(chrif->fd,10);
#endif
-
return true;
}
@@ -544,7 +540,7 @@ bool chrif_scdata_request(int account_id, int char_id) {
*------------------------------------------*/
void chrif_authreq(struct map_session_data *sd, bool hstandalone) {
struct auth_node *node= chrif->search(sd->bl.id);
-
+
if( node != NULL || !chrif->isconnected() ) {
set_eof(sd->fd);
return;
@@ -621,7 +617,7 @@ void chrif_authok(int fd) {
} else { //Auth Failed
pc->authfail(sd);
}
-
+
chrif_char_offline(sd); //Set him offline, the char server likely has it set as online already.
chrif->auth_delete(account_id, char_id, ST_LOGIN);
}
@@ -639,7 +635,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (
sex = RFIFOB(fd,14);
node = chrif->search(account_id);
-
+
if( node != NULL &&
node->account_id == account_id &&
node->char_id == char_id &&
@@ -660,7 +656,7 @@ void chrif_authfail(int fd) {/* HELLO WORLD. ip in RFIFOL 15 is not being used (
int auth_db_cleanup_sub(DBKey key, DBData *data, va_list ap) {
struct auth_node *node = DB->data2ptr(data);
const char* states[] = { "Login", "Logout", "Map change" };
-
+
if(DIFF_TICK(timer->gettick(),node->node_created)>60000) {
switch (node->state) {
case ST_LOGOUT:
@@ -694,7 +690,7 @@ bool chrif_charselectreq(struct map_session_data* sd, uint32 s_ip) {
if( !sd->bl.id || !sd->login_id1 )
return false;
-
+
chrif_check(false);
WFIFOHEAD(chrif->fd,22);
@@ -713,10 +709,10 @@ bool chrif_charselectreq(struct map_session_data* sd, uint32 s_ip) {
* Search Char trough id on char serv
*------------------------------------------*/
bool chrif_searchcharid(int char_id) {
-
+
if( !char_id )
return false;
-
+
chrif_check(false);
WFIFOHEAD(chrif->fd,6);
@@ -731,7 +727,7 @@ bool chrif_searchcharid(int char_id) {
* Change Email
*------------------------------------------*/
bool chrif_changeemail(int id, const char *actual_email, const char *new_email) {
-
+
if (battle_config.etc_log)
ShowInfo("chrif_changeemail: account: %d, actual_email: '%s', new_email: '%s'.\n", id, actual_email, new_email);
@@ -753,8 +749,8 @@ bool chrif_changeemail(int id, const char *actual_email, const char *new_email)
* type of operation:
* 1: block, 2: ban, 3: unblock, 4: unban, 5: changesex (use next function for 5), 6: charban
*------------------------------------------*/
-bool chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second) {
-
+bool chrif_char_ask_name(int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second)
+{
chrif_check(false);
WFIFOHEAD(chrif->fd,44);
@@ -762,7 +758,7 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope
WFIFOL(chrif->fd,2) = acc;
safestrncpy((char*)WFIFOP(chrif->fd,6), character_name, NAME_LENGTH);
WFIFOW(chrif->fd,30) = operation_type;
-
+
if ( operation_type == 2 || operation_type == 6 ) {
WFIFOW(chrif->fd,32) = year;
WFIFOW(chrif->fd,34) = month;
@@ -771,14 +767,14 @@ bool chrif_char_ask_name(int acc, const char* character_name, unsigned short ope
WFIFOW(chrif->fd,40) = minute;
WFIFOW(chrif->fd,42) = second;
}
-
+
WFIFOSET(chrif->fd,44);
return true;
}
bool chrif_changesex(struct map_session_data *sd) {
chrif_check(false);
-
+
WFIFOHEAD(chrif->fd,44);
WFIFOW(chrif->fd,0) = 0x2b0e;
WFIFOL(chrif->fd,2) = sd->status.account_id;
@@ -811,9 +807,9 @@ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, u
char action[25];
char output[256];
bool charsrv = ( type == 6 || type == 7 ) ? true : false;
-
+
sd = map->id2sd(acc);
-
+
if( acc < 0 || sd == NULL ) {
ShowError("chrif_char_ask_name_answer failed - player not online.\n");
return false;
@@ -822,7 +818,7 @@ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, u
/* re-use previous msg_txt */
if( type == 6 ) type = 2;
if( type == 7 ) type = 4;
-
+
if( type > 0 && type <= 5 )
snprintf(action,25,"%s",msg_txt(427+type)); //block|ban|unblock|unban|change the sex of
else
@@ -835,7 +831,7 @@ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, u
case 3 : sprintf(output, msg_txt(427), action, NAME_LENGTH, player_name); break;
default: output[0] = '\0'; break;
}
-
+
clif->message(sd->fd, output);
return true;
}
@@ -846,7 +842,7 @@ bool chrif_char_ask_name_answer(int acc, const char* player_name, uint16 type, u
void chrif_changedsex(int fd) {
int acc = RFIFOL(fd,2);
//int sex = RFIFOL(fd,6); // Dead store. Uncomment if needed again.
-
+
if ( battle_config.etc_log )
ShowNotice("chrif_changedsex %d.\n", acc);
@@ -896,7 +892,7 @@ bool chrif_divorceack(int char_id, int partner_id) {
if (sd->status.inventory[i].nameid == WEDDING_RING_M || sd->status.inventory[i].nameid == WEDDING_RING_F)
pc->delitem(sd, i, 1, 0, 0, LOG_TYPE_OTHER);
}
-
+
return true;
}
/*==========================================
@@ -932,10 +928,10 @@ void chrif_idbanned(int fd) {
struct map_session_data *sd;
id = RFIFOL(fd,2);
-
+
if ( battle_config.etc_log )
ShowNotice("chrif_idbanned %d.\n", id);
-
+
sd = ( RFIFOB(fd,6) == 2 ) ? map->charid2sd(id) : map->id2sd(id);
if ( id < 0 || sd == NULL ) {
@@ -981,10 +977,10 @@ int chrif_disconnectplayer(int fd) {
sd = map->id2sd(account_id);
if( sd == NULL ) {
struct auth_node* auth = chrif->search(account_id);
-
+
if( auth != NULL && chrif->auth_delete(account_id, auth->char_id, ST_LOGIN) )
return 0;
-
+
return -1;
}
@@ -1011,7 +1007,7 @@ int chrif_disconnectplayer(int fd) {
*------------------------------------------*/
int chrif_updatefamelist(struct map_session_data* sd) {
char type;
-
+
chrif_check(-1);
switch(sd->class_ & MAPID_UPPERMASK) {
@@ -1051,30 +1047,24 @@ void chrif_recvfamelist(int fd) {
memset(pc->taekwon_fame_list, 0, sizeof(pc->taekwon_fame_list));
size = RFIFOW(fd, 6); //Blacksmith block size
-
for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
memcpy(&pc->smith_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
- len += sizeof(struct fame_list);
+ len += sizeof(struct fame_list);
}
-
total += num;
size = RFIFOW(fd, 4); //Alchemist block size
-
for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
memcpy(&pc->chemist_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
- len += sizeof(struct fame_list);
+ len += sizeof(struct fame_list);
}
-
total += num;
size = RFIFOW(fd, 2); //Total packet length
-
for (num = 0; len < size && num < MAX_FAME_LIST; num++) {
memcpy(&pc->taekwon_fame_list[num], RFIFOP(fd,len), sizeof(struct fame_list));
- len += sizeof(struct fame_list);
+ len += sizeof(struct fame_list);
}
-
total += num;
ShowInfo("Received Fame List of '"CL_WHITE"%d"CL_RESET"' characters.\n", total);
@@ -1085,21 +1075,20 @@ void chrif_recvfamelist(int fd) {
int chrif_updatefamelist_ack(int fd) {
struct fame_list* list;
uint8 index;
-
+
switch (RFIFOB(fd,2)) {
case RANKTYPE_BLACKSMITH: list = pc->smith_fame_list; break;
case RANKTYPE_ALCHEMIST: list = pc->chemist_fame_list; break;
case RANKTYPE_TAEKWON: list = pc->taekwon_fame_list; break;
default: return 0;
}
-
+
index = RFIFOB(fd, 3);
-
if (index >= MAX_FAME_LIST)
return 0;
-
+
list[index].fame = RFIFOL(fd,4);
-
+
return 1;
}
@@ -1114,20 +1103,23 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th
chrif_check(false);
tick = timer->gettick();
-
+
WFIFOHEAD(chrif->fd, 14 + SC_MAX*sizeof(struct status_change_data));
WFIFOW(chrif->fd,0) = 0x2b1c;
WFIFOL(chrif->fd,4) = sd->status.account_id;
WFIFOL(chrif->fd,8) = sd->status.char_id;
-
+
for (i = 0; i < SC_MAX; i++) {
if (!sc->data[i])
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;
@@ -1139,15 +1131,15 @@ bool chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of th
&data, sizeof(struct status_change_data));
count++;
}
-
+
if (count == 0)
return true; //Nothing to save. | Everything was as successful as if there was something to save.
-
+
WFIFOW(chrif->fd,12) = count;
WFIFOW(chrif->fd,2) = 14 +count*sizeof(struct status_change_data); //Total packet size
WFIFOSET(chrif->fd,WFIFOW(chrif->fd,2));
#endif
-
+
return true;
}
@@ -1161,29 +1153,29 @@ bool chrif_load_scdata(int fd) {
aid = RFIFOL(fd,4); //Player Account ID
cid = RFIFOL(fd,8); //Player Char ID
-
+
sd = map->id2sd(aid);
-
+
if ( !sd ) {
ShowError("chrif_load_scdata: Player of AID %d not found!\n", aid);
return false;
}
-
+
if ( sd->status.char_id != cid ) {
ShowError("chrif_load_scdata: Receiving data for account %d, char id does not matches (%d != %d)!\n", aid, sd->status.char_id, cid);
return false;
}
-
+
count = RFIFOW(fd,12); //sc_count
-
+
for (i = 0; i < count; i++) {
data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
- status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, 15);
+ status->change_start(NULL, &sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4,
+ data->tick, SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE);
}
-
+
pc->scdata_received(sd);
#endif
-
return true;
}
@@ -1200,7 +1192,6 @@ bool chrif_ragsrvinfo(int base_rate, int job_rate, int drop_rate) {
WFIFOL(chrif->fd,6) = job_rate;
WFIFOL(chrif->fd,10) = drop_rate;
WFIFOSET(chrif->fd,14);
-
return true;
}
@@ -1266,7 +1257,7 @@ void chrif_on_disconnect(void) {
if( chrif->connected != 1 )
ShowWarning("Connection to Char Server lost.\n\n");
chrif->connected = 0;
-
+
chrif->other_mapserver_count = 0; //Reset counter. We receive ALL maps from all map-servers on reconnect.
map->eraseallipport();
@@ -1277,19 +1268,19 @@ void chrif_on_disconnect(void) {
void chrif_update_ip(int fd) {
uint32 new_ip;
-
+
WFIFOHEAD(fd,6);
-
+
new_ip = host2ip(chrif->ip_str);
-
+
if (new_ip && new_ip != chrif->ip)
chrif->ip = new_ip; //Update chrif->ip
new_ip = clif->refresh_ip();
-
+
if (!new_ip)
return; //No change
-
+
WFIFOW(fd,0) = 0x2736;
WFIFOL(fd,2) = htonl(new_ip);
WFIFOSET(fd,6);
@@ -1306,12 +1297,12 @@ void chrif_keepalive_ack(int fd) {
}
void chrif_skillid2idx(int fd) {
int i, count = 0;
-
+
if( fd == 0 ) fd = chrif->fd;
-
+
if( !session_isValid(fd) )
return;
-
+
WFIFOHEAD(fd,4 + (MAX_SKILL * 4));
WFIFOW(fd,0) = 0x2b0b;
for(i = 0; i < MAX_SKILL; i++) {
@@ -1363,12 +1354,12 @@ int chrif_parse(int fd) {
}
cmd = RFIFOW(fd,0);
-
+
if (cmd < 0x2af8 || cmd >= 0x2af8 + ARRAYLENGTH(chrif->packet_len_table) || chrif->packet_len_table[cmd-0x2af8] == 0) {
r = intif->parse(fd); // Passed on to the intif
- if (r == 1) continue; // Treated in intif
- if (r == 2) return 0; // Didn't have enough data (len==-1)
+ if (r == 1) continue; // Treated in intif
+ if (r == 2) return 0; // Didn't have enough data (len==-1)
ShowWarning("chrif_parse: session #%d, intif->parse failed (unrecognized command 0x%.4x).\n", fd, cmd);
set_eof(fd);
@@ -1444,20 +1435,18 @@ bool send_users_tochar(void) {
chrif_check(false);
users = map->usercount();
-
+
WFIFOHEAD(chrif->fd, 6+8*users);
WFIFOW(chrif->fd,0) = 0x2aff;
-
+
iter = mapit_getallusers();
-
for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) ) {
WFIFOL(chrif->fd,6+8*i) = sd->status.account_id;
WFIFOL(chrif->fd,6+8*i+4) = sd->status.char_id;
i++;
}
-
mapit->free(iter);
-
+
WFIFOW(chrif->fd,2) = 6 + 8*users;
WFIFOW(chrif->fd,4) = users;
WFIFOSET(chrif->fd, 6+8*users);
@@ -1467,7 +1456,7 @@ bool send_users_tochar(void) {
/*==========================================
* timerFunction
- * Check the connection to char server, (if it down)
+ * Check the connection to char server, (if it down)
*------------------------------------------*/
int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) {
static int displayed = 0;
@@ -1478,7 +1467,7 @@ int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) {
}
chrif->state = 0;
-
+
if ( ( chrif->fd = make_connection(chrif->ip, chrif->port,NULL) ) == -1) //Attempt to connect later. [Skotlex]
return 0;
@@ -1503,8 +1492,8 @@ int check_connect_char_server(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Asks char server to remove friend_id from the friend list of char_id
*------------------------------------------*/
-bool chrif_removefriend(int char_id, int friend_id) {
-
+bool chrif_removefriend(int char_id, int friend_id)
+{
chrif_check(false);
WFIFOHEAD(chrif->fd,10);
@@ -1512,7 +1501,6 @@ bool chrif_removefriend(int char_id, int friend_id) {
WFIFOL(chrif->fd,2) = char_id;
WFIFOL(chrif->fd,6) = friend_id;
WFIFOSET(chrif->fd,10);
-
return true;
}
@@ -1520,13 +1508,12 @@ void chrif_send_report(char* buf, int len) {
#ifndef STATS_OPT_OUT
if( chrif->fd > 0 ) {
WFIFOHEAD(chrif->fd,len + 2);
-
+
WFIFOW(chrif->fd,0) = 0x3008;
-
memcpy(WFIFOP(chrif->fd,2), buf, len);
-
+
WFIFOSET(chrif->fd,len + 2);
-
+
flush_fifo(chrif->fd); /* ensure it's sent now. */
}
#endif
@@ -1535,13 +1522,13 @@ void chrif_send_report(char* buf, int len) {
/**
* Sends a single scdata for saving into char server, meant to ensure integrity of duration-less conditions
**/
-void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce) {
-
+void chrif_save_scdata_single(int account_id, int char_id, short type, struct status_change_entry *sce)
+{
if( !chrif->isconnected() )
return;
-
+
WFIFOHEAD(chrif->fd, 28);
-
+
WFIFOW(chrif->fd, 0) = 0x2740;
WFIFOL(chrif->fd, 2) = account_id;
WFIFOL(chrif->fd, 6) = char_id;
@@ -1550,46 +1537,42 @@ void chrif_save_scdata_single(int account_id, int char_id, short type, struct st
WFIFOL(chrif->fd, 16) = sce->val2;
WFIFOL(chrif->fd, 20) = sce->val3;
WFIFOL(chrif->fd, 24) = sce->val4;
-
+
WFIFOSET(chrif->fd, 28);
-
}
/**
* Sends a single scdata deletion request into char server, meant to ensure integrity of duration-less conditions
**/
-void chrif_del_scdata_single(int account_id, int char_id, short type) {
-
+void chrif_del_scdata_single(int account_id, int char_id, short type)
+{
if( !chrif->isconnected() ) {
ShowError("MAYDAY! failed to delete status %d from CID:%d/AID:%d\n",type,char_id,account_id);
return;
}
-
WFIFOHEAD(chrif->fd, 12);
-
+
WFIFOW(chrif->fd, 0) = 0x2741;
WFIFOL(chrif->fd, 2) = account_id;
WFIFOL(chrif->fd, 6) = char_id;
WFIFOW(chrif->fd, 10) = type;
-
- WFIFOSET(chrif->fd, 12);
+ WFIFOSET(chrif->fd, 12);
}
-/** `
+/**
* @see DBApply
*/
int auth_db_final(DBKey key, DBData *data, va_list ap) {
struct auth_node *node = DB->data2ptr(data);
-
+
if (node->sd) {
-
if( node->sd->regs.vars )
node->sd->regs.vars->destroy(node->sd->regs.vars, script->reg_destroy);
-
+
if( node->sd->regs.arrays )
node->sd->regs.arrays->destroy(node->sd->regs.arrays, script->array_free_db);
-
+
aFree(node->sd);
}
ers_free(chrif->auth_db_ers, node);
@@ -1600,15 +1583,15 @@ int auth_db_final(DBKey key, DBData *data, va_list ap) {
/*==========================================
* Destructor
*------------------------------------------*/
-void do_final_chrif(void) {
-
+void do_final_chrif(void)
+{
if( chrif->fd != -1 ) {
do_close(chrif->fd);
chrif->fd = -1;
}
chrif->auth_db->destroy(chrif->auth_db, chrif->auth_db_final);
-
+
ers_destroy(chrif->auth_db_ers);
}
@@ -1644,12 +1627,12 @@ void do_init_chrif(bool minimal) {
*-------------------------------------*/
void chrif_defaults(void) {
const int packet_len_table[CHRIF_PACKET_LEN_TABLE_SIZE] = { // U - used, F - free
- 60, 3,-1,27,10,-1, 6,-1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
- 6,-1,18, 7,-1,39,30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
- 6,30, -1, 0,86, 7,44,34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
- 11,10,10, 0,11, 0,266,10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17
- 2,10, 2,-1,-1,-1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
- -1,10, 8, 2, 2,14,19,19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
+ 60, 3, -1, 27, 10, -1, 6, -1, // 2af8-2aff: U->2af8, U->2af9, U->2afa, U->2afb, U->2afc, U->2afd, U->2afe, U->2aff
+ 6, -1, 18, 7, -1, 39, 30, 10, // 2b00-2b07: U->2b00, U->2b01, U->2b02, U->2b03, U->2b04, U->2b05, U->2b06, U->2b07
+ 6, 30, -1, 0, 86, 7, 44, 34, // 2b08-2b0f: U->2b08, U->2b09, U->2b0a, F->2b0b, U->2b0c, U->2b0d, U->2b0e, U->2b0f
+ 11, 10, 10, 0, 11, 0,266, 10, // 2b10-2b17: U->2b10, U->2b11, U->2b12, F->2b13, U->2b14, F->2b15, U->2b16, U->2b17
+ 2, 10, 2, -1, -1, -1, 2, 7, // 2b18-2b1f: U->2b18, U->2b19, U->2b1a, U->2b1b, U->2b1c, U->2b1d, U->2b1e, U->2b1f
+ -1, 10, 8, 2, 2, 14, 19, 19, // 2b20-2b27: U->2b20, U->2b21, U->2b22, U->2b23, U->2b24, U->2b25, U->2b26, U->2b27
};
chrif = &chrif_s;
@@ -1657,7 +1640,7 @@ void chrif_defaults(void) {
/* vars */
chrif->connected = 0;
chrif->other_mapserver_count = 0;
-
+
memcpy(chrif->packet_len_table,&packet_len_table,sizeof(chrif->packet_len_table));
chrif->fd = -1;
chrif->srvinfo = 0;
@@ -1667,36 +1650,36 @@ void chrif_defaults(void) {
memset(chrif->userid,0,sizeof(chrif->userid));
memset(chrif->passwd,0,sizeof(chrif->passwd));
chrif->state = 0;
-
+
/* */
chrif->auth_db = NULL;
chrif->auth_db_ers = NULL;
/* */
chrif->init = do_init_chrif;
chrif->final = do_final_chrif;
-
+
/* funcs */
chrif->setuserid = chrif_setuserid;
chrif->setpasswd = chrif_setpasswd;
chrif->checkdefaultlogin = chrif_checkdefaultlogin;
chrif->setip = chrif_setip;
chrif->setport = chrif_setport;
-
+
chrif->isconnected = chrif_isconnected;
chrif->check_shutdown = chrif_check_shutdown;
-
+
chrif->search = chrif_search;
chrif->auth_check = chrif_auth_check;
chrif->auth_delete = chrif_auth_delete;
chrif->auth_finished = chrif_auth_finished;
-
+
chrif->authreq = chrif_authreq;
chrif->authok = chrif_authok;
chrif->scdata_request = chrif_scdata_request;
chrif->save = chrif_save;
chrif->charselectreq = chrif_charselectreq;
chrif->changemapserver = chrif_changemapserver;
-
+
chrif->searchcharid = chrif_searchcharid;
chrif->changeemail = chrif_changeemail;
chrif->char_ask_name = chrif_char_ask_name;
@@ -1711,13 +1694,13 @@ void chrif_defaults(void) {
chrif->changesex = chrif_changesex;
//chrif->chardisconnect = chrif_chardisconnect;
chrif->divorce = chrif_divorce;
-
+
chrif->removefriend = chrif_removefriend;
chrif->send_report = chrif_send_report;
-
+
chrif->flush = chrif_flush;
chrif->skillid2idx = chrif_skillid2idx;
-
+
chrif->sd_to_auth = chrif_sd_to_auth;
chrif->check_connect_char_server = check_connect_char_server;
chrif->auth_logout = chrif_auth_logout;
@@ -1728,7 +1711,7 @@ void chrif_defaults(void) {
chrif->auth_db_final = auth_db_final;
chrif->send_usercount_tochar = send_usercount_tochar;
chrif->auth_db_cleanup = auth_db_cleanup;
-
+
chrif->connect = chrif_connect;
chrif->connectack = chrif_connectack;
chrif->sendmap = chrif_sendmap;
diff --git a/src/map/chrif.h b/src/map/chrif.h
index 11baaf5ff..2ef4d0eb5 100644
--- a/src/map/chrif.h
+++ b/src/map/chrif.h
@@ -48,7 +48,7 @@ struct auth_node {
struct chrif_interface {
/* vars */
-
+
int connected;
int other_mapserver_count; //Holds count of how many other map servers are online (apart of this instance) [Skotlex]
@@ -73,22 +73,22 @@ struct chrif_interface {
void (*checkdefaultlogin) (void);
bool (*setip) (const char* ip);
void (*setport) (uint16 port);
-
+
int (*isconnected) (void);
void (*check_shutdown) (void);
-
+
struct auth_node* (*search) (int account_id);
struct auth_node* (*auth_check) (int account_id, int char_id, enum sd_state state);
bool (*auth_delete) (int account_id, int char_id, enum sd_state state);
bool (*auth_finished) (struct map_session_data* sd);
-
+
void (*authreq) (struct map_session_data* sd, bool hstandalone);
void (*authok) (int fd);
bool (*scdata_request) (int account_id, int char_id);
bool (*save) (struct map_session_data* sd, int flag);
bool (*charselectreq) (struct map_session_data* sd, uint32 s_ip);
bool (*changemapserver) (struct map_session_data* sd, uint32 ip, uint16 port);
-
+
bool (*searchcharid) (int char_id);
bool (*changeemail) (int id, const char *actual_email, const char *new_email);
bool (*char_ask_name) (int acc, const char* character_name, unsigned short operation_type, int year, int month, int day, int hour, int minute, int second);
@@ -104,13 +104,13 @@ struct chrif_interface {
bool (*changesex) (struct map_session_data *sd);
//int (*chardisconnect) (struct map_session_data *sd); // FIXME: Commented out in clif.c, function does not exist
bool (*divorce) (int partner_id1, int partner_id2);
-
+
bool (*removefriend) (int char_id, int friend_id);
void (*send_report) (char* buf, int len);
-
+
bool (*flush) (void);
void (*skillid2idx) (int fd);
-
+
bool (*sd_to_auth) (TBL_PC* sd, enum sd_state state);
int (*check_connect_char_server) (int tid, int64 tick, int id, intptr_t data);
bool (*auth_logout) (TBL_PC* sd, enum sd_state state);
diff --git a/src/map/clif.c b/src/map/clif.c
index d9acf0792..d7b10f2f4 100644
--- a/src/map/clif.c
+++ b/src/map/clif.c
@@ -72,16 +72,21 @@ static struct packet_npc_market_open npcmarket_open;
//#define DUMP_UNKNOWN_PACKET
//#define DUMP_INVALID_PACKET
+static struct hChSysConfig clif_hChSys;
+
//Converts item type in case of pet eggs.
static inline int itemtype(int type) {
switch( type ) {
#if PACKETVER >= 20080827
- case IT_WEAPON: return IT_ARMOR;
+ case IT_WEAPON:
+ return IT_ARMOR;
case IT_ARMOR:
case IT_PETARMOR:
#endif
- case IT_PETEGG: return IT_WEAPON;
- default: return type;
+ case IT_PETEGG:
+ return IT_WEAPON;
+ default:
+ return type;
}
}
@@ -331,6 +336,11 @@ int clif_send_sub(struct block_list *bl, va_list ap) {
if( clif->ally_only && !sd->sc.data[SC_CLAIRVOYANCE] && !sd->special_state.intravision && battle->check_target( src_bl, &sd->bl, BCT_ENEMY ) > 0 )
return 0;
+ return clif->send_actual(fd, buf, len);
+}
+
+int clif_send_actual(int fd, void *buf, int len)
+{
WFIFOHEAD(fd, len);
if (WFIFOP(fd,0) == buf) {
ShowError("WARNING: Invalid use of clif->send function\n");
@@ -619,7 +629,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);
}
@@ -1265,11 +1277,15 @@ void clif_spiritball_single(int fd, struct map_session_data *sd) {
* Kagerou/Oboro amulet spirit
*------------------------------------------*/
void clif_charm_single(int fd, struct map_session_data *sd, short type) {
+
+ if ( type <= SPIRITS_TYPE_NONE || type >= SPIRITS_TYPE_SPHERE )
+ return;
+
WFIFOHEAD(fd, packet_len(0x08cf));
WFIFOW(fd,0)=0x08cf;
WFIFOL(fd,2)=sd->bl.id;
WFIFOW(fd,6)=type;
- WFIFOW(fd,8)=sd->charm[type];
+ WFIFOW(fd,8)=sd->spiritcharm[type];
WFIFOSET(fd, packet_len(0x08cf));
}
@@ -1311,7 +1327,7 @@ void clif_weather(int16 m)
for( sd = (struct map_session_data*)mapit->first(iter); mapit->exists(iter); sd = (struct map_session_data*)mapit->next(iter) )
{
if( sd->bl.m == m )
- clif_weather_check(sd);
+ clif->weather_check(sd);
}
mapit->free(iter);
}
@@ -1348,17 +1364,15 @@ bool clif_spawn(struct block_list *bl)
clif->spiritball(&sd->bl);
if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect(bl,423,AREA);
- else if(sd->state.size==SZ_SMALL)
+ else if(sd->state.size==SZ_MEDIUM)
clif->specialeffect(bl,421,AREA);
if( sd->bg_id && map->list[sd->bl.m].flag.battleground )
clif->sendbgemblem_area(sd);
for( i = 0; i < sd->sc_display_count; i++ ) {
clif->sc_load(&sd->bl, sd->bl.id,AREA,status->IconChangeTable[sd->sc_display[i]->type],sd->sc_display[i]->val1,sd->sc_display[i]->val2,sd->sc_display[i]->val3);
}
- for(i = 1; i < 5; i++){
- if( sd->charm[i] > 0 )
- clif->charm(sd, i);
- }
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
+ clif->spiritcharm(sd, i);
if (sd->status.robe)
clif->refreshlook(bl,bl->id,LOOK_ROBE,sd->status.robe,AREA);
}
@@ -1368,7 +1382,7 @@ bool clif_spawn(struct block_list *bl)
TBL_MOB *md = ((TBL_MOB*)bl);
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect(&md->bl,423,AREA);
- else if(md->special_state.size==SZ_SMALL)
+ else if(md->special_state.size==SZ_MEDIUM)
clif->specialeffect(&md->bl,421,AREA);
}
break;
@@ -1377,7 +1391,7 @@ bool clif_spawn(struct block_list *bl)
TBL_NPC *nd = ((TBL_NPC*)bl);
if( nd->size == SZ_BIG )
clif->specialeffect(&nd->bl,423,AREA);
- else if( nd->size == SZ_SMALL )
+ else if( nd->size == SZ_MEDIUM )
clif->specialeffect(&nd->bl,421,AREA);
}
break;
@@ -1410,15 +1424,24 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
WBUFW(buf,29)=hd->homunculus.hunger;
WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ;
WBUFW(buf,33)=0; // equip id
+#ifdef RENEWAL
+ WBUFW(buf, 35) = cap_value(hstatus->rhw.atk2, 0, INT16_MAX);
+#else
WBUFW(buf,35)=cap_value(hstatus->rhw.atk2+hstatus->batk, 0, INT16_MAX);
+#endif
WBUFW(buf,37)=cap_value(hstatus->matk_max, 0, INT16_MAX);
WBUFW(buf,39)=hstatus->hit;
if (battle_config.hom_setting&0x10)
WBUFW(buf,41)=hstatus->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious]
else
WBUFW(buf,41)=hstatus->cri/10;
+#ifdef RENEWAL
+ WBUFW(buf, 43) = hstatus->def + hstatus->def2;
+ WBUFW(buf, 45) = hstatus->mdef + hstatus->mdef2;
+#else
WBUFW(buf,43)=hstatus->def + hstatus->vit ;
- WBUFW(buf,45)=hstatus->mdef;
+ WBUFW(buf, 45) = hstatus->mdef;
+#endif
WBUFW(buf,47)=hstatus->flee;
WBUFW(buf,49)=(flag)?0:hstatus->amotion;
if (hstatus->max_hp > INT16_MAX) {
@@ -1465,7 +1488,7 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag)
/// 3 = accessory?
/// ? = ignored
void clif_send_homdata(struct map_session_data *sd, int state, int param)
-{ //[orn]
+{
int fd = sd->fd;
if ( (state == SP_INTIMATE) && (param >= 910) && (sd->hd->homunculus.class_ == sd->hd->homunculusDB->evo_class) )
@@ -1536,7 +1559,7 @@ void clif_homskillup(struct map_session_data *sd, uint16 skill_id) { //[orn]
WFIFOSET(fd,packet_len(0x239));
}
-void clif_hom_food(struct map_session_data *sd,int foodid,int fail) //[orn]
+void clif_hom_food(struct map_session_data *sd,int foodid,int fail)
{
int fd;
nullpo_retv(sd);
@@ -1582,10 +1605,10 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
case BL_PC:
{
TBL_PC *sd = ((TBL_PC*)bl);
- // clif_movepc(sd);
+ //clif_movepc(sd);
if(sd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect(&sd->bl,423,AREA);
- else if(sd->state.size==SZ_SMALL)
+ else if(sd->state.size==SZ_MEDIUM)
clif->specialeffect(&sd->bl,421,AREA);
}
break;
@@ -1594,7 +1617,7 @@ void clif_move2(struct block_list *bl, struct view_data *vd, struct unit_data *u
TBL_MOB *md = ((TBL_MOB*)bl);
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect(&md->bl,423,AREA);
- else if(md->special_state.size==SZ_SMALL)
+ else if(md->special_state.size==SZ_MEDIUM)
clif->specialeffect(&md->bl,421,AREA);
}
break;
@@ -2669,76 +2692,77 @@ void read_channels_config(void) {
if( !libconfig->setting_lookup_string(settings, "map_local_channel_name", &local_name) )
local_name = "map";
- safestrncpy(hChSys.local_name, local_name, HCHSYS_NAME_LENGTH);
+ safestrncpy(clif->hChSys->local_name, local_name, HCHSYS_NAME_LENGTH);
if( !libconfig->setting_lookup_string(settings, "ally_channel_name", &ally_name) )
ally_name = "ally";
- safestrncpy(hChSys.ally_name, ally_name, HCHSYS_NAME_LENGTH);
+ safestrncpy(clif->hChSys->ally_name, ally_name, HCHSYS_NAME_LENGTH);
if( !libconfig->setting_lookup_string(settings, "irc_channel_name", &irc_name) )
irc_name = "irc";
- safestrncpy(hChSys.irc_name, irc_name, HCHSYS_NAME_LENGTH);
+ safestrncpy(clif->hChSys->irc_name, irc_name, HCHSYS_NAME_LENGTH);
libconfig->setting_lookup_bool(settings, "map_local_channel", &local_enabled);
libconfig->setting_lookup_bool(settings, "ally_channel_enabled", &ally_enabled);
libconfig->setting_lookup_bool(settings, "irc_channel_enabled", &irc_enabled);
- if( local_enabled )
- hChSys.local = true;
- if( ally_enabled )
- hChSys.ally = true;
- if( irc_enabled )
- hChSys.irc = true;
+ if (local_enabled)
+ clif->hChSys->local = true;
+ if (ally_enabled)
+ clif->hChSys->ally = true;
+ if (irc_enabled)
+ clif->hChSys->irc = true;
- hChSys.irc_server[0] = hChSys.irc_channel[0] = hChSys.irc_nick[0] = hChSys.irc_nick_pw[0] = '\0';
+ clif->hChSys->irc_server[0] = clif->hChSys->irc_channel[0] = clif->hChSys->irc_nick[0] = clif->hChSys->irc_nick_pw[0] = '\0';
- if( hChSys.irc ) {
+ if (clif->hChSys->irc) {
const char *irc_server, *irc_channel,
*irc_nick, *irc_nick_pw;
int irc_use_ghost = 0;
if( libconfig->setting_lookup_string(settings, "irc_channel_network", &irc_server) ) {
if( !strstr(irc_server,":") ) {
- hChSys.irc = false;
+ clif->hChSys->irc = false;
ShowWarning("channels.conf : network port wasn't found in 'irc_channel_network', disabling irc channel...\n");
} else {
unsigned char d = 0, dlen = strlen(irc_server);
char server[40];
-
+ 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);
- hChSys.irc_server_port = atoi(server);
+ safestrncpy(clif->hChSys->irc_server, server, 40);
+ memcpy(server, &irc_server[d+1], dlen - d - 1);
+ clif->hChSys->irc_server_port = atoi(server);
break;
}
}
}
} else {
- hChSys.irc = false;
+ clif->hChSys->irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_network wasn't found, disabling irc channel...\n");
}
if( libconfig->setting_lookup_string(settings, "irc_channel_channel", &irc_channel) )
- safestrncpy(hChSys.irc_channel, irc_channel, 50);
+ safestrncpy(clif->hChSys->irc_channel, irc_channel, 50);
else {
- hChSys.irc = false;
+ clif->hChSys->irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_channel wasn't found, disabling irc channel...\n");
}
if( libconfig->setting_lookup_string(settings, "irc_channel_nick", &irc_nick) ) {
if( strcmpi(irc_nick,"Hercules_chSysBot") == 0 ) {
- sprintf(hChSys.irc_nick, "Hercules_chSysBot%d",rand()%777);
+ sprintf(clif->hChSys->irc_nick, "Hercules_chSysBot%d",rand()%777);
} else
- safestrncpy(hChSys.irc_nick, irc_nick, 40);
+ safestrncpy(clif->hChSys->irc_nick, irc_nick, 40);
} else {
- hChSys.irc = false;
+ clif->hChSys->irc = false;
ShowWarning("channels.conf : irc channel enabled but irc_channel_nick wasn't found, disabling irc channel...\n");
}
if( libconfig->setting_lookup_string(settings, "irc_channel_nick_pw", &irc_nick_pw) ) {
- safestrncpy(hChSys.irc_nick_pw, irc_nick_pw, 30);
+ safestrncpy(clif->hChSys->irc_nick_pw, irc_nick_pw, 30);
config_setting_lookup_bool(settings, "irc_channel_use_ghost", &irc_use_ghost);
- hChSys.irc_use_ghost = irc_use_ghost;
+ clif->hChSys->irc_use_ghost = irc_use_ghost;
}
}
@@ -2746,83 +2770,83 @@ void read_channels_config(void) {
libconfig->setting_lookup_bool(settings, "map_local_channel_autojoin", &local_autojoin);
libconfig->setting_lookup_bool(settings, "ally_channel_autojoin", &ally_autojoin);
- if( local_autojoin )
- hChSys.local_autojoin = true;
- if( ally_autojoin )
- hChSys.ally_autojoin = true;
+ if (local_autojoin)
+ clif->hChSys->local_autojoin = true;
+ if (ally_autojoin)
+ clif->hChSys->ally_autojoin = true;
libconfig->setting_lookup_bool(settings, "allow_user_channel_creation", &allow_user_channel_creation);
if( allow_user_channel_creation )
- hChSys.allow_user_channel_creation = true;
+ clif->hChSys->allow_user_channel_creation = true;
if( (colors = libconfig->setting_get_member(settings, "colors")) != NULL ) {
int color_count = libconfig->setting_length(colors);
- CREATE( hChSys.colors, unsigned int, color_count );
- CREATE( hChSys.colors_name, char *, color_count );
+ CREATE(clif->hChSys->colors, unsigned int, color_count);
+ CREATE(clif->hChSys->colors_name, char *, color_count);
for(i = 0; i < color_count; i++) {
config_setting_t *color = libconfig->setting_get_elem(colors, i);
- CREATE( hChSys.colors_name[i], char, HCHSYS_NAME_LENGTH );
+ CREATE(clif->hChSys->colors_name[i], char, HCHSYS_NAME_LENGTH);
- safestrncpy(hChSys.colors_name[i], config_setting_name(color), HCHSYS_NAME_LENGTH);
+ safestrncpy(clif->hChSys->colors_name[i], config_setting_name(color), HCHSYS_NAME_LENGTH);
- hChSys.colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0);
- hChSys.colors[i] = (hChSys.colors[i] & 0x0000FF) << 16 | (hChSys.colors[i] & 0x00FF00) | (hChSys.colors[i] & 0xFF0000) >> 16;//RGB to BGR
+ clif->hChSys->colors[i] = (unsigned int)strtoul(libconfig->setting_get_string_elem(colors,i),NULL,0);
+ clif->hChSys->colors[i] = (clif->hChSys->colors[i] & 0x0000FF) << 16 | (clif->hChSys->colors[i] & 0x00FF00) | (clif->hChSys->colors[i] & 0xFF0000) >> 16;//RGB to BGR
}
- hChSys.colors_count = color_count;
+ clif->hChSys->colors_count = color_count;
}
libconfig->setting_lookup_string(settings, "map_local_channel_color", &local_color);
- for (k = 0; k < hChSys.colors_count; k++) {
- if( strcmpi(hChSys.colors_name[k],local_color) == 0 )
+ for (k = 0; k < clif->hChSys->colors_count; k++) {
+ if (strcmpi(clif->hChSys->colors_name[k], local_color) == 0)
break;
}
- if( k < hChSys.colors_count ) {
- hChSys.local_color = k;
+ if (k < clif->hChSys->colors_count) {
+ clif->hChSys->local_color = k;
} else {
ShowError("channels.conf: unknown color '%s' for 'map_local_channel_color', disabling '#%s'...\n",local_color,local_name);
- hChSys.local = false;
+ clif->hChSys->local = false;
}
libconfig->setting_lookup_string(settings, "ally_channel_color", &ally_color);
- for (k = 0; k < hChSys.colors_count; k++) {
- if( strcmpi(hChSys.colors_name[k],ally_color) == 0 )
+ for (k = 0; k < clif->hChSys->colors_count; k++) {
+ if (strcmpi(clif->hChSys->colors_name[k], ally_color) == 0)
break;
}
- if( k < hChSys.colors_count ) {
- hChSys.ally_color = k;
+ if( k < clif->hChSys->colors_count ) {
+ clif->hChSys->ally_color = k;
} else {
ShowError("channels.conf: unknown color '%s' for 'ally_channel_color', disabling '#%s'...\n",ally_color,ally_name);
- hChSys.ally = false;
+ clif->hChSys->ally = false;
}
libconfig->setting_lookup_string(settings, "irc_channel_color", &irc_color);
- for (k = 0; k < hChSys.colors_count; k++) {
- if( strcmpi(hChSys.colors_name[k],irc_color) == 0 )
+ for (k = 0; k < clif->hChSys->colors_count; k++) {
+ if (strcmpi(clif->hChSys->colors_name[k], irc_color) == 0)
break;
}
- if( k < hChSys.colors_count ) {
- hChSys.irc_color = k;
+ if (k < clif->hChSys->colors_count) {
+ clif->hChSys->irc_color = k;
} else {
ShowError("channels.conf: unknown color '%s' for 'irc_channel_color', disabling '#%s'...\n",irc_color,irc_name);
- hChSys.irc = false;
+ clif->hChSys->irc = false;
}
- if( hChSys.irc ) {
+ if (clif->hChSys->irc) {
struct hChSysCh *chd;
- CREATE( chd, struct hChSysCh, 1 );
+ CREATE(chd, struct hChSysCh, 1);
- safestrncpy(chd->name, hChSys.irc_name, HCHSYS_NAME_LENGTH);
+ safestrncpy(chd->name, clif->hChSys->irc_name, HCHSYS_NAME_LENGTH);
chd->type = hChSys_IRC;
- clif->chsys_create(chd,NULL,NULL,hChSys.irc_color);
+ clif->chsys_create(chd, NULL, NULL, clif->hChSys->irc_color);
ircbot->channel = chd;
}
@@ -2835,15 +2859,15 @@ void read_channels_config(void) {
const char *color = libconfig->setting_get_string_elem(channels,i);
struct hChSysCh *chd;
- for (k = 0; k < hChSys.colors_count; k++) {
- if( strcmpi(hChSys.colors_name[k],color) == 0 )
+ for (k = 0; k < clif->hChSys->colors_count; k++) {
+ if (strcmpi(clif->hChSys->colors_name[k],color) == 0)
break;
}
- if( k == hChSys.colors_count ) {
+ if( k == clif->hChSys->colors_count) {
ShowError("channels.conf: unknown color '%s' for channel '%s', skipping channel...\n",color,name);
continue;
}
- if( strcmpi(name,hChSys.local_name) == 0 || strcmpi(name,hChSys.ally_name) == 0 || strcmpi(name,hChSys.irc_name) == 0 || strdb_exists(clif->channel_db, name) ) {
+ if( strcmpi(name, clif->hChSys->local_name) == 0 || strcmpi(name, clif->hChSys->ally_name) == 0 || strcmpi(name, clif->hChSys->irc_name) == 0 || strdb_exists(clif->channel_db, name) ) {
ShowError("channels.conf: duplicate channel '%s', skipping channel...\n",name);
continue;
@@ -2943,7 +2967,7 @@ void clif_updatestatus(struct map_session_data *sd,int type)
case SP_WEIGHT:
pc->updateweightstatus(sd);
WFIFOHEAD(fd,14);
- WFIFOW(fd,0)=0xb0; //Need to re-set as pc->updateweightstatus can alter the buffer. [Skotlex]
+ WFIFOW(fd,0)=0xb0; //Need to re-set as pc->updateweightstatus can alter the buffer. [Skotlex]
WFIFOW(fd,2)=type;
WFIFOL(fd,4)=sd->weight;
break;
@@ -3173,17 +3197,14 @@ void clif_changestatus(struct map_session_data* sd,int type,int val)
clif->send(buf,packet_len(0x1ab),&sd->bl,AREA_WOS);
}
-
/// Updates sprite/style properties of an object.
-/// 00c3 <id>.L <type>.B <value>.B (ZC_SPRITE_CHANGE)
-/// 01d7 <id>.L <type>.B <value>.L (ZC_SPRITE_CHANGE2)
void clif_changelook(struct block_list *bl,int type,int val)
{
- unsigned char buf[16];
struct map_session_data* sd;
struct status_change* sc;
struct view_data* vd;
enum send_target target = AREA;
+ int val2 = 0;
nullpo_retv(bl);
sd = BL_CAST(BL_PC, bl);
@@ -3210,12 +3231,6 @@ void clif_changelook(struct block_list *bl,int type,int val)
break;
case LOOK_BASE:
if( !sd ) break;
- // We shouldn't update LOOK_BASE if the player is disguised
- // if we do so the client will think that the player class
- // is really a mob and issues like 7725 will happen in every
- // SC_ that alters class_ in any way [Panikon]
- if( sd->disguise != -1 )
- return;
if( sd->sc.option&OPTION_COSTUME )
vd->weapon = vd->shield = 0;
@@ -3295,57 +3310,34 @@ void clif_changelook(struct block_list *bl,int type,int val)
}
// prevent leaking the presence of GM-hidden objects
- if( sc && sc->option&OPTION_INVISIBLE )
+ if( sc && sc->option&OPTION_INVISIBLE && !disguised(bl) )
target = SELF;
-
#if PACKETVER < 4
- WBUFW(buf,0)=0xc3;
- WBUFL(buf,2)=bl->id;
- WBUFB(buf,6)=type;
- WBUFB(buf,7)=val;
- clif->send(buf,packet_len(0xc3),bl,target);
+ clif->sendlook(bl, bl->id, type, val, 0, target);
#else
- WBUFW(buf,0)=0x1d7;
- WBUFL(buf,2)=bl->id;
if(type == LOOK_WEAPON || type == LOOK_SHIELD) {
nullpo_retv(vd);
- WBUFB(buf,6)=LOOK_WEAPON;
- WBUFW(buf,7)=vd->weapon;
- WBUFW(buf,9)=vd->shield;
- } else {
- WBUFB(buf,6)=type;
- WBUFL(buf,7)=val;
- }
- clif->send(buf,packet_len(0x1d7),bl,target);
- if( disguised(bl) && sd && sd->fontcolor ) {
- WBUFL(buf,2)=-bl->id;
- clif->send(buf,packet_len(0x1d7),bl,SELF);
+ type = LOOK_WEAPON;
+ val = vd->weapon;
+ val2 = vd->shield;
}
+ if( disguised(bl) ) {
+ clif->sendlook(bl, bl->id, type, val, val2, AREA_WOS);
+ clif->sendlook(bl, -bl->id, type, val, val2, SELF);
+ } else
+ clif->sendlook(bl, bl->id, type, val, val2, target);
#endif
}
//Sends a change-base-look packet required for traps as they are triggered.
void clif_changetraplook(struct block_list *bl,int val)
{
- unsigned char buf[32];
-#if PACKETVER < 4
- WBUFW(buf,0)=0xc3;
- WBUFL(buf,2)=bl->id;
- WBUFB(buf,6)=LOOK_BASE;
- WBUFB(buf,7)=val;
- clif->send(buf,packet_len(0xc3),bl,AREA);
-#else
- WBUFW(buf,0)=0x1d7;
- WBUFL(buf,2)=bl->id;
- WBUFB(buf,6)=LOOK_BASE;
- WBUFW(buf,7)=val;
- WBUFW(buf,9)=0;
- clif->send(buf,packet_len(0x1d7),bl,AREA);
-#endif
+ clif->sendlook(bl, bl->id, LOOK_BASE, val, 0, AREA);
}
-//For the stupid cloth-dye bug. Resends the given view data to the area specified by bl.
-void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_target target)
+/// 00c3 <id>.L <type>.B <value>.B (ZC_SPRITE_CHANGE)
+/// 01d7 <id>.L <type>.B <value>.L (ZC_SPRITE_CHANGE2)
+void clif_sendlook(struct block_list *bl, int id, int type, int val, int val2, enum send_target target)
{
unsigned char buf[32];
#if PACKETVER < 4
@@ -3359,11 +3351,17 @@ void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_ta
WBUFL(buf,2)=id;
WBUFB(buf,6)=type;
WBUFW(buf,7)=val;
- WBUFW(buf,9)=0;
+ WBUFW(buf,9)=val2;
clif->send(buf,packet_len(0x1d7),bl,target);
#endif
}
+//For the stupid cloth-dye bug. Resends the given view data to the area specified by bl.
+void clif_refreshlook(struct block_list *bl,int id,int type,int val,enum send_target target)
+{
+ clif->sendlook(bl, id, type, val, 0, target);
+}
+
/// Character status (ZC_STATUS).
/// 00bd <stpoint>.W <str>.B <need str>.B <agi>.B <need agi>.B <vit>.B <need vit>.B
@@ -3437,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
@@ -4274,10 +4271,9 @@ void clif_getareachar_pc(struct map_session_data* sd,struct map_session_data* ds
if(dstsd->spiritball > 0)
clif->spiritball_single(sd->fd, dstsd);
- for(i = 1; i < 5; i++){
- if( dstsd->charm[i] > 0 )
- clif->charm_single(sd->fd, dstsd, i);
- }
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
+ clif->charm_single(sd->fd, dstsd, i);
+
for( i = 0; i < dstsd->sc_display_count; i++ ) {
clif->sc_load(&sd->bl,dstsd->bl.id,SELF,status->IconChangeTable[dstsd->sc_display[i]->type],dstsd->sc_display[i]->val1,dstsd->sc_display[i]->val2,dstsd->sc_display[i]->val3);
}
@@ -4326,7 +4322,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->getareachar_pc(sd, tsd);
if(tsd->state.size==SZ_BIG) // tiny/big players [Valaris]
clif->specialeffect_single(bl,423,sd->fd);
- else if(tsd->state.size==SZ_SMALL)
+ else if(tsd->state.size==SZ_MEDIUM)
clif->specialeffect_single(bl,421,sd->fd);
if( tsd->bg_id && map->list[tsd->bl.m].flag.battleground )
clif->sendbgemblem_single(sd->fd,tsd);
@@ -4345,7 +4341,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
clif->dispchat((struct chat_data*)map->id2bl(nd->chat_id),sd->fd);
if( nd->size == SZ_BIG )
clif->specialeffect_single(bl,423,sd->fd);
- else if( nd->size == SZ_SMALL )
+ else if( nd->size == SZ_MEDIUM )
clif->specialeffect_single(bl,421,sd->fd);
}
break;
@@ -4354,7 +4350,7 @@ void clif_getareachar_unit(struct map_session_data* sd,struct block_list *bl) {
TBL_MOB* md = (TBL_MOB*)bl;
if(md->special_state.size==SZ_BIG) // tiny/big mobs [Valaris]
clif->specialeffect_single(bl,423,sd->fd);
- else if(md->special_state.size==SZ_SMALL)
+ else if(md->special_state.size==SZ_MEDIUM)
clif->specialeffect_single(bl,421,sd->fd);
#if PACKETVER >= 20120404
if( !(md->status.mode&MD_BOSS) ){
@@ -4791,7 +4787,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);
}
@@ -4934,8 +4932,8 @@ void clif_deleteskill(struct map_session_data *sd, int id)
/// 010e <skill id>.W <level>.W <sp cost>.W <attack range>.W <upgradable>.B
/// Merged clif_skillup and clif_guild_skillup, same packet was used [panikon]
/// flag:
-/// 0: guild call
-/// 1: player call
+/// 0: guild call
+/// 1: player call
void clif_skillup(struct map_session_data *sd, uint16 skill_id, int skill_lv, int flag)
{
int fd;
@@ -5066,7 +5064,8 @@ void clif_skill_fail(struct map_session_data *sd,uint16 skill_id,enum useskill_f
{
int fd;
- if (!sd) { //Since this is the most common nullpo....
+ if (!sd) {
+ //Since this is the most common nullpo....
ShowDebug("clif_skill_fail: Error, received NULL sd for skill %d\n", skill_id);
return;
}
@@ -5128,8 +5127,12 @@ int clif_skill_damage(struct block_list *src, struct block_list *dst, int64 tick
damage = (int)cap_value(in_damage,INT_MIN,INT_MAX);
type = clif_calc_delay(type,div,damage,ddelay);
- sc = status->get_sc(dst);
- if(sc && sc->count) {
+
+#if PACKETVER >= 20131223
+ if( type == 6 ) type = 8; //bugreport:8263
+#endif
+
+ if( ( sc = status->get_sc(dst) ) && sc->count ) {
if(sc->data[SC_ILLUSION] && damage)
damage = damage*(sc->data[SC_ILLUSION]->val2) + rnd()%100;
}
@@ -5213,7 +5216,7 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic
nullpo_ret(src);
nullpo_ret(dst);
- type = (type>0)?type:skill_get_hit(skill_id);
+ type = (type>0)?type:skill->get_hit(skill_id);
type = clif_calc_delay(type,div,damage,ddelay);
sc = status->get_sc(dst);
@@ -5256,7 +5259,7 @@ int clif_skill_damage2(struct block_list *src, struct block_list *dst, int64 tic
}
//Because the damage delay must be synced with the client, here is where the can-walk tick must be updated. [Skotlex]
- return clif_calc_walkdelay(dst,ddelay,type,damage,div);
+ return clif->calc_walkdelay(dst,ddelay,type,damage,div);
}
#endif // 0
@@ -5373,7 +5376,7 @@ void clif_skill_memomessage(struct map_session_data* sd, int type)
/// type:
/// 0 = "Unable to Teleport in this area" in color 0xFFFF00 (cyan)
/// 1 = "Saved point cannot be memorized." in color 0x0000FF (red)
-/// 2 = "This skill cannot be used within this area." in color 0xFFFF00 (cyan)
+/// 2 = "This skill cannot be used within this area." in color 0xFFFF00 (cyan)
///
/// @param sd Who receives the message
/// @param type What message
@@ -5418,10 +5421,11 @@ void clif_skill_estimation(struct map_session_data *sd,struct block_list *dst) {
WBUFW(buf,16) = (battle_config.estimation_type&1?dstatus->mdef:0)
+ (battle_config.estimation_type&2?dstatus->mdef2:0);
WBUFW(buf,18) = dstatus->def_ele;
- for(i=0;i<9;i++)
+ for(i=0;i<9;i++) {
WBUFB(buf,20+i)= (unsigned char)battle->attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv);
-// The following caps negative attributes to 0 since the client displays them as 255-fix. [Skotlex]
-// WBUFB(buf,20+i)= (unsigned char)((fix=battle_attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv))<0?0:fix);
+ // The following caps negative attributes to 0 since the client displays them as 255-fix. [Skotlex]
+ //WBUFB(buf,20+i)= (unsigned char)((fix=battle->attr_ratio(i+1,dstatus->def_ele, dstatus->ele_lv))<0?0:fix);
+ }
clif->send(buf,packet_len(0x18c),&sd->bl,sd->status.party_id>0?PARTY_SAMEMAP:SELF);
}
@@ -5504,7 +5508,8 @@ void clif_cooking_list(struct map_session_data *sd, int trigger, uint16 skill_id
c++;
}
- if( skill_id == AM_PHARMACY ) { // Only send it while Cooking else check for c.
+ if( skill_id == AM_PHARMACY ) {
+ // Only send it while Cooking else check for c.
WFIFOW(fd,2) = 6 + 2 * c;
WFIFOSET(fd,WFIFOW(fd,2));
}
@@ -5580,6 +5585,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
@@ -5600,6 +5606,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.
@@ -5609,6 +5620,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) {
@@ -5833,12 +5845,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);
@@ -5988,17 +6000,17 @@ void clif_use_card(struct map_session_data *sd,int idx)
if(itemdb_isspecial(sd->status.inventory[i].card[0])) //Can't slot it
continue;
- if(sd->status.inventory[i].identify==0 ) //Not identified
+ if (sd->status.inventory[i].identify == 0) //Not identified
continue;
- if((sd->inventory_data[i]->equip&ep)==0) //Not equippable on this part.
+ if ((sd->inventory_data[i]->equip&ep) == 0) //Not equippable on this part.
continue;
if(sd->inventory_data[i]->type==IT_WEAPON && ep==EQP_SHIELD) //Shield card won't go on left weapon.
continue;
ARR_FIND( 0, sd->inventory_data[i]->slot, j, sd->status.inventory[i].card[j] == 0 );
- if( j == sd->inventory_data[i]->slot ) // No room
+ if (j == sd->inventory_data[i]->slot) // No room
continue;
if( sd->status.inventory[i].equip > 0 ) // Do not check items that are already equipped
@@ -6754,7 +6766,7 @@ void clif_party_message(struct party_data* p, int account_id, const char* mes, i
WBUFW(buf,0)=0x109;
WBUFW(buf,2)=len+8;
WBUFL(buf,4)=account_id;
- safestrncpy((char *)WBUFP(buf,8), mes, len);
+ safestrncpy((char *)WBUFP(buf,8), mes, len);
clif->send(buf,len+8,&sd->bl,PARTY);
}
}
@@ -7157,20 +7169,20 @@ void clif_devotion(struct block_list *src, struct map_session_data *tsd)
* 01e1 <id>.L <amount>.W (ZC_SPIRITS2)
*------------------------------------------*/
void clif_spiritball(struct block_list *bl) {
- unsigned char buf[16];
- TBL_PC *sd = BL_CAST(BL_PC,bl);
- TBL_HOM *hd = BL_CAST(BL_HOM,bl);
+ unsigned char buf[16];
+ TBL_PC *sd = BL_CAST(BL_PC,bl);
+ TBL_HOM *hd = BL_CAST(BL_HOM,bl);
- nullpo_retv(bl);
+ nullpo_retv(bl);
- WBUFW(buf, 0) = 0x1d0;
- WBUFL(buf, 2) = bl->id;
+ WBUFW(buf, 0) = 0x1d0;
+ WBUFL(buf, 2) = bl->id;
WBUFW(buf, 6) = 0; //init to 0
- switch(bl->type){
- case BL_PC: WBUFW(buf, 6) = sd->spiritball; break;
- case BL_HOM: WBUFW(buf, 6) = hd->homunculus.spiritball; break;
- }
- clif->send(buf, packet_len(0x1d0), bl, AREA);
+ switch(bl->type){
+ case BL_PC: WBUFW(buf, 6) = sd->spiritball; break;
+ case BL_HOM: WBUFW(buf, 6) = hd->homunculus.spiritball; break;
+ }
+ clif->send(buf, packet_len(0x1d0), bl, AREA);
}
@@ -7438,9 +7450,9 @@ void clif_guild_basicinfo(struct map_session_data *sd) {
WFIFOL(fd,18)=g->average_lv;
WFIFOL(fd,22)=(uint32)cap_value(g->exp,0,INT32_MAX);
WFIFOL(fd,26)=g->next_exp;
- WFIFOL(fd,30)=0; // Tax Points
- WFIFOL(fd,34)=0; // Honor: (left) Vulgar [-100,100] Famed (right)
- WFIFOL(fd,38)=0; // Virtue: (down) Wicked [-100,100] Righteous (up)
+ WFIFOL(fd,30)=0; // Tax Points
+ WFIFOL(fd,34)=0; // Honor: (left) Vulgar [-100,100] Famed (right)
+ WFIFOL(fd,38)=0; // Virtue: (down) Wicked [-100,100] Righteous (up)
WFIFOL(fd,42)=g->emblem_id;
memcpy(WFIFOP(fd,46),g->name, NAME_LENGTH);
memcpy(WFIFOP(fd,70),g->master, NAME_LENGTH);
@@ -7515,7 +7527,7 @@ void clif_guild_memberlist(struct map_session_data *sd)
WFIFOL(fd,c*104+22)=(int)cap_value(m->exp,0,INT32_MAX);
WFIFOL(fd,c*104+26)=m->online;
WFIFOL(fd,c*104+30)=m->position;
- memset(WFIFOP(fd,c*104+34),0,50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty.
+ memset(WFIFOP(fd,c*104+34),0,50); //[Ind] - This is displayed in the 'note' column but being you can't edit it it's sent empty.
memcpy(WFIFOP(fd,c*104+84),m->name,NAME_LENGTH);
c++;
}
@@ -8445,7 +8457,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 {
@@ -8478,10 +8490,9 @@ void clif_refresh(struct map_session_data *sd)
clif->updatestatus(sd,SP_LUK);
if (sd->spiritball)
clif->spiritball_single(sd->fd, sd);
- for(i = 1; i < 5; i++){
- if( sd->charm[i] > 0 )
- clif->charm_single(sd->fd, sd, i);
- }
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
+ clif->charm_single(sd->fd, sd, i);
+
if (sd->vd.cloth_color)
clif->refreshlook(&sd->bl,sd->bl.id,LOOK_CLOTHES_COLOR,sd->vd.cloth_color,SELF);
if(homun_alive(sd->hd))
@@ -8633,9 +8644,11 @@ void clif_charnameack (int fd, struct block_list *bl)
}
}
break;
- case BL_CHAT: //FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex]
- // memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH);
- // break;
+ case BL_CHAT:
+#if 0 //FIXME: Clients DO request this... what should be done about it? The chat's title may not fit... [Skotlex]
+ memcpy(WBUFP(buf,6), (struct chat*)->title, NAME_LENGTH);
+ break;
+#endif
return;
case BL_ELEM:
memcpy(WBUFP(buf,6), ((TBL_ELEM*)bl)->db->name, NAME_LENGTH);
@@ -8944,7 +8957,7 @@ void clif_viewequip_ack(struct map_session_data* sd, struct map_session_data* ts
for( i = 0; i < EQI_MAX; i++ ) {
if( (k = tsd->equip_index[i]) >= 0 ) {
- if (tsd->status.inventory[k].nameid <= 0 || tsd->inventory_data[k] == NULL) // Item doesn't exist
+ if (tsd->status.inventory[k].nameid <= 0 || tsd->inventory_data[k] == NULL) // Item doesn't exist
continue;
clif_item_equip(k+2,&viewequip_list.list[equip++],&tsd->status.inventory[k],tsd->inventory_data[k],pc->equippoint(tsd,k));
@@ -9035,8 +9048,8 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_,
packetlen = RFIFOW(fd,2);
// basic structure checks
- if( packetlen < 4 + 1 )
- { // 4-byte header and at least an empty string is expected
+ if (packetlen < 4 + 1) {
+ // 4-byte header and at least an empty string is expected
ShowWarning("clif_process_message: Received malformed packet from player '%s' (no message data)!\n", sd->status.name);
return false;
}
@@ -9075,8 +9088,8 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_,
name = text;
namelen = strnlen(name, NAME_LENGTH-1); // name length (w/o zero byte)
- if( name[namelen] != '\0' )
- { // only restriction is that the name must be zero-terminated
+ if (name[namelen] != '\0') {
+ // only restriction is that the name must be zero-terminated
ShowWarning("clif_process_message: Player '%s' sent an unterminated name!\n", sd->status.name);
return false;
}
@@ -9085,19 +9098,19 @@ bool clif_process_message(struct map_session_data *sd, int format, char **name_,
messagelen = textlen - NAME_LENGTH; // this should be the message length (w/ zero byte included)
}
- if( messagelen != strnlen(message, messagelen)+1 )
- { // the declared length must match real length
+ if (messagelen != strnlen(message, messagelen)+1) {
+ // the declared length must match real length
ShowWarning("clif_process_message: Received malformed packet from player '%s' (length is incorrect)!\n", sd->status.name);
return false;
}
// verify <message> part of the packet
- if( message[messagelen-1] != '\0' )
- { // message must be zero-terminated
+ if (message[messagelen-1] != '\0') {
+ // message must be zero-terminated
ShowWarning("clif_process_message: Player '%s' sent an unterminated message string!\n", sd->status.name);
return false;
}
- if( messagelen > CHAT_SIZE_MAX-1 )
- { // messages mustn't be too long
+ if (messagelen > CHAT_SIZE_MAX-1) {
+ // messages mustn't be too long
// Normally you can only enter CHATBOX_SIZE-1 letters into the chat box, but Frost Joke / Dazzler's text can be longer.
// Also, the physical size of strings that use multibyte encoding can go multiple times over the chatbox capacity.
// Neither the official client nor server place any restriction on the length of the data in the packet,
@@ -9122,7 +9135,7 @@ void clif_hercules_chsys_msg(struct hChSysCh *channel, struct map_session_data *
WFIFOW(sd->fd,0) = 0x2C1;
WFIFOW(sd->fd,2) = msg_len + 12;
WFIFOL(sd->fd,4) = 0;
- WFIFOL(sd->fd,8) = hChSys.colors[channel->color];
+ WFIFOL(sd->fd,8) = clif->hChSys->colors[channel->color];
safestrncpy((char*)WFIFOP(sd->fd,12), msg, msg_len);
for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) {
@@ -9147,7 +9160,7 @@ void clif_hercules_chsys_msg2(struct hChSysCh *channel, char *msg) {
WBUFW(buf,0) = 0x2C1;
WBUFW(buf,2) = msg_len + 12;
WBUFL(buf,4) = 0;
- WBUFL(buf,8) = hChSys.colors[channel->color];
+ WBUFL(buf,8) = clif->hChSys->colors[channel->color];
safestrncpy((char*)WBUFP(buf,12), msg, msg_len);
for( user = dbi_first(iter); dbi_exists(iter); user = dbi_next(iter) ) {
@@ -9248,11 +9261,11 @@ void clif_hercules_chsys_mjoin(struct map_session_data *sd) {
return;
CREATE(map->list[sd->bl.m].channel, struct hChSysCh , 1);
- safestrncpy(map->list[sd->bl.m].channel->name, hChSys.local_name, HCHSYS_NAME_LENGTH);
+ safestrncpy(map->list[sd->bl.m].channel->name, clif->hChSys->local_name, HCHSYS_NAME_LENGTH);
map->list[sd->bl.m].channel->type = hChSys_MAP;
map->list[sd->bl.m].channel->m = sd->bl.m;
- clif->chsys_create(map->list[sd->bl.m].channel,NULL,NULL,hChSys.local_color);
+ clif->chsys_create(map->list[sd->bl.m].channel, NULL, NULL, clif->hChSys->local_color);
}
if( map->list[sd->bl.m].channel->banned && idb_exists(map->list[sd->bl.m].channel->banned, sd->status.account_id) ) {
@@ -9263,7 +9276,7 @@ void clif_hercules_chsys_mjoin(struct map_session_data *sd) {
if( !( map->list[sd->bl.m].channel->opt & hChSys_OPT_ANNOUNCE_JOIN ) ) {
char mout[60];
- sprintf(mout, msg_txt(1435),hChSys.local_name,map->list[sd->bl.m].name); // You're now in the '#%s' channel for '%s'
+ sprintf(mout, msg_txt(1435), clif->hChSys->local_name, map->list[sd->bl.m].name); // You're now in the '#%s' channel for '%s'
clif->colormes(sd->fd, COLOR_DEFAULT, mout);
}
}
@@ -9340,7 +9353,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++;
}
@@ -9361,7 +9374,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);
@@ -9397,7 +9410,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
clif->spawn(&sd->pd->bl);
clif->send_petdata(sd,sd->pd,0,0);
clif->send_petstatus(sd);
-// skill->unit_move(&sd->pd->bl,timer->gettick(),1);
+ //skill->unit_move(&sd->pd->bl,timer->gettick(),1);
}
}
@@ -9446,11 +9459,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)
@@ -9538,7 +9551,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
status_calc_pc(sd, SCO_NONE);/* some conditions are map-dependent so we must recalculate */
sd->state.changemap = false;
- if( hChSys.local && hChSys.local_autojoin ) {
+ if (clif->hChSys->local && clif->hChSys->local_autojoin) {
clif->chsys_mjoin(sd);
}
}
@@ -9584,7 +9597,7 @@ void clif_parse_LoadEndAck(int fd,struct map_session_data *sd) {
if (map->getcell(sd->bl.m,sd->bl.x,sd->bl.y,CELL_CHKNPC))
npc->touch_areanpc(sd,sd->bl.m,sd->bl.x,sd->bl.y);
else
- sd->areanpc_id = 0;
+ npc->untouch_areanpc(sd, sd->bl.m, sd->bl.x, sd->bl.y);
/* it broke at some point (e.g. during a crash), so we make it visibly dead again. */
if( !sd->status.hp && !pc_isdead(sd) && status->isdead(&sd->bl) )
@@ -9651,18 +9664,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
@@ -9786,7 +9803,7 @@ void clif_disconnect_ack(struct map_session_data* sd, short result)
/// 0 = quit
void clif_parse_QuitGame(int fd, struct map_session_data *sd)
{
- /* Rovert's prevent logout option fixed [Valaris] */
+ /* Rovert's prevent logout option fixed [Valaris] */
if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] &&
(!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
{
@@ -9813,7 +9830,7 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) {
bl = map->id2bl(id);
if( bl == NULL )
- return; // Lagged clients could request names of already gone mobs/players. [Skotlex]
+ return; // Lagged clients could request names of already gone mobs/players. [Skotlex]
if( sd->bl.m != bl->m || !check_distance_bl(&sd->bl, bl, AREA_SIZE) )
return; // Block namerequests past view range
@@ -9921,7 +9938,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
sd->fontcolor_tid = timer->add(timer->gettick()+5000, clif->undisguise_timer, sd->bl.id, 0);
pc->disguise(sd,sd->status.class_);
if( pc_isdead(sd) )
- clif_clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd);
+ clif->clearunit_single(-sd->bl.id, CLR_DEAD, sd->fd);
if( unit->is_walking(&sd->bl) )
clif->move(&sd->ud);
} else if ( sd->disguise == sd->status.class_ && sd->fontcolor_tid != INVALID_TIMER ) {
@@ -9937,7 +9954,7 @@ void clif_parse_GlobalMessage(int fd, struct map_session_data* sd)
WFIFOW(fd,0) = 0x2C1;
WFIFOW(fd,2) = mylen + 12;
WFIFOL(fd,4) = sd->bl.id;
- WFIFOL(fd,8) = hChSys.colors[sd->fontcolor - 1];
+ WFIFOL(fd,8) = clif->hChSys->colors[sd->fontcolor - 1];
safestrncpy((char*)WFIFOP(fd,12), mout, mylen);
clif->send(WFIFOP(fd,0), WFIFOW(fd,2), &sd->bl, AREA_WOS);
WFIFOL(fd,4) = -sd->bl.id;
@@ -10123,7 +10140,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]
@@ -10173,6 +10191,7 @@ void clif_parse_ActionRequest_sub(struct map_session_data *sd, int action_type,
if (sd->sc.count && (
sd->sc.data[SC_DANCING] ||
+ sd->sc.data[SC_ANKLESNARE] ||
(sd->sc.data[SC_GRAVITATION] && sd->sc.data[SC_GRAVITATION]->val3 == BCT_SELF)
)) //No sitting during these states either.
break;
@@ -10212,7 +10231,7 @@ void clif_hercules_chsys_left(struct hChSysCh *channel, struct map_session_data
if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) {
clif->chsys_delete(channel);
- } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
+ } else if( !clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
char message[60];
sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
clif->chsys_msg(channel,sd,message);
@@ -10256,9 +10275,9 @@ void clif_hercules_chsys_quitg(struct map_session_data *sd) {
if( channel == sd->gcbind )
sd->gcbind = NULL;
- if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) {
+ if (!db_size(channel->users) && channel->type == hChSys_PRIVATE) {
clif->chsys_delete(channel);
- } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
+ } else if (!clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) {
char message[60];
sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
clif->chsys_msg(channel,sd,message);
@@ -10297,9 +10316,9 @@ void clif_hercules_chsys_quit(struct map_session_data *sd) {
if( channel == sd->gcbind )
sd->gcbind = NULL;
- if( !db_size(channel->users) && channel->type == hChSys_PRIVATE ) {
+ if (!db_size(channel->users) && channel->type == hChSys_PRIVATE) {
clif->chsys_delete(channel);
- } else if( !hChSys.closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN) ) {
+ } else if (!clif->hChSys->closing && (channel->opt & hChSys_OPT_ANNOUNCE_JOIN)) {
char message[60];
sprintf(message, "#%s '%s' left",channel->name,sd->status.name);
clif->chsys_msg(channel,sd,message);
@@ -10345,10 +10364,12 @@ void clif_parse_Restart(int fd, struct map_session_data *sd) {
pc->respawn(sd,CLR_OUTSIGHT);
break;
case 0x01:
- /* Rovert's Prevent logout option - Fixed [Valaris] */
- if( !sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK] && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY] &&
- (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout) )
- { //Send to char-server for character selection.
+ /* Rovert's Prevent logout option - Fixed [Valaris] */
+ if (!sd->sc.data[SC_CLOAKING] && !sd->sc.data[SC_HIDING] && !sd->sc.data[SC_CHASEWALK]
+ && !sd->sc.data[SC_CLOAKINGEXCEED] && !sd->sc.data[SC__INVISIBILITY]
+ && (!battle_config.prevent_logout || DIFF_TICK(timer->gettick(), sd->canlog_tick) > battle_config.prevent_logout)
+ ) {
+ //Send to char-server for character selection.
chrif->charselectreq(sd, session[fd]->client_addr);
} else {
clif->disconnect_ack(sd, 1);
@@ -10436,12 +10457,12 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
chname++;
- if( hChSys.local && strcmpi(chname, hChSys.local_name) == 0 ) {
+ if (clif->hChSys->local && strcmpi(chname, clif->hChSys->local_name) == 0) {
if( !map->list[sd->bl.m].channel ) {
clif->chsys_mjoin(sd);
}
channel = map->list[sd->bl.m].channel;
- } else if( hChSys.ally && sd->status.guild_id && strcmpi(chname, hChSys.ally_name) == 0 ) {
+ } else if (clif->hChSys->ally && sd->status.guild_id && strcmpi(chname, clif->hChSys->ally_name) == 0) {
struct guild *g = sd->guild;
if( !g ) return;
channel = g->channel;
@@ -10488,7 +10509,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
@@ -10496,7 +10517,7 @@ void clif_parse_WisMessage(int fd, struct map_session_data* sd)
}
// if player is autotrading
- if( dstsd->state.autotrade == 1 ) {
+ if( dstsd->state.autotrade ) {
char output[256];
sprintf(output, "%s is in autotrade mode and cannot receive whispered messages.", dstsd->status.name);
clif->wis_message(fd, map->wisp_server_name, output, strlen(output) + 1);
@@ -10692,7 +10713,7 @@ void clif_parse_EquipItem(int fd,struct map_session_data *sd) {
}
void clif_hercules_chsys_delete(struct hChSysCh *channel) {
- if( db_size(channel->users) && !hChSys.closing ) {
+ if (db_size(channel->users) && !clif->hChSys->closing) {
DBIterator *iter;
struct map_session_data *sd;
unsigned char i;
@@ -10732,7 +10753,7 @@ void clif_hercules_chsys_delete(struct hChSysCh *channel) {
aFree(channel);
} else if ( channel->type == hChSys_ALLY )
aFree(channel);
- else if( !hChSys.closing )
+ else if (!clif->hChSys->closing)
strdb_remove(clif->channel_db, channel->name);
}
void clif_hercules_chsys_gjoin(struct guild *g1,struct guild *g2) {
@@ -10817,7 +10838,7 @@ void clif_parse_NpcClicked(int fd,struct map_session_data *sd)
struct block_list *bl;
if( pc_isdead(sd) ) {
- clif_clearunit_area(&sd->bl,CLR_DEAD);
+ clif->clearunit_area(&sd->bl,CLR_DEAD);
return;
}
if( sd->npc_id || sd->state.workinprogress&2 ){
@@ -10886,7 +10907,7 @@ void clif_parse_NpcBuyListSend(int fd, struct map_session_data* sd)
unsigned short* item_list = (unsigned short*)RFIFOP(fd,4);
int result;
- if( sd->state.trading || !sd->npc_shopid )
+ if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) )
result = 1;
else
result = npc->buylist(sd,n,item_list);
@@ -11162,16 +11183,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
+ }
}
@@ -11247,15 +11269,23 @@ void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_dat
if( !hd )
return;
- if( skill->not_ok_hom(skill_id, hd) )
+ if (skill->not_ok_hom(skill_id, hd)){
+ clif->emotion(&hd->bl, E_DOTS);
return;
- if( hd->bl.id != target_id && skill->get_inf(skill_id)&INF_SELF_SKILL )
+ }
+ if (hd->bl.id != target_id && skill->get_inf(skill_id)&INF_SELF_SKILL)
target_id = hd->bl.id;
- if( hd->ud.skilltimer != INVALID_TIMER ) {
- if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return;
- } else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 )
+ if (hd->ud.skilltimer != INVALID_TIMER) {
+ if (skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST) return;
+ }
+ else if (DIFF_TICK(tick, hd->ud.canact_tick) < 0){
+ clif->emotion(&hd->bl, E_DOTS);
+ if (hd->master)
+ clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
return;
+ }
+
lv = homun->checkskill(hd, skill_id);
if( skill_lv > lv )
skill_lv = lv;
@@ -11267,12 +11297,19 @@ void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_da
int lv;
if( !hd )
return;
- if( skill->not_ok_hom(skill_id, hd) )
+ if (skill->not_ok_hom(skill_id, hd)){
+ clif->emotion(&hd->bl, E_DOTS);
return;
- if( hd->ud.skilltimer != INVALID_TIMER ) {
- if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return;
- } else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 )
+ }
+ if ( hd->ud.skilltimer != INVALID_TIMER ) {
+ if ( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return;
+
+ } else if ( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) {
+ clif->emotion(&hd->bl, E_DOTS);
+ if ( hd->master )
+ clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0);
return;
+ }
if( hd->sc.data[SC_BASILICA] )
return;
@@ -11413,7 +11450,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( skill_lv != sd->skillitemlv )
skill_lv = sd->skillitemlv;
if( !(tmp&INF_SELF_SKILL) )
- pc->delinvincibletimer(sd); // Target skills thru items cancel invincibility. [Inkfish]
+ pc->delinvincibletimer(sd); // Target skills through items cancel invincibility. [Inkfish]
unit->skilluse_id(&sd->bl, target_id, skill_id, skill_lv);
return;
}
@@ -11536,7 +11573,7 @@ void clif_parse_UseSkillToPos(int fd, struct map_session_data *sd)
RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[1]), //skill num
RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[2]), //pos x
RFIFOW(fd,packet_db[RFIFOW(fd,0)].pos[3]), //pos y
- -1 //Skill more info.
+ -1 //Skill more info.
);
}
@@ -12215,8 +12252,7 @@ void clif_parse_PartyMessage(int fd, struct map_session_data* sd)
if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
- if( battle_config.min_chat_delay )
- { //[Skotlex]
+ if (battle_config.min_chat_delay) {
if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
return;
sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
@@ -12234,7 +12270,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]
///
@@ -12721,11 +12757,11 @@ void clif_parse_PartyBookingAckRecall(int fd, struct map_session_data *sd)
/// 08f8 <caller AID>.L <reason>.B
/// <reason>:
-/// REASON_PROHIBITION = 0x0
-/// REASON_MASTER_IN_PROHIBITION_MAP = 0x1
-/// REASON_REFUSE = 0x2
-/// REASON_NOT_PARTY_MEMBER = 0x3
-/// REASON_ETC = 0x4
+/// REASON_PROHIBITION = 0x0
+/// REASON_MASTER_IN_PROHIBITION_MAP = 0x1
+/// REASON_REFUSE = 0x2
+/// REASON_NOT_PARTY_MEMBER = 0x3
+/// REASON_ETC = 0x4
void clif_PartyBookingFailedRecall(int fd, struct map_session_data *sd)
{
}
@@ -12951,22 +12987,22 @@ void clif_parse_GuildRequestInfo(int fd, struct map_session_data *sd)
return;
switch( RFIFOL(fd,2) ) {
- case 0: // Basic Information Guild, hostile alliance information
+ case 0: // Basic Information Guild, hostile alliance information
clif->guild_basicinfo(sd);
clif->guild_allianceinfo(sd);
break;
- case 1: // Members list, list job title
+ case 1: // Members list, list job title
clif->guild_positionnamelist(sd);
clif->guild_memberlist(sd);
break;
- case 2: // List job title, title information list
+ case 2: // List job title, title information list
clif->guild_positionnamelist(sd);
clif->guild_positioninfolist(sd);
break;
- case 3: // Skill list
+ case 3: // Skill list
clif->guild_skillinfo(sd);
break;
- case 4: // Expulsion list
+ case 4: // Expulsion list
clif->guild_expulsionlist(sd);
break;
default:
@@ -13278,8 +13314,7 @@ void clif_parse_GuildMessage(int fd, struct map_session_data* sd)
if( sd->sc.data[SC_BERSERK] || (sd->sc.data[SC_DEEP_SLEEP] && sd->sc.data[SC_DEEP_SLEEP]->val2) || (sd->sc.data[SC_NOCHAT] && sd->sc.data[SC_NOCHAT]->val1&MANNER_NOCHAT) )
return;
- if( battle_config.min_chat_delay )
- { //[Skotlex]
+ if (battle_config.min_chat_delay) {
if (DIFF_TICK(sd->cantalk_tick, timer->gettick()) > 0)
return;
sd->cantalk_tick = timer->gettick() + battle_config.min_chat_delay;
@@ -14259,8 +14294,8 @@ void clif_PVPInfo(struct map_session_data* sd) {
WFIFOW(fd,0) = 0x210;
WFIFOL(fd,2) = sd->status.char_id;
WFIFOL(fd,6) = sd->status.account_id;
- WFIFOL(fd,10) = sd->pvp_won; // times won
- WFIFOL(fd,14) = sd->pvp_lost; // times lost
+ WFIFOL(fd,10) = sd->pvp_won; // times won
+ WFIFOL(fd,14) = sd->pvp_lost; // times lost
WFIFOL(fd,18) = sd->pvp_point;
WFIFOSET(fd, packet_len(0x210));
}
@@ -14318,7 +14353,7 @@ void clif_ranklist(struct map_session_data *sd, enum fame_list_type type) {
WFIFOW(fd, 0) = 0x97d;
WFIFOW(fd, 2) = type;
clif_ranklist_sub(WFIFOP(fd,4), type);
-
+
if( (upperMask == MAPID_BLACKSMITH && type == RANKTYPE_BLACKSMITH)
|| (upperMask == MAPID_ALCHEMIST && type == RANKTYPE_ALCHEMIST)
|| (upperMask == MAPID_TAEKWON && type == RANKTYPE_TAEKWON)
@@ -14493,9 +14528,10 @@ void clif_parse_FeelSaveOk(int fd,struct map_session_data *sd)
sd->feel_map[i].m = sd->bl.m;
pc_setglobalreg(sd,script->add_str(pc->sg_info[i].feel_var),sd->feel_map[i].index);
-//Are these really needed? Shouldn't they show up automatically from the feel save packet?
-// clif_misceffect2(&sd->bl, 0x1b0);
-// clif_misceffect2(&sd->bl, 0x21f);
+#if 0 // Are these really needed? Shouldn't they show up automatically from the feel save packet?
+ clif_misceffect2(&sd->bl, 0x1b0);
+ clif_misceffect2(&sd->bl, 0x21f);
+#endif // 0
clif->feel_info(sd, i, 0);
clif_menuskill_clear(sd);
}
@@ -15116,7 +15152,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);
@@ -15281,7 +15318,7 @@ void clif_parse_Auction_setitem(int fd, struct map_session_data *sd)
!sd->status.inventory[idx].identify ||
!itemdb_canauction(&sd->status.inventory[idx],pc_get_group_level(sd)) || // Quest Item or something else
(sd->status.inventory[idx].bound && !pc_can_give_bound_items(sd)) ) {
- clif->auction_setitem(sd->fd, idx, true);
+ clif->auction_setitem(sd->fd, idx, true);
return;
}
@@ -15334,9 +15371,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);
@@ -15391,7 +15429,7 @@ void clif_parse_Auction_register(int fd, struct map_session_data *sd)
if( sd->status.inventory[sd->auction.index].bound && !pc_can_give_bound_items(sd) ) {
clif->message(sd->fd, msg_txt(293));
clif->auction_message(fd, 2); // The auction has been canceled
- return;
+ return;
}
safestrncpy(auction.item_name, item->jname, sizeof(auction.item_name));
@@ -15568,7 +15606,7 @@ void clif_cashshop_show(struct map_session_data *sd, struct npc_data *nd) {
/// For error return codes see enum cashshop_error@clif.h
void clif_cashshop_ack(struct map_session_data* sd, int error) {
struct npc_data *nd;
- int fd = sd->fd;
+ int fd = sd->fd;
int currency[2] = { 0,0 };
if( (nd = map->id2nd(sd->npc_shopid)) && nd->subtype == SCRIPT ) {
@@ -15599,34 +15637,33 @@ void clif_cashshop_ack(struct map_session_data* sd, int error) {
/// 0288 <packet len>.W <kafra points>.L <count>.W { <amount>.W <name id>.W }.4B*count (PACKETVER >= 20100803)
void clif_parse_cashshop_buy(int fd, struct map_session_data *sd)
{
- int fail = 0;
- nullpo_retv(sd);
+ int fail = 0;
+ nullpo_retv(sd);
- if( sd->state.trading || !sd->npc_shopid )
- fail = 1;
- else {
+ if( sd->state.trading || !sd->npc_shopid || pc_has_permission(sd,PC_PERM_DISABLE_STORE) )
+ fail = 1;
+ else {
#if PACKETVER < 20101116
- short nameid = RFIFOW(fd,2);
- short amount = RFIFOW(fd,4);
- int points = RFIFOL(fd,6);
+ short nameid = RFIFOW(fd,2);
+ short amount = RFIFOW(fd,4);
+ int points = RFIFOL(fd,6);
- fail = npc->cashshop_buy(sd, nameid, amount, points);
+ fail = npc->cashshop_buy(sd, nameid, amount, points);
#else
- int len = RFIFOW(fd,2);
- int points = RFIFOL(fd,4);
- int count = RFIFOW(fd,8);
- unsigned short* item_list = (unsigned short*)RFIFOP(fd,10);
-
- if( len < 10 || len != 10 + count * 4)
- {
- ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4);
- return;
- }
- fail = npc->cashshop_buylist(sd,points,count,item_list);
+ int len = RFIFOW(fd,2);
+ int points = RFIFOL(fd,4);
+ int count = RFIFOW(fd,8);
+ unsigned short* item_list = (unsigned short*)RFIFOP(fd,10);
+
+ if( len < 10 || len != 10 + count * 4) {
+ ShowWarning("Player %u sent incorrect cash shop buy packet (len %u:%u)!\n", sd->status.char_id, len, 10 + count * 4);
+ return;
+ }
+ fail = npc->cashshop_buylist(sd,points,count,item_list);
#endif
- }
+ }
- clif->cashshop_ack(sd,fail);
+ clif->cashshop_ack(sd,fail);
}
@@ -15795,18 +15832,33 @@ void clif_parse_PartyTick(int fd, struct map_session_data* sd)
void clif_quest_send_list(struct map_session_data *sd) {
int fd = sd->fd;
int i;
- int len = sd->avail_quests*5+8;
-
+#if PACKETVER >= 20141022
+ int info_len = 15;
+ int len = sd->avail_quests*info_len+8;
+ WFIFOHEAD(fd,len);
+ 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);
}
@@ -16566,8 +16618,8 @@ void clif_parse_ItemListWindowSelected(int fd, struct map_session_data* sd) {
case 0: // Change Material
skill->changematerial(sd,n,item_list);
break;
- case 1: // Level 1: Pure to Rough
- case 2: // Level 2: Rough to Pure
+ case 1: // Level 1: Pure to Rough
+ case 2: // Level 2: Rough to Pure
skill->elementalanalysis(sd,n,type,item_list);
break;
}
@@ -17406,10 +17458,13 @@ void clif_charm(struct map_session_data *sd,short type)
nullpo_retv(sd);
+ if ( type <= SPIRITS_TYPE_NONE || type >= SPIRITS_TYPE_SPHERE )
+ return;
+
WBUFW(buf,0)=0x08cf;
WBUFL(buf,2)=sd->bl.id;
WBUFW(buf,6)=type;
- WBUFW(buf,8)=sd->charm[type];
+ WBUFW(buf,8)=sd->spiritcharm[type];
clif->send(buf,packet_len(0x08cf),&sd->bl,AREA);
}
/// Move Item from or to Personal Tab (CZ_WHATSOEVER) [FE]
@@ -17417,8 +17472,8 @@ void clif_charm(struct map_session_data *sd,short type)
///
/// R 0908 <index>.w <type>.b
/// type:
-/// 0 = move item to personal tab
-/// 1 = move item to normal tab
+/// 0 = move item to personal tab
+/// 1 = move item to normal tab
void clif_parse_MoveItem(int fd, struct map_session_data *sd) {
#if PACKETVER >= 20111122
int index;
@@ -17697,13 +17752,17 @@ void clif_parse_CashShopReqTab(int fd, struct map_session_data *sd) {
void clif_maptypeproperty2(struct block_list *bl,enum send_target t) {
#if PACKETVER >= 20121010
struct packet_maptypeproperty2 p;
+ struct map_session_data *sd = NULL;
+ nullpo_retv(bl);
+
+ sd = BL_CAST(BL_PC, bl);
p.PacketType = maptypeproperty2Type;
p.type = 0x28;
p.flag.party = map->list[bl->m].flag.pvp ? 1 : 0;
- p.flag.guild = map_flag_gvg(bl->m) ? 1 : 0;
- p.flag.siege = map_flag_gvg2(bl->m) ? 1: 0;
- p.flag.mineffect = map_flag_gvg(bl->m); // FIXME/CHECKME Forcing /mineffect in castles during WoE (probably redundant? I'm not sure)
+ p.flag.guild = (map->list[bl->m].flag.battleground || map_flag_gvg(bl->m)) ? 1 : 0;
+ p.flag.siege = (map->list[bl->m].flag.battleground || map_flag_gvg2(bl->m)) ? 1: 0;
+ p.flag.mineffect = map_flag_gvg(bl->m) ? 1 : ( (sd && sd->state.lesseffect) ? 1 : 0); // Forcing /mineffect in castles during WoE (probably redundant? I'm not sure)
p.flag.nolockon = 0; // TODO
p.flag.countpk = map->list[bl->m].flag.pvp ? 1 : 0;
p.flag.nopartyformation = map->list[bl->m].flag.partylock ? 1 : 0;
@@ -17836,7 +17895,7 @@ void clif_bgqueue_update_info(struct map_session_data *sd, unsigned char arena_i
safestrncpy(p.bg_name, bg->arena[arena_id]->name, sizeof(p.bg_name));
p.position = position;
- sd->bg_queue.client_has_bg_data = true; // Client creates bg data when this packet arrives
+ sd->bg_queue.client_has_bg_data = true; // Client creates bg data when this packet arrives
clif->send(&p,sizeof(p), &sd->bl, SELF);
}
@@ -18254,6 +18313,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 = (char)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 ) {
@@ -18533,7 +18882,7 @@ int do_init_clif(bool minimal) {
clif->delayed_damage_ers = ers_new(sizeof(struct cdelayed_damage),"clif.c::delayed_damage_ers",ERS_OPT_CLEAR);
clif->channel_db = stridb_alloc(DB_OPT_DUP_KEY|DB_OPT_RELEASE_DATA, HCHSYS_NAME_LENGTH);
- hChSys.ally = hChSys.local = hChSys.irc = hChSys.ally_autojoin = hChSys.local_autojoin = false;
+ clif->hChSys->ally = clif->hChSys->local = clif->hChSys->irc = clif->hChSys->ally_autojoin = clif->hChSys->local_autojoin = false;
clif->chann_config_read();
return 0;
@@ -18550,13 +18899,13 @@ void do_final_clif(void) {
dbi_destroy(iter);
- for(i = 0; i < hChSys.colors_count; i++) {
- aFree(hChSys.colors_name[i]);
+ for(i = 0; i < clif->hChSys->colors_count; i++) {
+ aFree(clif->hChSys->colors_name[i]);
}
- if( hChSys.colors_count ) {
- aFree(hChSys.colors_name);
- aFree(hChSys.colors);
+ if (clif->hChSys->colors_count) {
+ aFree(clif->hChSys->colors_name);
+ aFree(clif->hChSys->colors);
}
db_destroy(clif->channel_db);
@@ -18570,6 +18919,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) {
@@ -18588,6 +18944,7 @@ void clif_defaults(void) {
clif->refresh_ip = clif_refresh_ip;
clif->send = clif_send;
clif->send_sub = clif_send_sub;
+ clif->send_actual = clif_send_actual;
clif->parse = clif_parse;
clif->parse_cmd = clif_parse_cmd_optional;
clif->decrypt_cmd = clif_decrypt_cmd;
@@ -18632,6 +18989,7 @@ void clif_defaults(void) {
clif->changelook = clif_changelook;
clif->changetraplook = clif_changetraplook;
clif->refreshlook = clif_refreshlook;
+ clif->sendlook = clif_sendlook;
clif->class_change = clif_class_change;
clif->skill_delunit = clif_skill_delunit;
clif->skillunit_update = clif_skillunit_update;
@@ -18800,7 +19158,7 @@ void clif_defaults(void) {
clif->specialeffect_single = clif_specialeffect_single;
clif->specialeffect_value = clif_specialeffect_value;
clif->millenniumshield = clif_millenniumshield;
- clif->charm = clif_charm;
+ clif->spiritcharm = clif_charm;
clif->charm_single = clif_charm_single;
clif->snap = clif_snap;
clif->weather_check = clif_weather_check;
@@ -18884,6 +19242,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;
@@ -19045,6 +19404,7 @@ void clif_defaults(void) {
clif->bc_ready = clif_bc_ready;
clif->undisguise_timer = clif_undisguise_timer;
/* Hercules Channel System */
+ clif->hChSys = &clif_hChSys;
clif->chsys_create = clif_hercules_chsys_create;
clif->chsys_msg = clif_hercules_chsys_msg;
clif->chsys_msg2 = clif_hercules_chsys_msg2;
@@ -19070,6 +19430,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 +19662,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..4c90a3a28 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;
@@ -48,8 +46,10 @@ struct skill_cd;
#define P2PTR(fd) RFIFO2PTR(fd)
#define clif_menuskill_clear(sd) ((sd)->menuskill_id = (sd)->menuskill_val = (sd)->menuskill_val2 = 0)
#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 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
@@ -86,14 +86,14 @@ typedef enum send_target {
DUEL,
DUEL_WOS,
SELF,
-
+
BG, // BattleGround System
BG_WOS,
BG_SAMEMAP,
BG_SAMEMAP_WOS,
BG_AREA,
BG_AREA_WOS,
-
+
BG_QUEUE,
} send_target;
@@ -340,6 +340,7 @@ typedef enum useskill_fail_cause { // clif_skill_fail
USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 81,
USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 82,
USESKILL_FAIL_THERE_ARE_NPC_AROUND = 83,
+ USESKILL_FAIL_NEED_MORE_BULLET = 84,
}useskill_fail_cause;
enum clif_messages {
@@ -352,16 +353,16 @@ enum clif_messages {
* Used to answer CZ_PC_BUY_CASH_POINT_ITEM (clif_parse_cashshop_buy)
**/
enum cashshop_error {
- ERROR_TYPE_NONE = 0, // The deal has successfully completed. (ERROR_TYPE_NONE)
- ERROR_TYPE_NPC, // The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC)
- ERROR_TYPE_SYSTEM, // The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM)
- ERROR_TYPE_INVENTORY_WEIGHT, // You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT)
- ERROR_TYPE_EXCHANGE, // You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE)
- ERROR_TYPE_ITEM_ID, // The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID)
- ERROR_TYPE_MONEY, // You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY)
+ ERROR_TYPE_NONE = 0, ///< The deal has successfully completed. (ERROR_TYPE_NONE)
+ ERROR_TYPE_NPC = 1, ///< The Purchase has failed because the NPC does not exist. (ERROR_TYPE_NPC)
+ ERROR_TYPE_SYSTEM = 2, ///< The Purchase has failed because the Kafra Shop System is not working correctly. (ERROR_TYPE_SYSTEM)
+ ERROR_TYPE_INVENTORY_WEIGHT = 3, ///< You are over your Weight Limit. (ERROR_TYPE_INVENTORY_WEIGHT)
+ ERROR_TYPE_EXCHANGE = 4, ///< You cannot purchase items while you are in a trade. (ERROR_TYPE_EXCHANGE)
+ ERROR_TYPE_ITEM_ID = 5, ///< The Purchase has failed because the Item Information was incorrect. (ERROR_TYPE_ITEM_ID)
+ ERROR_TYPE_MONEY = 6, ///< You do not have enough Kafra Credit Points. (ERROR_TYPE_MONEY)
// Unofficial type names
- ERROR_TYPE_QUANTITY, // You can purchase up to 10 items. (ERROR_TYPE_QUANTITY)
- ERROR_TYPE_NOT_ALL, // Some items could not be purchased. (ERROR_TYPE_NOT_ALL)
+ ERROR_TYPE_QUANTITY = 7, ///< You can purchase up to 10 items. (ERROR_TYPE_QUANTITY)
+ ERROR_TYPE_NOT_ALL = 8, ///< Some items could not be purchased. (ERROR_TYPE_NOT_ALL)
};
/**
@@ -375,40 +376,40 @@ enum clif_colors {
};
enum hChSysChOpt {
- hChSys_OPT_BASE = 0x0,
- hChSys_OPT_ANNOUNCE_JOIN = 0x1,
- hChSys_OPT_MSG_DELAY = 0x2,
+ hChSys_OPT_BASE = 0x0,
+ hChSys_OPT_ANNOUNCE_JOIN = 0x1,
+ hChSys_OPT_MSG_DELAY = 0x2,
};
enum hChSysChType {
- hChSys_PUBLIC = 0,
- hChSys_PRIVATE = 1,
- hChSys_MAP = 2,
- hChSys_ALLY = 3,
- hChSys_IRC = 4,
+ hChSys_PUBLIC = 0,
+ hChSys_PRIVATE = 1,
+ hChSys_MAP = 2,
+ hChSys_ALLY = 3,
+ hChSys_IRC = 4,
};
enum CASH_SHOP_TABS {
- CASHSHOP_TAB_NEW = 0,
- CASHSHOP_TAB_POPULAR = 1,
- CASHSHOP_TAB_LIMITED = 2,
- CASHSHOP_TAB_RENTAL = 3,
+ CASHSHOP_TAB_NEW = 0,
+ CASHSHOP_TAB_POPULAR = 1,
+ CASHSHOP_TAB_LIMITED = 2,
+ CASHSHOP_TAB_RENTAL = 3,
CASHSHOP_TAB_PERPETUITY = 4,
- CASHSHOP_TAB_BUFF = 5,
- CASHSHOP_TAB_RECOVERY = 6,
- CASHSHOP_TAB_ETC = 7,
+ CASHSHOP_TAB_BUFF = 5,
+ CASHSHOP_TAB_RECOVERY = 6,
+ CASHSHOP_TAB_ETC = 7,
CASHSHOP_TAB_MAX,
};
enum CASH_SHOP_BUY_RESULT {
- CSBR_SUCCESS = 0x0,
- CSBR_SHORTTAGE_CASH = 0x2,
- CSBR_UNKONWN_ITEM = 0x3,
- CSBR_INVENTORY_WEIGHT = 0x4,
- CSBR_INVENTORY_ITEMCNT = 0x5,
- CSBR_RUNE_OVERCOUNT = 0x9,
- CSBR_EACHITEM_OVERCOUNT = 0xa,
- CSBR_UNKNOWN = 0xb,
+ CSBR_SUCCESS = 0x0,
+ CSBR_SHORTTAGE_CASH = 0x2,
+ CSBR_UNKONWN_ITEM = 0x3,
+ CSBR_INVENTORY_WEIGHT = 0x4,
+ CSBR_INVENTORY_ITEMCNT = 0x5,
+ CSBR_RUNE_OVERCOUNT = 0x9,
+ CSBR_EACHITEM_OVERCOUNT = 0xa,
+ CSBR_UNKNOWN = 0xb,
};
enum BATTLEGROUNDS_QUEUE_ACK {
@@ -478,6 +479,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
**/
@@ -488,7 +518,7 @@ struct s_packet_db {
short pos[MAX_PACKET_POS];
};
-struct {
+struct hChSysConfig {
unsigned int *colors;
char **colors_name;
unsigned char colors_count;
@@ -501,7 +531,7 @@ struct {
char irc_server[40], irc_channel[50], irc_nick[40], irc_nick_pw[30];
unsigned short irc_server_port;
bool irc_use_ghost;
-} hChSys;
+};
struct hChSysBanEntry {
char name[NAME_LENGTH];
@@ -547,6 +577,7 @@ struct clif_interface {
char map_ip_str[128];
int map_fd;
DBMap* channel_db;
+ struct hChSysConfig *hChSys;
/* for clif_clearunit_delayed */
struct eri *delay_clearunit_ers;
/* Cash Shop [Ind/Hercules] */
@@ -554,6 +585,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];
/* */
@@ -569,6 +606,7 @@ struct clif_interface {
uint32 (*refresh_ip) (void);
bool (*send) (const void* buf, int len, struct block_list* bl, enum send_target type);
int (*send_sub) (struct block_list *bl, va_list ap);
+ int (*send_actual) (int fd, void *buf, int len);
int (*parse) (int fd);
unsigned short (*parse_cmd) ( int fd, struct map_session_data *sd );
unsigned short (*decrypt_cmd) ( int cmd, struct map_session_data *sd );
@@ -613,6 +651,7 @@ struct clif_interface {
void (*changelook) (struct block_list *bl,int type,int val);
void (*changetraplook) (struct block_list *bl,int val);
void (*refreshlook) (struct block_list *bl,int id,int type,int val,enum send_target target);
+ void (*sendlook) (struct block_list *bl, int id, int type, int val, int val2, enum send_target target);
void (*class_change) (struct block_list *bl,int class_,int type);
void (*skill_delunit) (struct skill_unit *su);
void (*skillunit_update) (struct block_list* bl);
@@ -781,7 +820,7 @@ struct clif_interface {
void (*specialeffect_single) (struct block_list* bl, int type, int fd);
void (*specialeffect_value) (struct block_list* bl, int effect_id, int num, send_target target);
void (*millenniumshield) (struct block_list *bl, short shields );
- void (*charm) (struct map_session_data *sd, short type);
+ void (*spiritcharm) (struct map_session_data *sd, short type);
void (*charm_single) (int fd, struct map_session_data *sd, short type);
void (*snap) ( struct block_list *bl, short x, short y );
void (*weather_check) (struct map_session_data *sd);
@@ -866,6 +905,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 +1092,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 +1322,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/duel.c b/src/map/duel.c
index 4e4eeef1f..0ae2770c4 100644
--- a/src/map/duel.c
+++ b/src/map/duel.c
@@ -16,6 +16,8 @@
#include "pc.h"
#include "../common/cbasetypes.h"
+struct duel_interface duel_s;
+
/*==========================================
* Duel organizing functions [LuzZza]
*------------------------------------------*/
diff --git a/src/map/duel.h b/src/map/duel.h
index de2bd1bf6..5466f3b43 100644
--- a/src/map/duel.h
+++ b/src/map/duel.h
@@ -37,10 +37,10 @@ struct duel_interface {
void (*leave) (const unsigned int did, struct map_session_data* sd);
void (*showinfo) (const unsigned int did, struct map_session_data* sd);
int (*checktime) (struct map_session_data* sd);
-
+
void (*init) (bool minimal);
void (*final) (void);
-} duel_s;
+};
struct duel_interface *duel;
diff --git a/src/map/elemental.c b/src/map/elemental.c
index caba02692..50d6c34b3 100644
--- a/src/map/elemental.c
+++ b/src/map/elemental.c
@@ -218,6 +218,9 @@ int elemental_delete(struct elemental_data *ed, int reply) {
sd->ed = NULL;
sd->status.ele_id = 0;
+ if( !ed->bl.prev )
+ return unit->free(&ed->bl, 0);
+
return unit->remove_map(&ed->bl, 0, ALC_MARK);
}
@@ -243,7 +246,8 @@ int elemental_data_received(struct s_elemental *ele, bool flag) {
}
db = &elemental->db[i];
- if( !sd->ed ) { // Initialize it after first summon.
+ if( !sd->ed ) {
+ // Initialize it after first summon.
sd->ed = ed = (struct elemental_data*)aCalloc(1,sizeof(struct elemental_data));
ed->bl.type = BL_ELEM;
ed->bl.id = npc->get_new_npc_id();
@@ -319,8 +323,8 @@ int elemental_clean_single_effect(struct elemental_data *ed, uint16 skill_id) {
case SC_UPHEAVAL_OPTION:
case SC_CIRCLE_OF_FIRE_OPTION:
case SC_TIDAL_WEAPON_OPTION:
- if( bl ) status_change_end(bl,type,INVALID_TIMER); // Master
- status_change_end(&ed->bl,type-1,INVALID_TIMER); // Elemental Spirit
+ if( bl ) status_change_end(bl,type,INVALID_TIMER); // Master
+ status_change_end(&ed->bl,type-1,INVALID_TIMER); // Elemental Spirit
break;
case SC_ZEPHYR:
if( bl ) status_change_end(bl,type,INVALID_TIMER);
@@ -406,7 +410,7 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tic
return 0;
if( ed->target_id )
- elemental->unlocktarget(ed); // Remove previous target.
+ elemental->unlocktarget(ed); // Remove previous target.
ARR_FIND(0, MAX_ELESKILLTREE, i, ed->db->skill[i].id && (ed->db->skill[i].mode&EL_SKILLMODE_AGGRESSIVE));
if( i == MAX_ELESKILLTREE )
@@ -423,7 +427,7 @@ int elemental_action(struct elemental_data *ed, struct block_list *bl, int64 tic
else if( DIFF_TICK(tick, ed->ud.canact_tick) < 0 )
return 0;
- ed->target_id = ed->ud.skilltarget = bl->id; // Set new target
+ ed->target_id = ed->ud.skilltarget = bl->id; // Set new target
ed->last_thinktime = tick;
// Not in skill range.
@@ -501,7 +505,7 @@ int elemental_change_mode_ack(struct elemental_data *ed, int mode) {
else if( DIFF_TICK(timer->gettick(), ed->ud.canact_tick) < 0 )
return 0;
- ed->target_id = bl->id; // Set new target
+ ed->target_id = bl->id; // Set new target
ed->last_thinktime = timer->gettick();
if( skill->get_inf(skill_id) & INF_GROUND_SKILL )
@@ -509,7 +513,7 @@ int elemental_change_mode_ack(struct elemental_data *ed, int mode) {
else
unit->skilluse_id(&ed->bl,bl->id,skill_id,skill_lv);
- ed->target_id = 0; // Reset target after casting the skill to avoid continuous attack.
+ ed->target_id = 0; // Reset target after casting the skill to avoid continuous attack.
return 1;
}
@@ -529,9 +533,9 @@ int elemental_change_mode(struct elemental_data *ed, int mode) {
ed->battle_status.mode = ed->elemental.mode = mode;
// Normalize elemental mode to elemental skill mode.
- if( mode == EL_MODE_AGGRESSIVE ) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill.
- else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill.
- else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill.
+ if( mode == EL_MODE_AGGRESSIVE ) mode = EL_SKILLMODE_AGGRESSIVE; // Aggressive spirit mode -> Aggressive spirit skill.
+ else if( mode == EL_MODE_ASSIST ) mode = EL_SKILLMODE_ASSIST; // Assist spirit mode -> Assist spirit skill.
+ else mode = EL_SKILLMODE_PASIVE; // Passive spirit mode -> Passive spirit skill.
// Use a skill immediately after every change mode.
if( mode != EL_SKILLMODE_AGGRESSIVE )
@@ -577,7 +581,7 @@ struct skill_condition elemental_skill_get_requirements(uint16 skill_id, uint16
memset(&req,0,sizeof(req));
if( idx == 0 ) // invalid skill id
- return req;
+ return req;
if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
return req;
@@ -657,12 +661,16 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s
int sp = 5;
switch(ed->vd->class_){
- case 2115: case 2118:
- case 2121: case 2124:
+ case 2115:
+ case 2118:
+ case 2121:
+ case 2124:
sp = 8;
break;
- case 2116: case 2119:
- case 2122: case 2125:
+ case 2116:
+ case 2119:
+ case 2122:
+ case 2125:
sp = 11;
break;
}
@@ -698,13 +706,15 @@ int elemental_ai_sub_timer(struct elemental_data *ed, struct map_session_data *s
mode = status_get_mode(&ed->bl);
master_dist = distance_bl(&sd->bl, &ed->bl);
- if( master_dist > AREA_SIZE ) { // Master out of vision range.
+ if( master_dist > AREA_SIZE ) {
+ // Master out of vision range.
elemental->unlocktarget(ed);
unit->warp(&ed->bl,sd->bl.m,sd->bl.x,sd->bl.y,CLR_TELEPORT);
clif->elemental_updatestatus(sd,SP_HP);
clif->elemental_updatestatus(sd,SP_SP);
return 0;
- } else if( master_dist > MAX_ELEDISTANCE ) { // Master too far, chase.
+ } else if( master_dist > MAX_ELEDISTANCE ) {
+ // Master too far, chase.
short x = sd->bl.x, y = sd->bl.y;
if( ed->target_id )
elemental->unlocktarget(ed);
diff --git a/src/map/elemental.h b/src/map/elemental.h
index 0c8fff8b3..ca13c30b8 100644
--- a/src/map/elemental.h
+++ b/src/map/elemental.h
@@ -79,22 +79,22 @@ struct elemental_interface {
/* funcs */
bool (*class) (int class_);
struct view_data * (*get_viewdata) (int class_);
-
+
int (*create) (struct map_session_data *sd, int class_, unsigned int lifetime);
int (*data_received) (struct s_elemental *ele, bool flag);
int (*save) (struct elemental_data *ed);
-
+
int (*change_mode_ack) (struct elemental_data *ed, int mode);
int (*change_mode) (struct elemental_data *ed, int mode);
-
+
void (*heal) (struct elemental_data *ed, int hp, int sp);
int (*dead) (struct elemental_data *ed);
-
+
int (*delete) (struct elemental_data *ed, int reply);
void (*summon_stop) (struct elemental_data *ed);
-
+
int (*get_lifetime) (struct elemental_data *ed);
-
+
int (*unlocktarget) (struct elemental_data *ed);
int (*skillnotok) (uint16 skill_id, struct elemental_data *ed);
int (*set_target) (struct map_session_data *sd, struct block_list *bl);
@@ -102,11 +102,11 @@ struct elemental_interface {
int (*clean_effect) (struct elemental_data *ed);
int (*action) (struct elemental_data *ed, struct block_list *bl, int64 tick);
struct skill_condition (*skill_get_requirements) (uint16 skill_id, uint16 skill_lv);
-
+
int (*read_skilldb) (void);
void (*reload_db) (void);
void (*reload_skilldb) (void);
-
+
int (*search_index) (int class_);
void (*summon_init) (struct elemental_data *ed);
int (*summon_end_timer) (int tid, int64 tick, int id, intptr_t data);
diff --git a/src/map/guild.c b/src/map/guild.c
index ac24edeab..d46da60a3 100644
--- a/src/map/guild.c
+++ b/src/map/guild.c
@@ -63,10 +63,10 @@ int guild_skill_get_max (int id) {
// Retrieve skill_lv learned by guild
int guild_checkskill(struct guild *g, int id) {
- int idx = id - GD_SKILLBASE;
- if (idx < 0 || idx >= MAX_GUILDSKILL)
- return 0;
- return g->skill[idx].lv;
+ int idx = id - GD_SKILLBASE;
+ if (idx < 0 || idx >= MAX_GUILDSKILL)
+ return 0;
+ return g->skill[idx].lv;
}
/*==========================================
@@ -236,17 +236,17 @@ void guild_makemember(struct guild_member *m,struct map_session_data *sd)
nullpo_retv(sd);
memset(m,0,sizeof(struct guild_member));
- m->account_id =sd->status.account_id;
- m->char_id =sd->status.char_id;
- m->hair =sd->status.hair;
- m->hair_color =sd->status.hair_color;
- m->gender =sd->status.sex;
- m->class_ =sd->status.class_;
- m->lv =sd->status.base_level;
-// m->exp =0;
-// m->exp_payper =0;
- m->online =1;
- m->position =MAX_GUILDPOSITION-1;
+ m->account_id = sd->status.account_id;
+ m->char_id = sd->status.char_id;
+ m->hair = sd->status.hair;
+ m->hair_color = sd->status.hair_color;
+ m->gender = sd->status.sex;
+ m->class_ = sd->status.class_;
+ m->lv = sd->status.base_level;
+ //m->exp = 0;
+ //m->exp_payper = 0;
+ m->online = 1;
+ m->position = MAX_GUILDPOSITION-1;
memcpy(m->name,sd->status.name,NAME_LENGTH);
return;
}
@@ -366,14 +366,14 @@ int guild_created(int account_id,int guild_id) {
if(sd==NULL)
return 0;
if(!guild_id) {
- clif->guild_created(sd, 2); // Creation failure (presence of the same name Guild)
+ clif->guild_created(sd, 2); // Creation failure (presence of the same name Guild)
return 0;
}
//struct guild *g;
sd->status.guild_id=guild_id;
clif->guild_created(sd,0);
if(battle_config.guild_emperium_check)
- pc->delitem(sd,pc->search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption
+ pc->delitem(sd,pc->search_inventory(sd,ITEMID_EMPERIUM),1,0,0,LOG_TYPE_CONSUME); //emperium consumption
return 0;
}
@@ -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);
@@ -468,15 +470,15 @@ int guild_recv_info(struct guild *sg) {
g->instance = NULL;
g->instances = 0;
idb_put(guild->db,sg->guild_id,g);
- if( hChSys.ally ) {
+ if (clif->hChSys->ally) {
struct hChSysCh *channel;
-
+
CREATE(channel, struct hChSysCh , 1);
- safestrncpy(channel->name, hChSys.ally_name, HCHSYS_NAME_LENGTH);
+ safestrncpy(channel->name, clif->hChSys->ally_name, HCHSYS_NAME_LENGTH);
channel->type = hChSys_ALLY;
- clif->chsys_create(channel,NULL,NULL,hChSys.ally_color);
- if( hChSys.ally_autojoin ) {
+ clif->chsys_create(channel, NULL, NULL, clif->hChSys->ally_color);
+ if (clif->hChSys->ally_autojoin) {
struct s_mapiterator* iter = mapit_getallusers();
struct guild *tg[MAX_GUILDALLIANCE];
@@ -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);
@@ -559,32 +567,32 @@ int guild_recv_info(struct guild *sg) {
bm++;
}
- for (i = 0; i < g->max_member; i++) { //Transmission of information at all members
+ for (i = 0; i < g->max_member; i++) { //Transmission of information at all members
sd = g->member[i].sd;
if( sd==NULL )
continue;
sd->guild = g;
- if (before.guild_lv != g->guild_lv || bm != m ||
- before.max_member != g->max_member) {
- clif->guild_basicinfo(sd); //Submit basic information
- clif->guild_emblem(sd, g); //Submit emblem
- }
+ if (before.guild_lv != g->guild_lv || bm != m
+ || before.max_member != g->max_member) {
+ clif->guild_basicinfo(sd); //Submit basic information
+ clif->guild_emblem(sd, g); //Submit emblem
+ }
- if (bm != m) { //Send members information
- clif->guild_memberlist(g->member[i].sd);
- }
+ if (bm != m) { //Send members information
+ clif->guild_memberlist(g->member[i].sd);
+ }
- if (before.skill_point != g->skill_point)
- clif->guild_skillinfo(sd); //Submit information skills
+ if (before.skill_point != g->skill_point)
+ clif->guild_skillinfo(sd); //Submit information skills
if (guild_new) { // Send information and affiliation if unsent
- clif->guild_belonginfo(sd, g);
- //clif->guild_notice(sd, g); Is already sent in clif_parse_LoadEndAck
- sd->guild_emblem_id = g->emblem_id;
- }
- }
+ clif->guild_belonginfo(sd, g);
+ //clif->guild_notice(sd, g); Is already sent in clif_parse_LoadEndAck
+ sd->guild_emblem_id = g->emblem_id;
+ }
+ }
- //Occurrence of an event
+ //Occurrence of an event
if (guild->infoevent_db->remove(guild->infoevent_db, DB->i2key(sg->guild_id), &data)) {
struct eventlist *ev = DB->data2ptr(&data), *ev2;
while(ev) {
@@ -602,8 +610,8 @@ int guild_recv_info(struct guild *sg) {
* Player sd send a guild invatation to player tsd to join his guild
*--------------------------------------------*/
int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) {
- struct guild *g;
- int i;
+ struct guild *g;
+ int i;
nullpo_ret(sd);
@@ -616,7 +624,7 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) {
return 0; //Invite permission.
if(!battle_config.invite_request_check) {
- if (tsd->party_invite > 0 || tsd->trade_partner || tsd->adopt_invite) { //checking if there no other invitation pending
+ if (tsd->party_invite > 0 || tsd->trade_partner || tsd->adopt_invite) { //checking if there no other invitation pending
clif->guild_inviteack(sd,0);
return 0;
}
@@ -627,8 +635,8 @@ int guild_invite(struct map_session_data *sd, struct map_session_data *tsd) {
return 0;
}
- if( tsd->status.guild_id > 0
- || tsd->guild_invite > 0
+ if( tsd->status.guild_id > 0
+ || tsd->guild_invite > 0
|| ( (map->agit_flag || map->agit2_flag)
&& map->list[tsd->bl.m].flag.gvg_castle
&& !battle_config.guild_castle_invite
@@ -722,7 +730,8 @@ void guild_member_joined(struct map_session_data *sd)
guild->request_info(sd->status.guild_id);
return;
}
- if (strcmp(sd->status.name,g->master) == 0) { // set the Guild Master flag
+ if (strcmp(sd->status.name,g->master) == 0) {
+ // set the Guild Master flag
sd->state.gmaster_flag = 1;
// prevent Guild Skills from being used directly after relog
if( battle_config.guild_skill_relog_delay )
@@ -736,7 +745,7 @@ void guild_member_joined(struct map_session_data *sd)
g->member[i].sd = sd;
sd->guild = g;
- if( hChSys.ally && hChSys.ally_autojoin ) {
+ if (clif->hChSys->ally && clif->hChSys->ally_autojoin) {
struct guild* sg = NULL;
struct hChSysCh *channel = g->channel;
@@ -815,8 +824,8 @@ int guild_leave(struct map_session_data* sd, int guild_id, int account_id, int c
return 0;
if( sd->status.account_id != account_id
- || sd->status.char_id != char_id
- || sd->status.guild_id != guild_id
+ || sd->status.char_id != char_id
+ || sd->status.guild_id != guild_id
// Can't leave inside castles
|| ((map->agit_flag || map->agit2_flag)
&& map->list[sd->bl.m].flag.gvg_castle
@@ -847,11 +856,11 @@ int guild_expulsion(struct map_session_data* sd, int guild_id, int account_id, i
return 0;
if( (ps=guild->getposition(g,sd))<0 || !(g->position[ps].mode&0x0010) )
- return 0; //Expulsion permission
+ return 0; //Expulsion permission
//Can't leave inside guild castles.
- if ((tsd = map->id2sd(account_id))
- && tsd->status.char_id == char_id
+ if ((tsd = map->id2sd(account_id))
+ && tsd->status.char_id == char_id
&& ((map->agit_flag || map->agit2_flag)
&& map->list[sd->bl.m].flag.gvg_castle
&& !battle_config.guild_castle_expulsion)
@@ -904,7 +913,7 @@ int guild_member_withdraw(int guild_id, int account_id, int char_id, int flag, c
if (sd->state.storage_flag == 2) //Close the guild storage.
gstorage->close(sd);
guild->send_dot_remove(sd);
- if( hChSys.ally ) {
+ if (clif->hChSys->ally) {
clif->chsys_quitg(sd);
}
sd->status.guild_id = 0;
@@ -928,7 +937,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) ) {
@@ -968,8 +977,8 @@ int guild_send_memberinfoshort(struct map_session_data *sd,int online)
return 0;
}
- if(sd->state.connect_new)
- { //Note that this works because it is invoked in parse_LoadEndAck before connect_new is cleared.
+ if (sd->state.connect_new) {
+ //Note that this works because it is invoked in parse_LoadEndAck before connect_new is cleared.
clif->guild_belonginfo(sd,g);
sd->guild_emblem_id = g->emblem_id;
}
@@ -1384,8 +1393,8 @@ void guild_guildaura_refresh(struct map_session_data *sd, uint16 skill_id, uint1
/*====================================================
* Count number of relations the guild has.
* Flag:
- * 0 = allied
- * 1 = enemy
+ * 0 = allied
+ * 1 = enemy
*---------------------------------------------------*/
int guild_get_alliance_count(struct guild *g,int flag)
{
@@ -1393,9 +1402,8 @@ int guild_get_alliance_count(struct guild *g,int flag)
nullpo_ret(g);
- for(i=c=0;i<MAX_GUILDALLIANCE;i++){
- if( g->alliance[i].guild_id>0 &&
- g->alliance[i].opposition==flag )
+ for(i=c=0;i<MAX_GUILDALLIANCE;i++) {
+ if(g->alliance[i].guild_id>0 && g->alliance[i].opposition==flag)
c++;
}
return c;
@@ -1413,8 +1421,8 @@ void guild_block_skill(struct map_session_data *sd, int time)
/*====================================================
* Check relation between guild_id1 and guild_id2.
* Flag:
- * 0 = allied
- * 1 = enemy
+ * 0 = allied
+ * 1 = enemy
* Returns true if yes.
*---------------------------------------------------*/
int guild_check_alliance(int guild_id1, int guild_id2, int flag)
@@ -1459,7 +1467,7 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
if(sd->status.guild_id == tsd->status.guild_id)
return 0;
- if( guild->get_alliance_count(g[0],0) >= battle_config.max_guild_alliance ) {
+ if( guild->get_alliance_count(g[0],0) >= battle_config.max_guild_alliance ) {
clif->guild_allianceack(sd,4);
return 0;
}
@@ -1473,9 +1481,8 @@ int guild_reqalliance(struct map_session_data *sd,struct map_session_data *tsd)
return 0;
}
- for (i = 0; i < MAX_GUILDALLIANCE; i++) { // check if already allied
- if( g[0]->alliance[i].guild_id==tsd->status.guild_id &&
- g[0]->alliance[i].opposition==0){
+ for (i = 0; i < MAX_GUILDALLIANCE; i++) { // check if already allied
+ if(g[0]->alliance[i].guild_id==tsd->status.guild_id && g[0]->alliance[i].opposition==0) {
clif->guild_allianceack(sd,0);
return 0;
}
@@ -1501,13 +1508,13 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
return 0;
}
- if (sd->guild_alliance != tsd->status.guild_id) // proposed guild_id alliance doesn't match tsd guildid
+ if (sd->guild_alliance != tsd->status.guild_id) // proposed guild_id alliance doesn't match tsd guildid
return 0;
- if (flag == 1) { // consent
+ if (flag == 1) { // consent
int i;
- struct guild *g, *tg; // Reconfirm the number of alliance
+ struct guild *g, *tg; // Reconfirm the number of alliance
g=sd->guild;
tg=tsd->guild;
@@ -1535,11 +1542,11 @@ int guild_reply_reqalliance(struct map_session_data *sd,int account_id,int flag)
tsd->status.account_id,sd->status.account_id,9 );
}
- // inform other servers
+ // inform other servers
intif->guild_alliance( sd->status.guild_id,tsd->status.guild_id,
sd->status.account_id,tsd->status.account_id,0 );
return 0;
- } else { // deny
+ } else { // deny
sd->guild_alliance=0;
sd->guild_alliance_account=0;
if(tsd!=NULL)
@@ -1582,7 +1589,7 @@ int guild_opposition(struct map_session_data *sd,struct map_session_data *tsd)
if(sd->status.guild_id == tsd->status.guild_id)
return 0;
- if( guild->get_alliance_count(g,1) >= battle_config.max_guild_alliance ) {
+ if( guild->get_alliance_count(g,1) >= battle_config.max_guild_alliance ) {
clif->guild_oppositionack(sd,1);
return 0;
}
@@ -1639,9 +1646,9 @@ int guild_allianceack(int guild_id1,int guild_id2,int account_id1,int account_id
return 0;
}
- if( g[0] && g[1] && hChSys.ally && ( flag & 1 ) == 0 ) {
+ if (g[0] && g[1] && clif->hChSys->ally && ( flag & 1 ) == 0) {
if( !(flag & 0x08) ) {
- if( hChSys.ally_autojoin )
+ if (clif->hChSys->ally_autojoin)
clif->chsys_gjoin(g[0],g[1]);
} else {
clif->chsys_gleave(g[0],g[1]);
@@ -1703,7 +1710,8 @@ int guild_broken_sub(DBKey key, DBData *data, va_list ap)
nullpo_ret(g);
- for(i=0;i<MAX_GUILDALLIANCE;i++){ // Destroy all relationships
+ for(i=0;i<MAX_GUILDALLIANCE;i++) {
+ // Destroy all relationships
if(g->alliance[i].guild_id==guild_id){
for(j=0;j<g->max_member;j++)
if( (sd=g->member[j].sd)!=NULL )
@@ -1749,7 +1757,8 @@ int guild_broken(int guild_id,int flag)
if(flag!=0 || g==NULL)
return 0;
- for(i=0;i<g->max_member;i++){ // Destroy all relationships
+ for(i=0;i<g->max_member;i++){
+ // Destroy all relationships
if((sd=g->member[i].sd)!=NULL){
if(sd->state.storage_flag == 2)
gstorage->pc_quit(sd,1);
@@ -1768,7 +1777,7 @@ int guild_broken(int guild_id,int flag)
guild->db->foreach(guild->db,guild->broken_sub,guild_id);
guild->castle_db->foreach(guild->castle_db,guild->castle_broken_sub,guild_id);
gstorage->delete(guild_id);
- if( hChSys.ally ) {
+ if (clif->hChSys->ally) {
if( g->channel != NULL ) {
clif->chsys_delete(g->channel);
}
@@ -1878,11 +1887,13 @@ int guild_break(struct map_session_data *sd,char *name) {
return 0;
if(!sd->state.gmaster_flag)
return 0;
- for(i=0;i<g->max_member;i++){
- if( g->member[i].account_id>0 && (
- g->member[i].account_id!=sd->status.account_id ||
- g->member[i].char_id!=sd->status.char_id ))
+ for (i = 0; i < g->max_member; i++) {
+ if (g->member[i].account_id > 0
+ && (g->member[i].account_id!=sd->status.account_id
+ || g->member[i].char_id!=sd->status.char_id
+ )) {
break;
+ }
}
if(i<g->max_member){
clif->guild_broken(sd,2);
@@ -2086,7 +2097,8 @@ int guild_castledataloadack(int len, struct guild_castle *gc)
* Start normal woe and triggers all npc OnAgitStart
*---------------------------------------------------*/
void guild_agit_start(void)
-{ // Run All NPC_Event[OnAgitStart]
+{
+ // Run All NPC_Event[OnAgitStart]
int c = npc->event_doall("OnAgitStart");
ShowStatus("NPC_Event:[OnAgitStart] Run (%d) Events by @AgitStart.\n",c);
}
@@ -2095,7 +2107,8 @@ void guild_agit_start(void)
* End normal woe and triggers all npc OnAgitEnd
*---------------------------------------------------*/
void guild_agit_end(void)
-{ // Run All NPC_Event[OnAgitEnd]
+{
+ // Run All NPC_Event[OnAgitEnd]
int c = npc->event_doall("OnAgitEnd");
ShowStatus("NPC_Event:[OnAgitEnd] Run (%d) Events by @AgitEnd.\n",c);
}
@@ -2104,7 +2117,8 @@ void guild_agit_end(void)
* Start woe2 and triggers all npc OnAgitStart2
*---------------------------------------------------*/
void guild_agit2_start(void)
-{ // Run All NPC_Event[OnAgitStart2]
+{
+ // Run All NPC_Event[OnAgitStart2]
int c = npc->event_doall("OnAgitStart2");
ShowStatus("NPC_Event:[OnAgitStart2] Run (%d) Events by @AgitStart2.\n",c);
}
@@ -2113,7 +2127,8 @@ void guild_agit2_start(void)
* End woe2 and triggers all npc OnAgitEnd2
*---------------------------------------------------*/
void guild_agit2_end(void)
-{ // Run All NPC_Event[OnAgitEnd2]
+{
+ // Run All NPC_Event[OnAgitEnd2]
int c = npc->event_doall("OnAgitEnd2");
ShowStatus("NPC_Event:[OnAgitEnd2] Run (%d) Events by @AgitEnd2.\n",c);
}
diff --git a/src/map/guild.h b/src/map/guild.h
index 126325eef..eb6de7070 100644
--- a/src/map/guild.h
+++ b/src/map/guild.h
@@ -13,8 +13,8 @@
/**
* Defines
**/
-#define GUILD_SEND_XY_INVERVAL 5000 // Interval of sending coordinates and HP
-#define GUILD_PAYEXP_INVERVAL 10000 //Interval (maximum survival time of the cache, in milliseconds)
+#define GUILD_SEND_XY_INVERVAL 5000 // Interval of sending coordinates and HP
+#define GUILD_PAYEXP_INVERVAL 10000 //Interval (maximum survival time of the cache, in milliseconds)
#define MAX_GUILD_SKILL_REQUIRE 5
/**
diff --git a/src/map/homunculus.c b/src/map/homunculus.c
index 0f76fcf5f..1d226749b 100644
--- a/src/map/homunculus.c
+++ b/src/map/homunculus.c
@@ -78,39 +78,39 @@ enum homun_type homunculus_class2type(int class_) {
}
void homunculus_addspiritball(struct homun_data *hd, int max) {
- nullpo_retv(hd);
+ nullpo_retv(hd);
- if (max > MAX_SKILL_LEVEL)
- max = MAX_SKILL_LEVEL;
- if (hd->homunculus.spiritball < 0)
- hd->homunculus.spiritball = 0;
+ if (max > MAX_SKILL_LEVEL)
+ max = MAX_SKILL_LEVEL;
+ if (hd->homunculus.spiritball < 0)
+ hd->homunculus.spiritball = 0;
- if (hd->homunculus.spiritball && hd->homunculus.spiritball >= max) {
- hd->homunculus.spiritball = max;
- }
- else
- hd->homunculus.spiritball++;
+ if (hd->homunculus.spiritball && hd->homunculus.spiritball >= max) {
+ hd->homunculus.spiritball = max;
+ }
+ else
+ hd->homunculus.spiritball++;
- clif->spiritball(&hd->bl);
+ clif->spiritball(&hd->bl);
}
void homunculus_delspiritball(struct homun_data *hd, int count, int type) {
- nullpo_retv(hd);
-
- if (hd->homunculus.spiritball <= 0) {
- hd->homunculus.spiritball = 0;
- return;
- }
- if (count <= 0)
- return;
- if (count > MAX_SKILL_LEVEL)
- count = MAX_SKILL_LEVEL;
- if (count > hd->homunculus.spiritball)
- count = hd->homunculus.spiritball;
-
- hd->homunculus.spiritball -= count;
- if (!type)
- clif->spiritball(&hd->bl);
+ nullpo_retv(hd);
+
+ if (hd->homunculus.spiritball <= 0) {
+ hd->homunculus.spiritball = 0;
+ return;
+ }
+ if (count <= 0)
+ return;
+ if (count > MAX_SKILL_LEVEL)
+ count = MAX_SKILL_LEVEL;
+ if (count > hd->homunculus.spiritball)
+ count = hd->homunculus.spiritball;
+
+ hd->homunculus.spiritball -= count;
+ if (!type)
+ clif->spiritball(&hd->bl);
}
void homunculus_damaged(struct homun_data *hd) {
@@ -313,7 +313,7 @@ bool homunculus_levelup(struct homun_data *hd) {
hom = &hd->homunculus;
hom->level++ ;
if (!(hom->level % 3))
- hom->skillpts++; //1 skillpoint each 3 base level
+ hom->skillpts++; //1 skillpoint each 3 base level
hom->exp -= hd->exp_next;
hd->exp_next = homun->exptable[hom->level - 1];
@@ -347,6 +347,8 @@ bool homunculus_levelup(struct homun_data *hd) {
hom->int_+= growth_int;
hom->luk += growth_luk;
+ APPLY_HOMUN_LEVEL_STATWEIGHT();
+
if ( battle_config.homunculus_show_growth ) {
char output[256] ;
sprintf(output,
@@ -500,7 +502,7 @@ int homunculus_gainexp(struct homun_data *hd,unsigned int exp) {
return 0;
}
- //levelup
+ //levelup
while( hd->homunculus.exp > hd->exp_next && homun->levelup(hd) );
if( hd->exp_next == 0 )
@@ -601,7 +603,7 @@ bool homunculus_feed(struct map_session_data *sd, struct homun_data *hd) {
emotion = E_HO;
}
- hd->homunculus.hunger += 10; //dunno increase value for each food
+ hd->homunculus.hunger += 10; //dunno increase value for each food
if(hd->homunculus.hunger > 100)
hd->homunculus.hunger = 100;
@@ -912,7 +914,7 @@ bool homunculus_ressurect(struct map_session_data* sd, unsigned char per, short
hd = sd->hd;
- if (hd->homunculus.vaporize != HOM_ST_ACTIVE)
+ if (hd->homunculus.vaporize != HOM_ST_ACTIVE)
return false; // vaporized homunculi need to be 'called'
if (!status->isdead(&hd->bl))
@@ -1126,7 +1128,7 @@ bool homunculus_read_db_sub(char* str[], int columns, int current) {
void homunculus_read_db(void) {
int i;
- const char *filename[]={"homunculus_db.txt","homunculus_db2.txt"};
+ const char *filename[]={DBPATH"homunculus_db.txt","homunculus_db2.txt"};
memset(homun->db,0,sizeof(homun->db));
for(i = 0; i<ARRAYLENGTH(filename); i++) {
@@ -1151,7 +1153,7 @@ bool homunculus_read_skill_db_sub(char* split[], int columns, int current) {
int minJobLevelPresent = 0;
if( columns == 15 )
- minJobLevelPresent = 1; // MinJobLvl has been added - FIXME: is this extra field even needed anymore?
+ minJobLevelPresent = 1; // MinJobLvl has been added - FIXME: is this extra field even needed anymore?
// check for bounds [celest]
classid = atoi(split[0]) - HM_CLASS_BASE;
diff --git a/src/map/homunculus.h b/src/map/homunculus.h
index 25ccabf48..5b1fd2031 100644
--- a/src/map/homunculus.h
+++ b/src/map/homunculus.h
@@ -14,6 +14,17 @@
#define homdb_checkid(id) ((id) >= HM_CLASS_BASE && (id) <= HM_CLASS_MAX)
#define homun_alive(x) ((x) && (x)->homunculus.vaporize == HOM_ST_ACTIVE && (x)->battle_status.hp > 0)
+#ifdef RENEWAL
+#define HOMUN_LEVEL_STATWEIGHT_VALUE 0
+#define APPLY_HOMUN_LEVEL_STATWEIGHT()( \
+ hom->str_value = hom->agi_value = \
+ hom->vit_value = hom->int_value = \
+ hom->dex_value = hom->luk_value = hom->level / 10 - HOMUN_LEVEL_STATWEIGHT_VALUE \
+ )
+#else
+#define APPLY_HOMUN_LEVEL_STATWEIGHT()
+#endif
+
struct h_stats {
unsigned int HP, SP;
unsigned short str, agi, vit, int_, dex, luk;
@@ -65,7 +76,7 @@ struct homun_data {
int hungry_timer; //[orn]
unsigned int exp_next;
char blockskill[MAX_SKILL]; // [orn]
-
+
int64 masterteleport_timer;
};
diff --git a/src/map/instance.c b/src/map/instance.c
index 5789d7dd6..4140973b1 100644
--- a/src/map/instance.c
+++ b/src/map/instance.c
@@ -273,7 +273,7 @@ int instance_add_map(const char *name, int instance_id, bool usebasename, const
* type : result (0 = map id | 1 = instance id)
*--------------------------------------*/
int instance_map2imap(int16 m, int instance_id) {
- int i;
+ int i;
if( !instance->valid(instance_id) ) {
return -1;
@@ -282,12 +282,12 @@ int instance_map2imap(int16 m, int instance_id) {
for( i = 0; i < instance->list[instance_id].num_map; i++ ) {
if( instance->list[instance_id].map[i] && map->list[instance->list[instance_id].map[i]].instance_src_map == m )
return instance->list[instance_id].map[i];
- }
- return -1;
+ }
+ return -1;
}
int instance_mapname2imap(const char *map_name, int instance_id) {
- int i;
+ int i;
if( !instance->valid(instance_id) ) {
return -1;
@@ -296,8 +296,8 @@ int instance_mapname2imap(const char *map_name, int instance_id) {
for( i = 0; i < instance->list[instance_id].num_map; i++ ) {
if( instance->list[instance_id].map[i] && !strcmpi(map->list[map->list[instance->list[instance_id].map[i]].instance_src_map].name,map_name) )
return instance->list[instance_id].map[i];
- }
- return -1;
+ }
+ return -1;
}
diff --git a/src/map/instance.h b/src/map/instance.h
index 2ee77d3e3..4848c9c59 100644
--- a/src/map/instance.h
+++ b/src/map/instance.h
@@ -41,17 +41,17 @@ struct instance_data {
unsigned short users;
struct reg_db regs; ///< Instance variables for scripts
-
+
int progress_timer;
unsigned int progress_timeout;
int idle_timer;
unsigned int idle_timeout, idle_timeoutval;
-
+
unsigned int original_progress_timeout;
-
+
struct point respawn; ///< reload spawn
-
+
/** HPM Custom Struct */
struct HPluginData **hdata;
unsigned int hdatac;
diff --git a/src/map/intif.c b/src/map/intif.c
index be82a7583..73fb648ae 100644
--- a/src/map/intif.c
+++ b/src/map/intif.c
@@ -210,8 +210,8 @@ int intif_wis_message(struct map_session_data *sd, char *nick, char *mes, size_t
if (intif->CheckForCharServer())
return 0;
- if (chrif->other_mapserver_count < 1)
- { //Character not found.
+ if (chrif->other_mapserver_count < 1) {
+ //Character not found.
clif->wis_end(sd->fd, 1);
return 0;
}
@@ -924,8 +924,8 @@ void intif_parse_WisMessage(int fd) {
strcmp(sd->ignore[i].name, wisp_source) != 0
; i++);
- if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0')
- { //Ignored
+ if (i < MAX_IGNORE_LIST && sd->ignore[i].name[0] != '\0') {
+ //Ignored
intif_wis_replay(id, 2);
return;
}
@@ -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;
@@ -1113,7 +1113,7 @@ void intif_parse_LoadGuildStorage(int fd)
}
if (RFIFOW(fd,2)-13 != sizeof(struct guild_storage)) {
ShowError("intif_parse_LoadGuildStorage: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd,2)-13, sizeof(struct guild_storage));
- gstor->storage_status = 0;
+ gstor->storage_status = 0;
return;
}
@@ -1567,10 +1567,8 @@ void intif_parse_MailInboxReceived(int fd) {
sd = map->charid2sd(RFIFOL(fd,4));
- if (sd == NULL) {
- ShowError("intif_parse_MailInboxReceived: char not found %d\n",RFIFOL(fd,4));
+ if (sd == NULL) /** user is not online anymore and its ok (quest log also does this) **/
return;
- }
if (RFIFOW(fd,2) - 9 != sizeof(struct mail_data)) {
ShowError("intif_parse_MailInboxReceived: data size mismatch %d != %"PRIuS"\n", RFIFOW(fd,2) - 9, sizeof(struct mail_data));
@@ -2138,7 +2136,7 @@ void intif_request_accinfo( int u_fd, int aid, int group_lv, char* query ) {
WFIFOL(inter_fd,2) = u_fd;
WFIFOL(inter_fd,6) = aid;
WFIFOL(inter_fd,10) = group_lv;
- safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH);
+ safestrncpy((char *)WFIFOP(inter_fd,14), query, NAME_LENGTH);
WFIFOSET(inter_fd,2 + 4 + 4 + 4 + NAME_LENGTH);
@@ -2167,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;
@@ -2185,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
@@ -2198,12 +2196,13 @@ int intif_parse(int fd)
{
int packet_len, cmd;
cmd = RFIFOW(fd,0);
- // Verify ID of the packet
- if(cmd<0x3800 || cmd>=0x3800+(sizeof(intif->packet_len_table)/sizeof(intif->packet_len_table[0])) ||
- intif->packet_len_table[cmd-0x3800]==0){
- return 0;
+ // Verify ID of the packet
+ if (cmd < 0x3800 || cmd >= 0x3800+(sizeof(intif->packet_len_table)/sizeof(intif->packet_len_table[0]))
+ || intif->packet_len_table[cmd-0x3800] == 0
+ ) {
+ return 0;
}
- // Check the length of the packet
+ // Check the length of the packet
packet_len = intif->packet_len_table[cmd-0x3800];
if(packet_len==-1){
if(RFIFOREST(fd)<4)
@@ -2213,7 +2212,7 @@ int intif_parse(int fd)
if((int)RFIFOREST(fd)<packet_len){
return 2;
}
- // Processing branch
+ // Processing branch
switch(cmd){
case 0x3800:
if (RFIFOL(fd,4) == 0xFF000000) //Normal announce.
@@ -2221,57 +2220,57 @@ int intif_parse(int fd)
else //Color announce.
clif->broadcast2(NULL, (char *) RFIFOP(fd,16), packet_len-16, RFIFOL(fd,4), RFIFOW(fd,8), RFIFOW(fd,10), RFIFOW(fd,12), RFIFOW(fd,14), ALL_CLIENT);
break;
- case 0x3801: intif->pWisMessage(fd); break;
- case 0x3802: intif->pWisEnd(fd); break;
- case 0x3803: intif->pWisToGM(fd); break;
- case 0x3804: intif->pRegisters(fd); break;
- case 0x3806: intif->pChangeNameOk(fd); break;
- case 0x3807: intif->pMessageToFD(fd); break;
- case 0x3818: intif->pLoadGuildStorage(fd); break;
- case 0x3819: intif->pSaveGuildStorage(fd); break;
- case 0x3820: intif->pPartyCreated(fd); break;
- case 0x3821: intif->pPartyInfo(fd); break;
- case 0x3822: intif->pPartyMemberAdded(fd); break;
- case 0x3823: intif->pPartyOptionChanged(fd); break;
- case 0x3824: intif->pPartyMemberWithdraw(fd); break;
- case 0x3825: intif->pPartyMove(fd); break;
- case 0x3826: intif->pPartyBroken(fd); break;
- case 0x3827: intif->pPartyMessage(fd); break;
- case 0x3830: intif->pGuildCreated(fd); break;
- case 0x3831: intif->pGuildInfo(fd); break;
- case 0x3832: intif->pGuildMemberAdded(fd); break;
- case 0x3834: intif->pGuildMemberWithdraw(fd); break;
- case 0x3835: intif->pGuildMemberInfoShort(fd); break;
- case 0x3836: intif->pGuildBroken(fd); break;
- case 0x3837: intif->pGuildMessage(fd); break;
- case 0x3839: intif->pGuildBasicInfoChanged(fd); break;
- case 0x383a: intif->pGuildMemberInfoChanged(fd); break;
- case 0x383b: intif->pGuildPosition(fd); break;
- case 0x383c: intif->pGuildSkillUp(fd); break;
- case 0x383d: intif->pGuildAlliance(fd); break;
- case 0x383e: intif->pGuildNotice(fd); break;
- case 0x383f: intif->pGuildEmblem(fd); break;
- case 0x3840: intif->pGuildCastleDataLoad(fd); break;
- case 0x3843: intif->pGuildMasterChanged(fd); break;
+ case 0x3801: intif->pWisMessage(fd); break;
+ case 0x3802: intif->pWisEnd(fd); break;
+ case 0x3803: intif->pWisToGM(fd); break;
+ case 0x3804: intif->pRegisters(fd); break;
+ case 0x3806: intif->pChangeNameOk(fd); break;
+ case 0x3807: intif->pMessageToFD(fd); break;
+ case 0x3818: intif->pLoadGuildStorage(fd); break;
+ case 0x3819: intif->pSaveGuildStorage(fd); break;
+ case 0x3820: intif->pPartyCreated(fd); break;
+ case 0x3821: intif->pPartyInfo(fd); break;
+ case 0x3822: intif->pPartyMemberAdded(fd); break;
+ case 0x3823: intif->pPartyOptionChanged(fd); break;
+ case 0x3824: intif->pPartyMemberWithdraw(fd); break;
+ case 0x3825: intif->pPartyMove(fd); break;
+ case 0x3826: intif->pPartyBroken(fd); break;
+ case 0x3827: intif->pPartyMessage(fd); break;
+ case 0x3830: intif->pGuildCreated(fd); break;
+ case 0x3831: intif->pGuildInfo(fd); break;
+ case 0x3832: intif->pGuildMemberAdded(fd); break;
+ case 0x3834: intif->pGuildMemberWithdraw(fd); break;
+ case 0x3835: intif->pGuildMemberInfoShort(fd); break;
+ case 0x3836: intif->pGuildBroken(fd); break;
+ case 0x3837: intif->pGuildMessage(fd); break;
+ case 0x3839: intif->pGuildBasicInfoChanged(fd); break;
+ case 0x383a: intif->pGuildMemberInfoChanged(fd); break;
+ case 0x383b: intif->pGuildPosition(fd); break;
+ case 0x383c: intif->pGuildSkillUp(fd); break;
+ case 0x383d: intif->pGuildAlliance(fd); break;
+ case 0x383e: intif->pGuildNotice(fd); break;
+ case 0x383f: intif->pGuildEmblem(fd); break;
+ case 0x3840: intif->pGuildCastleDataLoad(fd); break;
+ case 0x3843: intif->pGuildMasterChanged(fd); break;
//Quest system
- case 0x3860: intif->pQuestLog(fd); break;
- case 0x3861: intif->pQuestSave(fd); break;
+ case 0x3860: intif->pQuestLog(fd); break;
+ case 0x3861: intif->pQuestSave(fd); break;
// Mail System
- case 0x3848: intif->pMailInboxReceived(fd); break;
- case 0x3849: intif->pMailNew(fd); break;
- case 0x384a: intif->pMailGetAttach(fd); break;
- case 0x384b: intif->pMailDelete(fd); break;
- case 0x384c: intif->pMailReturn(fd); break;
- case 0x384d: intif->pMailSend(fd); break;
+ case 0x3848: intif->pMailInboxReceived(fd); break;
+ case 0x3849: intif->pMailNew(fd); break;
+ case 0x384a: intif->pMailGetAttach(fd); break;
+ case 0x384b: intif->pMailDelete(fd); break;
+ case 0x384c: intif->pMailReturn(fd); break;
+ case 0x384d: intif->pMailSend(fd); break;
// Auction System
- case 0x3850: intif->pAuctionResults(fd); break;
- case 0x3851: intif->pAuctionRegister(fd); break;
- case 0x3852: intif->pAuctionCancel(fd); break;
- case 0x3853: intif->pAuctionClose(fd); break;
- case 0x3854: intif->pAuctionMessage(fd); break;
- case 0x3855: intif->pAuctionBid(fd); break;
+ case 0x3850: intif->pAuctionResults(fd); break;
+ case 0x3851: intif->pAuctionRegister(fd); break;
+ case 0x3852: intif->pAuctionCancel(fd); break;
+ case 0x3853: intif->pAuctionClose(fd); break;
+ case 0x3854: intif->pAuctionMessage(fd); break;
+ case 0x3855: intif->pAuctionBid(fd); break;
//Bound items
case 0x3856:
#ifdef GP_BOUND_ITEMS
@@ -2281,27 +2280,27 @@ int intif_parse(int fd)
#endif
break;
// Mercenary System
- case 0x3870: intif->pMercenaryReceived(fd); break;
- case 0x3871: intif->pMercenaryDeleted(fd); break;
- case 0x3872: intif->pMercenarySaved(fd); break;
+ case 0x3870: intif->pMercenaryReceived(fd); break;
+ case 0x3871: intif->pMercenaryDeleted(fd); break;
+ case 0x3872: intif->pMercenarySaved(fd); break;
// Elemental System
- case 0x387c: intif->pElementalReceived(fd); break;
- case 0x387d: intif->pElementalDeleted(fd); break;
- case 0x387e: intif->pElementalSaved(fd); break;
+ case 0x387c: intif->pElementalReceived(fd); break;
+ case 0x387d: intif->pElementalDeleted(fd); break;
+ case 0x387e: intif->pElementalSaved(fd); break;
- case 0x3880: intif->pCreatePet(fd); break;
- case 0x3881: intif->pRecvPetData(fd); break;
- case 0x3882: intif->pSavePetOk(fd); break;
- case 0x3883: intif->pDeletePetOk(fd); break;
- case 0x3890: intif->pCreateHomunculus(fd); break;
- case 0x3891: intif->pRecvHomunculusData(fd); break;
- case 0x3892: intif->pSaveHomunculusOk(fd); break;
- case 0x3893: intif->pDeleteHomunculusOk(fd); break;
+ case 0x3880: intif->pCreatePet(fd); break;
+ case 0x3881: intif->pRecvPetData(fd); break;
+ case 0x3882: intif->pSavePetOk(fd); break;
+ case 0x3883: intif->pDeletePetOk(fd); break;
+ case 0x3890: intif->pCreateHomunculus(fd); break;
+ case 0x3891: intif->pRecvHomunculusData(fd); break;
+ case 0x3892: intif->pSaveHomunculusOk(fd); break;
+ case 0x3893: intif->pDeleteHomunculusOk(fd); break;
default:
ShowError("intif_parse : unknown packet %d %x\n",fd,RFIFOW(fd,0));
return 0;
}
- // Skip packet
+ // Skip packet
RFIFOSKIP(fd,packet_len);
return 1;
}
diff --git a/src/map/irc-bot.c b/src/map/irc-bot.c
index 6f016697f..8b4991c20 100644
--- a/src/map/irc-bot.c
+++ b/src/map/irc-bot.c
@@ -41,7 +41,7 @@ int irc_connect_timer(int tid, int64 tick, int id, intptr_t data) {
ircbot->last_try = timer->gettick();
- if( ( ircbot->fd = make_connection(ircbot->ip,hChSys.irc_server_port,&opt) ) > 0 ){
+ if ((ircbot->fd = make_connection(ircbot->ip, clif->hChSys->irc_server_port, &opt)) > 0) {
session[ircbot->fd]->func_parse = ircbot->parse;
session[ircbot->fd]->flag.server = 1;
timer->add(timer->gettick() + 3000, ircbot->identify_timer, 0, 0);
@@ -60,7 +60,7 @@ int irc_identify_timer(int tid, int64 tick, int id, intptr_t data) {
sprintf(send_string, "USER HerculesWS%d 8 * : Hercules IRC Bridge",rand()%777);
ircbot->send(send_string);
- sprintf(send_string, "NICK %s", hChSys.irc_nick);
+ sprintf(send_string, "NICK %s", clif->hChSys->irc_nick);
ircbot->send(send_string);
timer->add(timer->gettick() + 3000, ircbot->join_timer, 0, 0);
@@ -76,15 +76,15 @@ int irc_join_timer(int tid, int64 tick, int id, intptr_t data) {
if( !ircbot->isOn )
return 0;
- if( hChSys.irc_nick_pw[0] != '\0' ) {
- sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", hChSys.irc_nick_pw);
+ if (clif->hChSys->irc_nick_pw[0] != '\0') {
+ sprintf(send_string, "PRIVMSG NICKSERV : IDENTIFY %s", clif->hChSys->irc_nick_pw);
ircbot->send(send_string);
- if( hChSys.irc_use_ghost ) {
- sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", hChSys.irc_nick, hChSys.irc_nick_pw);
+ if (clif->hChSys->irc_use_ghost) {
+ sprintf(send_string, "PRIVMSG NICKSERV : GHOST %s %s", clif->hChSys->irc_nick, clif->hChSys->irc_nick_pw);
}
}
- sprintf(send_string, "JOIN %s", hChSys.irc_channel);
+ sprintf(send_string, "JOIN %s", clif->hChSys->irc_channel);
ircbot->send(send_string);
ircbot->isIn = true;
@@ -120,9 +120,9 @@ int irc_parse(int fd) {
ircbot->isOn = false;
ircbot->isIn = false;
ircbot->fails = 0;
- ircbot->ip = host2ip(hChSys.irc_server);
+ ircbot->ip = host2ip(clif->hChSys->irc_server);
timer->add(timer->gettick() + 120000, ircbot->connect_timer, 0, 0);
- return 0;
+ return 0;
}
if( !RFIFOREST(fd) )
@@ -289,10 +289,10 @@ void irc_privmsg(int fd, char *cmd, char *source, char *target, char *msg) {
irc_privmsg_ctcp(fd, command, source, target, message);
#ifdef IRCBOT_DEBUG
- } else if( strcmpi(target,hChSys.irc_nick) == 0 ) {
+ } else if (strcmpi(target, clif->hChSys->irc_nick) == 0) {
ShowDebug("irc_privmsg: Received message from %s: '%s'\n", source ? source : "(null)", msg);
#endif // IRCBOT_DEBUG
- } else if( msg && strcmpi(target,hChSys.irc_channel) == 0 ) {
+ } else if (msg && strcmpi(target, clif->hChSys->irc_channel) == 0) {
char source_nick[IRC_NICK_LENGTH], source_ident[IRC_IDENT_LENGTH], source_host[IRC_HOST_LENGTH];
source_nick[0] = source_ident[0] = source_host[0] = '\0';
@@ -382,7 +382,7 @@ void irc_usernick(int fd, char *cmd, char *source, char *target, char *msg) {
void irc_relay(char *name, const char *msg) {
if( !ircbot->isIn )
return;
- sprintf(send_string,"PRIVMSG %s :[ %s ] : %s",hChSys.irc_channel,name,msg);
+ sprintf(send_string,"PRIVMSG %s :[ %s ] : %s", clif->hChSys->irc_channel, name, msg);
ircbot->send(send_string);
}
@@ -405,12 +405,12 @@ void irc_bot_init(bool minimal) {
if (minimal)
return;
- if( !hChSys.irc )
+ if (!clif->hChSys->irc)
return;
- if (!(ircbot->ip = host2ip(hChSys.irc_server))) {
- ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", hChSys.irc_server);
- hChSys.irc = false;
+ if (!(ircbot->ip = host2ip(clif->hChSys->irc_server))) {
+ ShowError("Unable to resolve '%s' (irc server), disabling irc channel...\n", clif->hChSys->irc_server);
+ clif->hChSys->irc = false;
return;
}
@@ -443,7 +443,7 @@ void irc_bot_init(bool minimal) {
void irc_bot_final(void) {
int i;
- if( !hChSys.irc )
+ if (!clif->hChSys->irc)
return;
if( ircbot->isOn ) {
ircbot->send("QUIT :Hercules is shutting down");
diff --git a/src/map/itemdb.c b/src/map/itemdb.c
index 0d3146191..19cc02d21 100644
--- a/src/map/itemdb.c
+++ b/src/map/itemdb.c
@@ -16,6 +16,7 @@
#include "mob.h" // MAX_MOB_DB
#include "pc.h" // W_MUSICAL, W_WHIP
#include "script.h" // item script processing
+#include "../common/HPM.h"
#include "../common/conf.h"
#include "../common/malloc.h"
#include "../common/nullpo.h"
@@ -320,8 +321,8 @@ void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
int i;
bclass[0]= bclass[1]= bclass[2]= 0;
//Base classes
- if (jobmask & 1<<JOB_NOVICE)
- { //Both Novice/Super-Novice are counted with the same ID
+ if (jobmask & 1<<JOB_NOVICE) {
+ //Both Novice/Super-Novice are counted with the same ID
bclass[0] |= 1<<MAPID_NOVICE;
bclass[1] |= 1<<MAPID_NOVICE;
}
@@ -354,9 +355,10 @@ void itemdb_jobid2mapid(unsigned int *bclass, unsigned int jobmask)
bclass[2] |= 1<<MAPID_MERCHANT;
if (jobmask & 1<<JOB_BARD)
bclass[2] |= 1<<MAPID_ARCHER;
-// Bard/Dancer share the same slot now.
-// if (jobmask & 1<<JOB_DANCER)
-// bclass[2] |= 1<<MAPID_ARCHER;
+#if 0 // Bard/Dancer share the same slot now.
+ if (jobmask & 1<<JOB_DANCER)
+ bclass[2] |= 1<<MAPID_ARCHER;
+#endif // 0
if (jobmask & 1<<JOB_ROGUE)
bclass[2] |= 1<<MAPID_THIEF;
//Special classes that don't fit above.
@@ -487,16 +489,16 @@ int itemdb_isequip2(struct item_data *data) {
*------------------------------------------*/
int itemdb_isstackable(int nameid)
{
- int type=itemdb_type(nameid);
- switch(type) {
- case IT_WEAPON:
- case IT_ARMOR:
- case IT_PETEGG:
- case IT_PETARMOR:
- return 0;
- default:
- return 1;
- }
+ int type=itemdb_type(nameid);
+ switch(type) {
+ case IT_WEAPON:
+ case IT_ARMOR:
+ case IT_PETEGG:
+ case IT_PETARMOR:
+ return 0;
+ default:
+ return 1;
+ }
}
/*==========================================
@@ -504,16 +506,16 @@ int itemdb_isstackable(int nameid)
*------------------------------------------*/
int itemdb_isstackable2(struct item_data *data)
{
- nullpo_ret(data);
- switch(data->type) {
- case IT_WEAPON:
- case IT_ARMOR:
- case IT_PETEGG:
- case IT_PETARMOR:
- return 0;
- default:
- return 1;
- }
+ nullpo_ret(data);
+ switch(data->type) {
+ case IT_WEAPON:
+ case IT_ARMOR:
+ case IT_PETEGG:
+ case IT_PETARMOR:
+ return 0;
+ default:
+ return 1;
+ }
}
@@ -576,7 +578,7 @@ int itemdb_isrestricted(struct item* item, int gmlv, int gmlv2, int (*func)(stru
}
/*==========================================
- * Specifies if item-type should drop unidentified.
+ * Specifies if item-type should drop unidentified.
*------------------------------------------*/
int itemdb_isidentified(int nameid) {
int type=itemdb_type(nameid);
@@ -1500,6 +1502,11 @@ int itemdb_validate_entry(struct item_data *entry, int n, const char *source) {
return item->nameid;
}
+void itemdb_readdb_additional_fields(int itemid, config_setting_t *it, int n, const char *source)
+{
+ // do nothing. plugins can do own work
+}
+
/**
* Processes one itemdb entry from the sql backend, loading and inserting it
* into the item database.
@@ -1675,7 +1682,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
* OnUnequipScript: <" OnUnequip Script ">
* Inherit: inherit or override
*/
- if( !libconfig->setting_lookup_int(it, "Id", &i32) ) {
+ if( !itemdb->lookup_const(it, "Id", &i32) ) {
ShowWarning("itemdb_readdb_libconfig_sub: Invalid or missing id in \"%s\", entry #%d, skipping.\n", source, n);
return 0;
}
@@ -1710,57 +1717,57 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
safestrncpy(id.jname, str, sizeof(id.jname));
}
- if( libconfig->setting_lookup_int(it, "Type", &i32) )
+ if( itemdb->lookup_const(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) )
+ if( itemdb->lookup_const(it, "Buy", &i32) )
id.value_buy = i32;
else if( !inherit )
id.value_buy = -1;
- if( libconfig->setting_lookup_int(it, "Sell", &i32) )
+ if( itemdb->lookup_const(it, "Sell", &i32) )
id.value_sell = i32;
else if( !inherit )
id.value_sell = -1;
- if( libconfig->setting_lookup_int(it, "Weight", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Weight", &i32) && i32 >= 0 )
id.weight = i32;
- if( libconfig->setting_lookup_int(it, "Atk", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Atk", &i32) && i32 >= 0 )
id.atk = i32;
- if( libconfig->setting_lookup_int(it, "Matk", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Matk", &i32) && i32 >= 0 )
id.matk = i32;
- if( libconfig->setting_lookup_int(it, "Def", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Def", &i32) && i32 >= 0 )
id.def = i32;
- if( libconfig->setting_lookup_int(it, "Range", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Range", &i32) && i32 >= 0 )
id.range = i32;
- if( libconfig->setting_lookup_int(it, "Slots", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Slots", &i32) && i32 >= 0 )
id.slot = i32;
- if( libconfig->setting_lookup_int(it, "Job", &i32) ) // This is an unsigned value, do not check for >= 0
+ if( itemdb->lookup_const(it, "Job", &i32) ) // This is an unsigned value, do not check for >= 0
itemdb->jobid2mapid(id.class_base, (unsigned int)i32);
else if( !inherit )
itemdb->jobid2mapid(id.class_base, UINT_MAX);
- if( libconfig->setting_lookup_int(it, "Upper", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Upper", &i32) && i32 >= 0 )
id.class_upper = (unsigned int)i32;
else if( !inherit )
id.class_upper = ITEMUPPER_ALL;
- if( libconfig->setting_lookup_int(it, "Gender", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Gender", &i32) && i32 >= 0 )
id.sex = i32;
else if( !inherit )
id.sex = 2;
- if( libconfig->setting_lookup_int(it, "Loc", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "Loc", &i32) && i32 >= 0 )
id.equip = i32;
- if( libconfig->setting_lookup_int(it, "WeaponLv", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "WeaponLv", &i32) && i32 >= 0 )
id.wlv = i32;
if( (t = libconfig->setting_get_member(it, "EquipLv")) ) {
@@ -1777,7 +1784,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
if( (t = libconfig->setting_get_member(it, "Refine")) )
id.flag.no_refine = libconfig->setting_get_bool(t) ? 0 : 1;
- if( libconfig->setting_lookup_int(it, "View", &i32) && i32 >= 0 )
+ if( itemdb->lookup_const(it, "View", &i32) && i32 >= 0 )
id.look = i32;
if( (t = libconfig->setting_get_member(it, "BindOnEquip")) )
@@ -1786,9 +1793,12 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
if ( (t = libconfig->setting_get_member(it, "BuyingStore")) )
id.flag.buyingstore = libconfig->setting_get_bool(t) ? 1 : 0;
- if (libconfig->setting_lookup_int(it, "Delay", &i32) && i32 >= 0)
+ if ((t = libconfig->setting_get_member(it, "KeepAfterUse")))
+ id.flag.keepafteruse = libconfig->setting_get_bool(t) ? 1 : 0;
+
+ if (itemdb->lookup_const(it, "Delay", &i32) && i32 >= 0)
id.delay = i32;
-
+
if ( (t = libconfig->setting_get_member(it, "Trade")) ) {
if (config_setting_is_group(t)) {
config_setting_t *tt = NULL;
@@ -1888,7 +1898,7 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
}
}
- if (libconfig->setting_lookup_int(it, "Sprite", &i32) && i32 >= 0) {
+ if (itemdb->lookup_const(it, "Sprite", &i32) && i32 >= 0) {
id.flag.available = 1;
id.view_id = i32;
}
@@ -1905,6 +1915,24 @@ int itemdb_readdb_libconfig_sub(config_setting_t *it, int n, const char *source)
return itemdb->validate_entry(&id, n, source);
}
+bool itemdb_lookup_const(const config_setting_t *it, const char *name, int *value)
+{
+ if (libconfig->setting_lookup_int(it, name, value))
+ {
+ return true;
+ }
+ else
+ {
+ const char *str = NULL;
+ if (libconfig->setting_lookup_string(it, name, &str))
+ {
+ if (*str && script->get_constant(str, value))
+ return true;
+ }
+ }
+ return false;
+}
+
/**
* Reads from a libconfig-formatted itemdb file and inserts the found entries into the
* item database, overwriting duplicate ones (i.e. item_db2 overriding item_db.)
@@ -1932,6 +1960,7 @@ int itemdb_readdb_libconfig(const char *filename) {
if( !nameid )
continue;
+ itemdb->readdb_additional_fields(nameid, it, i - 1, filename);
count++;
if( duplicate[nameid] ) {
@@ -2050,6 +2079,14 @@ struct item_combo * itemdb_id2combo( unsigned short id ) {
return itemdb->combos[id];
}
+/**
+ * check is item have usable type
+ **/
+bool itemdb_is_item_usable(struct item_data *item)
+{
+ return item->type == IT_HEALING || item->type == IT_USABLE || item->type == IT_CASH;
+}
+
/*==========================================
* Initialize / Finalize
*------------------------------------------*/
@@ -2057,6 +2094,7 @@ struct item_combo * itemdb_id2combo( unsigned short id ) {
/// Destroys the item_data.
void destroy_item_data(struct item_data* self, int free_self)
{
+ int v;
if( self == NULL )
return;
// free scripts
@@ -2068,6 +2106,14 @@ void destroy_item_data(struct item_data* self, int free_self)
script->free_code(self->unequip_script);
if( self->combos )
aFree(self->combos);
+ for (v = 0; v < self->hdatac; v++ ) {
+ if (self->hdata[v]->flag.free ) {
+ aFree(self->hdata[v]->data);
+ }
+ aFree(self->hdata[v]);
+ }
+ if (self->hdata)
+ aFree(self->hdata);
#if defined(DEBUG)
// trash item
memset(self, 0xDD, sizeof(struct item_data));
@@ -2248,6 +2294,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;
@@ -2319,6 +2369,7 @@ void itemdb_defaults(void) {
itemdb->read_combos = itemdb_read_combos;
itemdb->gendercheck = itemdb_gendercheck;
itemdb->validate_entry = itemdb_validate_entry;
+ itemdb->readdb_additional_fields = itemdb_readdb_additional_fields;
itemdb->readdb_sql_sub = itemdb_readdb_sql_sub;
itemdb->readdb_libconfig_sub = itemdb_readdb_libconfig_sub;
itemdb->readdb_libconfig = itemdb_readdb_libconfig;
@@ -2329,4 +2380,6 @@ void itemdb_defaults(void) {
itemdb->final_sub = itemdb_final_sub;
itemdb->clear = itemdb_clear;
itemdb->id2combo = itemdb_id2combo;
+ itemdb->is_item_usable = itemdb_is_item_usable;
+ itemdb->lookup_const = itemdb_lookup_const;
}
diff --git a/src/map/itemdb.h b/src/map/itemdb.h
index 198d7a542..902e6e5e9 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,
@@ -372,7 +374,7 @@ enum ItemNouseRestrictions {
struct item_data {
uint16 nameid;
char name[ITEM_NAME_LENGTH],jname[ITEM_NAME_LENGTH];
-
+
//Do not add stuff between value_buy and view_id (see how getiteminfo works)
int value_buy;
int value_sell;
@@ -394,24 +396,25 @@ struct item_data {
int delay;
//Lupus: I rearranged order of these fields due to compatibility with ITEMINFO script command
-// some script commands should be revised as well...
- unsigned int class_base[3]; //Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2)
- unsigned class_upper : 6; //Specifies if the upper-type can equip it (bitfield, 0x01: normal, 0x02: upper, 0x04: baby normal, 0x08: third normal, 0x10: third upper, 0x20: third baby)
+// some script commands should be revised as well...
+ unsigned int class_base[3]; ///< Specifies if the base can wear this item (split in 3 indexes per type: 1-1, 2-1, 2-2)
+ unsigned class_upper : 6; ///< Specifies if the upper-type can equip it (bitfield, 0x01: normal, 0x02: upper, 0x04: baby normal, 0x08: third normal, 0x10: third upper, 0x20: third baby)
struct {
unsigned short chance;
int id;
- } mob[MAX_SEARCH]; //Holds the mobs that have the highest drop rate for this item. [Skotlex]
- struct script_code *script; //Default script for everything.
- struct script_code *equip_script; //Script executed once when equipping.
- struct script_code *unequip_script;//Script executed once when unequipping.
+ } mob[MAX_SEARCH]; ///< Holds the mobs that have the highest drop rate for this item. [Skotlex]
+ struct script_code *script; ///< Default script for everything.
+ struct script_code *equip_script; ///< Script executed once when equipping.
+ struct script_code *unequip_script; ///< Script executed once when unequipping.
struct {
unsigned available : 1;
- unsigned no_refine : 1; // [celest]
- unsigned delay_consume : 1; // Signifies items that are not consumed immediately upon double-click [Skotlex]
- unsigned trade_restriction : 9; ///< Item trade restrictions mask (@see enum ItemTradeRestrictions)
+ unsigned no_refine : 1; // [celest]
+ unsigned delay_consume : 1; ///< Signifies items that are not consumed immediately upon double-click [Skotlex]
+ unsigned trade_restriction : 9; ///< Item trade restrictions mask (@see enum ItemTradeRestrictions)
unsigned autoequip: 1;
unsigned buyingstore : 1;
unsigned bindonequip : 1;
+ unsigned keepafteruse : 1;
} flag;
struct {// item stacking limitation
unsigned short amount;
@@ -424,13 +427,17 @@ struct item_data {
unsigned int flag; ///< Item nouse restriction mask (@see enum ItemNouseRestrictions)
unsigned short override;
} item_usage;
- short gm_lv_trade_override; //GM-level to override trade_restriction
+ short gm_lv_trade_override; ///< GM-level to override trade_restriction
/* bugreport:309 */
struct item_combo **combos;
unsigned char combos_count;
/* TODO add a pointer to some sort of (struct extra) and gather all the not-common vals into it to save memory */
struct item_group *group;
struct item_package *package;
+
+ /* HPM Custom Struct */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
};
struct item_combo {
@@ -597,6 +604,7 @@ struct itemdb_interface {
void (*read_combos) ();
int (*gendercheck) (struct item_data *id);
int (*validate_entry) (struct item_data *entry, int n, const char *source);
+ void (*readdb_additional_fields) (int itemid, config_setting_t *it, int n, const char *source);
int (*readdb_sql_sub) (Sql *handle, int n, const char *source);
int (*readdb_libconfig_sub) (config_setting_t *it, int n, const char *source);
int (*readdb_libconfig) (const char *filename);
@@ -607,6 +615,8 @@ struct itemdb_interface {
int (*final_sub) (DBKey key, DBData *data, va_list ap);
void (*clear) (bool total);
struct item_combo * (*id2combo) (unsigned short id);
+ bool (*is_item_usable) (struct item_data *item);
+ bool (*lookup_const) (const config_setting_t *it, const char *name, int *value);
};
struct itemdb_interface *itemdb;
diff --git a/src/map/log.c b/src/map/log.c
index b5179e16b..92956fa67 100644
--- a/src/map/log.c
+++ b/src/map/log.c
@@ -20,6 +20,7 @@
#include "../common/showmsg.h"
#include "../common/sql.h" // SQL_INNODB
#include "../common/strlib.h"
+#include "../common/HPM.h"
struct log_interface log_s;
@@ -44,7 +45,7 @@ char log_picktype2char(e_log_pick_type type) {
case LOG_TYPE_BUYING_STORE: return 'B'; // (B)uying Store
case LOG_TYPE_LOOT: return 'L'; // (L)oot (consumed monster pick/drop)
case LOG_TYPE_BANK: return 'K'; // Ban(K) Transactions
- case LOG_TYPE_OTHER: return 'X'; // Other
+ case LOG_TYPE_OTHER: return 'X'; // Other
}
// should not get here, fallback
@@ -452,7 +453,9 @@ int log_config_read(const char* cfgName) {
safestrncpy(logs->config.log_chat, w2, sizeof(logs->config.log_chat));
//support the import command, just like any other config
else if( strcmpi(w1,"import") == 0 )
- log_config_read(w2);
+ logs->config_read(w2);
+ else if (HPM->parseConf(w1, w2, HPCT_LOG))
+ ; // handled by plugins
else
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
}
diff --git a/src/map/log.h b/src/map/log.h
index 6ab142f87..fb61b6e66 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;
/* */
@@ -110,7 +110,7 @@ struct log_interface {
void (*atcommand) (struct map_session_data* sd, const char* message);
void (*branch) (struct map_session_data* sd);
void (*mvpdrop) (struct map_session_data* sd, int monster_id, int* log_mvp);
-
+
void (*pick_sub) (int id, int16 m, e_log_pick_type type, int amount, struct item* itm, struct item_data *data);
void (*zeny_sub) (struct map_session_data* sd, e_log_pick_type type, struct map_session_data* src_sd, int amount);
void (*npc_sub) (struct map_session_data* sd, const char *message);
@@ -118,12 +118,12 @@ struct log_interface {
void (*atcommand_sub) (struct map_session_data* sd, const char* message);
void (*branch_sub) (struct map_session_data* sd);
void (*mvpdrop_sub) (struct map_session_data* sd, int monster_id, int* log_mvp);
-
+
int (*config_read) (const char* cfgName);
void (*config_done) (void);
void (*sql_init) (void);
void (*sql_final) (void);
-
+
char (*picktype2char) (e_log_pick_type type);
char (*chattype2char) (e_log_chat_type type);
bool (*should_log_item) (int nameid, int amount, int refine, struct item_data *id);
diff --git a/src/map/map.c b/src/map/map.c
index 0c8c2d949..25d7ce692 100644
--- a/src/map/map.c
+++ b/src/map/map.c
@@ -309,7 +309,7 @@ int map_moveblock(struct block_list *bl, int x1, int y1, int64 tick) {
skill->unit_move(bl,tick,2);
status_change_end(bl, SC_RG_CCONFINE_M, INVALID_TIMER);
status_change_end(bl, SC_RG_CCONFINE_S, INVALID_TIMER);
- // status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure...
+ //status_change_end(bl, SC_BLADESTOP, INVALID_TIMER); //Won't stop when you are knocked away, go figure...
status_change_end(bl, SC_NJ_TATAMIGAESHI, INVALID_TIMER);
status_change_end(bl, SC_MAGICROD, INVALID_TIMER);
if (sc && sc->data[SC_PROPERTYWALK] &&
@@ -395,9 +395,12 @@ 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
+ * 0x2 - don't count invinsible 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;
@@ -408,15 +411,41 @@ int map_count_oncell(int16 m, int16 x, int16 y, int type) {
bx = x/BLOCK_SIZE;
by = y/BLOCK_SIZE;
- 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)
+ 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) {
+ if (flag&0x2) {
+ struct status_change *sc = status->get_sc(bl);
+ if (sc && (sc->option&OPTION_INVISIBLE))
+ continue;
+ }
+ if (flag&0x1) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud && ud->walktimer != INVALID_TIMER)
+ continue;
+ }
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)
+ 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) {
+ if (flag&0x2) {
+ struct status_change *sc = status->get_sc(bl);
+ if (sc && (sc->option&OPTION_INVISIBLE))
+ continue;
+ }
+ if (flag&0x1) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ if (ud && ud->walktimer != INVALID_TIMER)
+ continue;
+ }
count++;
+ }
+ }
+ }
return count;
}
@@ -1379,7 +1408,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 +1502,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
@@ -1692,7 +1800,7 @@ int map_quit(struct map_session_data *sd) {
if( sd->bg_id && !sd->bg_queue.arena ) /* TODO: dump this chunk after bg_queue is fully enabled */
bg->team_leave(sd,BGTL_QUIT);
- if( sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !hChSys.closing )
+ if (sd->state.autotrade && runflag != MAPSERVER_ST_SHUTDOWN && !clif->hChSys->closing)
pc->autotrade_update(sd,PAUC_REMOVE);
skill->cooldown_save(sd);
@@ -1749,7 +1857,7 @@ int map_quit(struct map_session_data *sd) {
unit->remove_map(&sd->ed->bl,CLR_TELEPORT,ALC_MARK);
}
- if( hChSys.local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id) ) {
+ if (clif->hChSys->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) {
clif->chsys_left(map->list[sd->bl.m].channel,sd);
}
@@ -2412,36 +2520,31 @@ uint8 map_calc_dir(struct block_list* src, int16 x, int16 y)
dx = x-src->x;
dy = y-src->y;
- if( dx == 0 && dy == 0 )
- { // both are standing on the same spot.
+ if (dx == 0 && dy == 0) {
+ // both are standing on the same spot.
// aegis-style, makes knockback default to the left.
// athena-style, makes knockback default to behind 'src'.
dir = (battle_config.knockback_left ? 6 : unit->getdir(src));
- }
- 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
- }
- 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
- }
- 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
- }
- else
- { // upper-left
- if( -dx*2 <= dy ) dir = 0; // up
- else if( -dx > dy*2 ) dir = 2; // left
- else dir = 1; // up-left
-
+ } else if (dx >= 0 && dy >=0) {
+ // upper-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 || 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 || 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 || dx == 0 ) dir = 0; // up
+ else if( -dx > dy*2+1 || dy == 0) dir = 2; // left
+ else dir = 1; // up-left
}
return dir;
}
@@ -2479,7 +2582,7 @@ int map_random_dir(struct block_list *bl, int16 *x, int16 *y)
}
// gat system
-inline static struct mapcell map_gat2cell(int gat) {
+struct mapcell map_gat2cell(int gat) {
struct mapcell cell;
memset(&cell,0,sizeof(struct mapcell));
@@ -2526,9 +2629,6 @@ void map_cellfromcache(struct map_data *m) {
// Set cell properties
for( xy = 0; xy < size; ++xy ) {
m->cell[xy] = map->gat2cell(decode_buffer[xy]);
-#ifdef CELL_NOSTACK
- m->cell[xy].cell_bl = 0;
-#endif
}
m->getcellp = map->getcellp;
@@ -2587,25 +2687,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 +2748,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;
@@ -3300,9 +3404,6 @@ int map_readgat (struct map_data* m)
type = 3; // Cell is 0 (walkable) but under water level, set to 3 (walkable water)
m->cell[xy] = map->gat2cell(type);
-#ifdef CELL_NOSTACK
- m->cell[xy].cell_bl = 0;
-#endif
}
aFree(gat);
@@ -3384,8 +3485,8 @@ int map_readallmaps (void) {
map->list[i].m = i;
map->addmap2db(&map->list[i]);
- memset(map->list[i].moblist, 0, sizeof(map->list[i].moblist)); //Initialize moblist [Skotlex]
- map->list[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex]
+ memset(map->list[i].moblist, 0, sizeof(map->list[i].moblist)); //Initialize moblist [Skotlex]
+ map->list[i].mob_delete_timer = INVALID_TIMER; //Initialize timer [Skotlex]
map->list[i].bxs = (map->list[i].xs + BLOCK_SIZE - 1) / BLOCK_SIZE;
map->list[i].bys = (map->list[i].ys + BLOCK_SIZE - 1) / BLOCK_SIZE;
@@ -3621,15 +3722,19 @@ int inter_config_read(char *cfgName) {
if(strcmpi(w1,"item_db_db")==0)
strcpy(map->item_db_db,w2);
else if(strcmpi(w1,"mob_db_db")==0)
- strcpy(map->mob_db_db,w2);
+ strcpy(map->mob_db_db, w2);
+ else if (strcmpi(w1, "mob_db_re_db") == 0)
+ strcpy(map->mob_db_re_db, w2);
else if(strcmpi(w1,"item_db2_db")==0)
strcpy(map->item_db2_db,w2);
else if(strcmpi(w1,"item_db_re_db")==0)
strcpy(map->item_db_re_db,w2);
else if(strcmpi(w1,"mob_db2_db")==0)
- strcpy(map->mob_db2_db,w2);
- else if(strcmpi(w1,"mob_skill_db_db")==0)
- strcpy(map->mob_skill_db_db,w2);
+ strcpy(map->mob_db2_db, w2);
+ else if(strcmpi(w1, "mob_skill_db_db") == 0)
+ strcpy(map->mob_skill_db_db, w2);
+ else if(strcmpi(w1, "mob_skill_db_re_db") == 0)
+ strcpy(map->mob_skill_db_re_db, w2);
else if(strcmpi(w1,"mob_skill_db2_db")==0)
strcpy(map->mob_skill_db2_db,w2);
else if(strcmpi(w1,"interreg_db")==0)
@@ -3682,6 +3787,8 @@ int inter_config_read(char *cfgName) {
/* import */
else if(strcmpi(w1,"import")==0)
map->inter_config_read(w2);
+ else
+ HPM->parseConf(w1, w2, HPCT_MAP_INTER);
}
fclose(fp);
@@ -5020,6 +5127,7 @@ void read_map_zone_db(void) {
CREATE( entry, struct map_zone_disabled_skill_entry, 1 );
entry->nameid = izone->disabled_skills[j]->nameid;
entry->type = izone->disabled_skills[j]->type;
+ entry->subtype = izone->disabled_skills[j]->subtype;
zone->disabled_skills[zone->disabled_skills_count-1] = entry;
}
}
@@ -5114,6 +5222,7 @@ void read_map_zone_db(void) {
entry->nameid = izone->capped_skills[j]->nameid;
entry->cap = izone->capped_skills[j]->cap;
entry->type = izone->capped_skills[j]->type;
+ entry->subtype = izone->capped_skills[j]->subtype;
zone->capped_skills[zone->capped_skills_count-1] = entry;
}
}
@@ -5248,7 +5357,7 @@ int do_final(void) {
ShowStatus("Terminating...\n");
- hChSys.closing = true;
+ clif->hChSys->closing = true;
HPM->event(HPET_FINAL);
if (map->cpsd) aFree(map->cpsd);
@@ -5392,7 +5501,7 @@ void map_helpscreen(bool do_exit)
ShowInfo(" scripts passed through --load-script.\n");
ShowInfo(" --load-script <file> Loads an additional script (can be repeated).\n");
ShowInfo(" --load-plugin <name> Loads an additional plugin (can be repeated).\n");
- HPM->arg_help();/* display help for commands implemented thru HPM */
+ HPM->arg_help(); /* display help for commands implemented through HPM */
if( do_exit )
exit(EXIT_SUCCESS);
}
@@ -5489,9 +5598,9 @@ void map_cp_defaults(void) {
/* default HCP data */
map->cpsd = pc->get_dummy_sd();
strcpy(map->cpsd->status.name, "Hercules Console");
- map->cpsd->bl.x = MAP_DEFAULT_X;
- map->cpsd->bl.y = MAP_DEFAULT_Y;
- map->cpsd->bl.m = map->mapname2mapid(MAP_DEFAULT);
+ map->cpsd->bl.x = mapindex->default_x;
+ map->cpsd->bl.y = mapindex->default_y;
+ map->cpsd->bl.m = map->mapname2mapid(mapindex->default_map);
console->input->addCommand("gm:info",CPCMD_A(gm_position));
console->input->addCommand("gm:use",CPCMD_A(gm_use));
@@ -5609,10 +5718,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 ) {
@@ -5841,7 +5947,7 @@ int do_init(int argc, char *argv[])
exit(EXIT_SUCCESS);
}
- npc->event_do_oninit( false ); // Init npcs (OnInit)
+ npc->event_do_oninit( false ); // Init npcs (OnInit)
npc->market_fromsql(); /* after OnInit */
if (battle_config.pk_mode)
@@ -5903,8 +6009,10 @@ void map_defaults(void) {
sprintf(map->item_db2_db, "item_db2");
sprintf(map->item_db_re_db, "item_db_re");
sprintf(map->mob_db_db, "mob_db");
+ sprintf(map->mob_db_re_db, "mob_db_re");
sprintf(map->mob_db2_db, "mob_db2");
sprintf(map->mob_skill_db_db, "mob_skill_db");
+ sprintf(map->mob_skill_db_re_db, "mob_skill_db_re");
sprintf(map->mob_skill_db2_db, "mob_skill_db2");
sprintf(map->interreg_db, "interreg");
@@ -5998,6 +6106,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..447437cf4 100644
--- a/src/map/map.h
+++ b/src/map/map.h
@@ -295,6 +295,16 @@ enum {
ELE_MAX
};
+enum {
+ SPIRITS_TYPE_NONE = 0,
+ SPIRITS_TYPE_CHARM_WATER,
+ SPIRITS_TYPE_CHARM_LAND,
+ SPIRITS_TYPE_CHARM_FIRE,
+ SPIRITS_TYPE_CHARM_WIND,
+ SPIRITS_TYPE_SPHERE,
+ SPIRITS_TYPE_END
+};
+
enum auto_trigger_flag {
ATF_SELF=0x01,
ATF_TARGET=0x02,
@@ -315,20 +325,20 @@ struct block_list {
// Mob List Held in memory for Dynamic Mobs [Wizputer]
// Expanded to specify all mob-related spawn data by [Skotlex]
struct spawn_data {
- short class_; //Class, used because a mob can change it's class
- unsigned short m, x, y; //Spawn information (map, point, spawn-area around point)
+ short class_; ///< Class, used because a mob can change it's class
+ unsigned short m, x, y; ///< Spawn information (map, point, spawn-area around point)
signed short xs, ys;
- unsigned short num; //Number of mobs using this structure
- unsigned short active;//Number of mobs that are already spawned (for mob_remove_damaged: no)
- unsigned int delay1, delay2; //Spawn delay (fixed base + random variance)
+ unsigned short num; ///< Number of mobs using this structure
+ unsigned short active; ///< Number of mobs that are already spawned (for mob_remove_damaged: no)
+ unsigned int delay1, delay2; ///< Spawn delay (fixed base + random variance)
unsigned int level;
struct {
- unsigned int size : 2; //Holds if mob has to be tiny/large
- unsigned int ai : 4; //Special AI for summoned monsters.
+ unsigned int size : 2; ///< Holds if mob has to be tiny/large
+ unsigned int ai : 4; ///< Special AI for summoned monsters.
//0: Normal mob | 1: Standard summon, attacks mobs
//2: Alchemist Marine Sphere | 3: Alchemist Summon Flora | 4: Summon Zanzou
- unsigned int dynamic : 1; //Whether this data is indexed by a map's dynamic mob list
- unsigned int boss : 1; //0: Non-boss monster | 1: Boss monster
+ unsigned int dynamic : 1; ///< Whether this data is indexed by a map's dynamic mob list
+ unsigned int boss : 1; ///< 0: Non-boss monster | 1: Boss monster
} state;
char name[NAME_LENGTH], eventname[EVENT_NAME_LENGTH]; //Name/event
};
@@ -343,18 +353,18 @@ struct flooritem_data {
};
enum status_point_types {
- SP_SPEED,SP_BASEEXP,SP_JOBEXP,SP_KARMA,SP_MANNER,SP_HP,SP_MAXHP,SP_SP, // 0-7
- SP_MAXSP,SP_STATUSPOINT,SP_0a,SP_BASELEVEL,SP_SKILLPOINT,SP_STR,SP_AGI,SP_VIT, // 8-15
- SP_INT,SP_DEX,SP_LUK,SP_CLASS,SP_ZENY,SP_SEX,SP_NEXTBASEEXP,SP_NEXTJOBEXP, // 16-23
- SP_WEIGHT,SP_MAXWEIGHT,SP_1a,SP_1b,SP_1c,SP_1d,SP_1e,SP_1f, // 24-31
- SP_USTR,SP_UAGI,SP_UVIT,SP_UINT,SP_UDEX,SP_ULUK,SP_26,SP_27, // 32-39
- SP_28,SP_ATK1,SP_ATK2,SP_MATK1,SP_MATK2,SP_DEF1,SP_DEF2,SP_MDEF1, // 40-47
- SP_MDEF2,SP_HIT,SP_FLEE1,SP_FLEE2,SP_CRITICAL,SP_ASPD,SP_36,SP_JOBLEVEL, // 48-55
- SP_UPPER,SP_PARTNER,SP_CART,SP_FAME,SP_UNBREAKABLE, //56-60
- SP_CARTINFO=99, // 99
-
- SP_BASEJOB=119, // 100+19 - celest
- SP_BASECLASS=120, //Hmm.. why 100+19? I just use the next one... [Skotlex]
+ SP_SPEED,SP_BASEEXP,SP_JOBEXP,SP_KARMA,SP_MANNER,SP_HP,SP_MAXHP,SP_SP, // 0-7
+ SP_MAXSP,SP_STATUSPOINT,SP_0a,SP_BASELEVEL,SP_SKILLPOINT,SP_STR,SP_AGI,SP_VIT, // 8-15
+ SP_INT,SP_DEX,SP_LUK,SP_CLASS,SP_ZENY,SP_SEX,SP_NEXTBASEEXP,SP_NEXTJOBEXP, // 16-23
+ SP_WEIGHT,SP_MAXWEIGHT,SP_1a,SP_1b,SP_1c,SP_1d,SP_1e,SP_1f, // 24-31
+ SP_USTR,SP_UAGI,SP_UVIT,SP_UINT,SP_UDEX,SP_ULUK,SP_26,SP_27, // 32-39
+ SP_28,SP_ATK1,SP_ATK2,SP_MATK1,SP_MATK2,SP_DEF1,SP_DEF2,SP_MDEF1, // 40-47
+ SP_MDEF2,SP_HIT,SP_FLEE1,SP_FLEE2,SP_CRITICAL,SP_ASPD,SP_36,SP_JOBLEVEL, // 48-55
+ SP_UPPER,SP_PARTNER,SP_CART,SP_FAME,SP_UNBREAKABLE, //56-60
+ SP_CARTINFO=99, // 99
+
+ SP_BASEJOB=119, // 100+19 - celest
+ SP_BASECLASS=120, //Hmm.. why 100+19? I just use the next one... [Skotlex]
SP_KILLERRID=121,
SP_KILLEDRID=122,
SP_SLOTCHANGE=123,
@@ -367,10 +377,10 @@ enum status_point_types {
SP_MERCFLEE=165, SP_MERCKILLS=189, SP_MERCFAITH=190,
// original 1000-
- SP_ATTACKRANGE=1000, SP_ATKELE,SP_DEFELE, // 1000-1002
+ SP_ATTACKRANGE=1000, SP_ATKELE,SP_DEFELE, // 1000-1002
SP_CASTRATE, SP_MAXHPRATE, SP_MAXSPRATE, SP_SPRATE, // 1003-1006
SP_ADDELE, SP_ADDRACE, SP_ADDSIZE, SP_SUBELE, SP_SUBRACE, // 1007-1011
- SP_ADDEFF, SP_RESEFF, // 1012-1013
+ SP_ADDEFF, SP_RESEFF, // 1012-1013
SP_BASE_ATK,SP_ASPD_RATE,SP_HP_RECOV_RATE,SP_SP_RECOV_RATE,SP_SPEED_RATE, // 1014-1018
SP_CRITICAL_DEF,SP_NEAR_ATK_DEF,SP_LONG_ATK_DEF, // 1019-1021
SP_DOUBLE_RATE, SP_DOUBLE_ADD_RATE, SP_SKILL_HEAL, SP_MATK_RATE, // 1022-1025
@@ -401,8 +411,8 @@ enum status_point_types {
SP_CRIT_ATK_RATE, SP_CRITICAL_ADDRACE, SP_NO_REGEN, SP_ADDEFF_WHENHIT, SP_AUTOSPELL_WHENHIT, // 2013-2017
SP_SKILL_ATK, SP_UNSTRIPABLE, SP_AUTOSPELL_ONSKILL, // 2018-2020
SP_SP_GAIN_VALUE, SP_HP_REGEN_RATE, SP_HP_LOSS_RATE, SP_ADDRACE2, SP_HP_GAIN_VALUE, // 2021-2025
- SP_SUBSIZE, SP_HP_DRAIN_VALUE_RACE, SP_ADD_ITEM_HEAL_RATE, SP_SP_DRAIN_VALUE_RACE, SP_EXP_ADDRACE, // 2026-2030
- SP_SP_GAIN_RACE, SP_SUBRACE2, SP_UNBREAKABLE_SHOES, // 2031-2033
+ SP_SUBSIZE, SP_HP_DRAIN_VALUE_RACE, SP_ADD_ITEM_HEAL_RATE, SP_SP_DRAIN_VALUE_RACE, SP_EXP_ADDRACE, // 2026-2030
+ SP_SP_GAIN_RACE, SP_SUBRACE2, SP_UNBREAKABLE_SHOES, // 2031-2033
SP_UNSTRIPABLE_WEAPON,SP_UNSTRIPABLE_ARMOR,SP_UNSTRIPABLE_HELM,SP_UNSTRIPABLE_SHIELD, // 2034-2037
SP_INTRAVISION, SP_ADD_MONSTER_DROP_CHAINITEM, SP_SP_LOSS_RATE, // 2038-2040
SP_ADD_SKILL_BLOW, SP_SP_VANISH_RATE, SP_MAGIC_SP_GAIN_VALUE, SP_MAGIC_HP_GAIN_VALUE, SP_ADD_CLASS_DROP_ITEM, //2041-2045
@@ -410,8 +420,7 @@ enum status_point_types {
SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2050-2054
SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST, //2055-2058
SP_SET_DEF_RACE,SP_SET_MDEF_RACE, //2059-2060
-
-
+
/* must be the last, plugins add bonuses from this value onwards */
SP_LAST_KNOWN,
};
@@ -444,22 +453,23 @@ typedef enum {
CELL_NOVENDING,
CELL_NOCHAT,
CELL_ICEWALL,
+ CELL_NOICEWALL,
} cell_t;
// used by map->getcell()
typedef enum {
- CELL_GETTYPE, // retrieves a cell's 'gat' type
+ CELL_GETTYPE, ///< retrieves a cell's 'gat' type
- CELL_CHKWALL, // wall (gat type 1)
- CELL_CHKWATER, // water (gat type 3)
- CELL_CHKCLIFF, // cliff/gap (gat type 5)
+ CELL_CHKWALL, ///< wall (gat type 1)
+ CELL_CHKWATER, ///< water (gat type 3)
+ CELL_CHKCLIFF, ///< cliff/gap (gat type 5)
- CELL_CHKPASS, // passable cell (gat type non-1/5)
- CELL_CHKREACH, // Same as PASS, but ignores the cell-stacking mod.
- CELL_CHKNOPASS, // non-passable cell (gat types 1 and 5)
- CELL_CHKNOREACH, // Same as NOPASS, but ignores the cell-stacking mod.
- CELL_CHKSTACK, // whether cell is full (reached cell stacking limit)
+ CELL_CHKPASS, ///< passable cell (gat type non-1/5)
+ CELL_CHKREACH, ///< Same as PASS, but ignores the cell-stacking mod.
+ CELL_CHKNOPASS, ///< non-passable cell (gat types 1 and 5)
+ CELL_CHKNOREACH, ///< Same as NOPASS, but ignores the cell-stacking mod.
+ CELL_CHKSTACK, ///< whether cell is full (reached cell stacking limit)
CELL_CHKNPC,
CELL_CHKBASILICA,
@@ -467,6 +477,7 @@ typedef enum {
CELL_CHKNOVENDING,
CELL_CHKNOCHAT,
CELL_CHKICEWALL,
+ CELL_CHKNOICEWALL,
} cell_chk;
@@ -484,7 +495,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.
@@ -504,11 +516,11 @@ struct mapflag_skill_adjust {
};
enum map_zone_skill_subtype {
- MZS_NONE = 0x0,
- MZS_CLONE = 0x01,
- MZS_BOSS = 0x02,
+ MZS_NONE = 0x0,
+ MZS_CLONE = 0x01,
+ MZS_BOSS = 0x02,
- MZS_ALL = 0xFFF,
+ MZS_ALL = 0xFFF
};
struct map_zone_disabled_skill_entry {
@@ -575,7 +587,7 @@ struct map_data {
char name[MAP_NAME_LENGTH];
uint16 index; // The map index used by the mapindex* functions.
struct mapcell* cell; // Holds the information of each map cell (NULL if the map is not on this map-server).
-
+
/* 2D Orthogonal Range Search: Grid Implementation
"Algorithms in Java, Parts 1-4" 3.18, Robert Sedgewick
Map is divided into squares, called blocks (side length = BLOCK_SIZE).
@@ -587,7 +599,7 @@ struct map_data {
*/
struct block_list **block; // Grid array of block_lists containing only non-BL_MOB objects
struct block_list **block_mob; // Grid array of block_lists containing only BL_MOB objects
-
+
int16 m;
int16 xs,ys; // map dimensions (in cells)
int16 bxs,bys; // map dimensions (in blocks)
@@ -630,10 +642,10 @@ struct map_data {
unsigned fireworks : 1;
unsigned sakura : 1; // [Valaris]
unsigned leaves : 1; // [Valaris]
- unsigned nobaseexp : 1; // [Lorky] added by Lupus
- unsigned nojobexp : 1; // [Lorky]
- unsigned nomobloot : 1; // [Lorky]
- unsigned nomvploot : 1; // [Lorky]
+ unsigned nobaseexp : 1; // [Lorky] added by Lupus
+ unsigned nojobexp : 1; // [Lorky]
+ unsigned nomobloot : 1; // [Lorky]
+ unsigned nomvploot : 1; // [Lorky]
unsigned nightenabled :1; //For night display. [Skotlex]
unsigned nodrop : 1;
unsigned novending : 1;
@@ -654,17 +666,11 @@ struct map_data {
unsigned short drop_list_count;
struct spawn_data *moblist[MAX_MOB_LIST_PER_MAP]; // [Wizputer]
- int mob_delete_timer; // [Skotlex]
- int jexp; // map experience multiplicator
- int bexp; // map experience multiplicator
+ int mob_delete_timer; // [Skotlex]
+ 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;
@@ -705,14 +711,14 @@ struct map_data {
int (*getcellp)(struct map_data* m,int16 x,int16 y,cell_chk cellchk);
void (*setcell) (int16 m, int16 x, int16 y, cell_t cell, bool flag);
char *cellPos;
-
+
/* ShowEvent Data Cache */
struct questinfo *qi_data;
unsigned short qi_count;
-
+
/* speeds up clif_updatestatus processing by causing hpmeter to run only when someone with the permission can view it */
unsigned short hpmeter_visible;
-
+
/* HPM Custom Struct */
struct HPluginData **hdata;
unsigned int hdatac;
@@ -733,7 +739,7 @@ struct map_data_other_server {
/// Bitfield of flags for the iterator.
enum e_mapitflags {
MAPIT_NORMAL = 0,
- // MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold authed, active players.
+ //MAPIT_PCISPLAYING = 1,// Unneeded as pc_db/id_db will only hold authed, active players.
};
struct s_mapiterator;
@@ -767,7 +773,7 @@ typedef struct skill_unit TBL_SKILL;
typedef struct pet_data TBL_PET;
typedef struct homun_data TBL_HOM;
typedef struct mercenary_data TBL_MER;
-typedef struct elemental_data TBL_ELEM;
+typedef struct elemental_data TBL_ELEM;
#define BL_CAST(type_, bl) \
( ((bl) == (struct block_list*)NULL || (bl)->type != (type_)) ? (T ## type_ *)NULL : (T ## type_ *)(bl) )
@@ -840,8 +846,10 @@ struct map_interface {
char item_db2_db[32];
char item_db_re_db[32];
char mob_db_db[32];
+ char mob_db_re_db[32];
char mob_db2_db[32];
char mob_skill_db_db[32];
+ char mob_skill_db_re_db[32];
char mob_skill_db2_db[32];
char interreg_db[32];
char autotrade_merchants_db[32];
@@ -849,17 +857,17 @@ struct map_interface {
char npc_market_data_db[32];
char default_codepage[32];
-
+
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;
-
+
int port;
int users;
- int enable_grf; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
+ int enable_grf; //To enable/disable reading maps from GRF files, bypassing mapcache [blackhole89]
bool ip_set;
bool char_ip_set;
@@ -920,11 +928,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
@@ -1018,7 +1027,7 @@ struct map_interface {
void (*clean) (int i);
void (*do_shutdown) (void);
-
+
int (*freeblock_timer) (int tid, int64 tick, int id, intptr_t data);
int (*searchrandfreecell) (int16 m, int16 *x, int16 *y, int stack);
int (*count_sub) (struct block_list *bl, va_list ap);
diff --git a/src/map/mercenary.c b/src/map/mercenary.c
index 80bcfdf05..a1503e97a 100644
--- a/src/map/mercenary.c
+++ b/src/map/mercenary.c
@@ -362,7 +362,7 @@ int mercenary_killbonus(struct mercenary_data *md)
const enum sc_type scs[] = { SC_MER_FLEE, SC_MER_ATK, SC_MER_HP, SC_MER_SP, SC_MER_HIT };
int index = rnd() % ARRAYLENGTH(scs);
- sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000);
+ sc_start(NULL,&md->bl, scs[index], 100, rnd() % 5, 600000);
return 0;
}
diff --git a/src/map/mercenary.h b/src/map/mercenary.h
index 270245e96..68f60b08b 100644
--- a/src/map/mercenary.h
+++ b/src/map/mercenary.h
@@ -42,7 +42,7 @@ struct mercenary_data {
struct map_session_data *master;
int contract_timer;
-
+
unsigned devotion_flag : 1;
int64 masterteleport_timer;
};
@@ -55,26 +55,26 @@ struct mercenary_data {
struct mercenary_interface {
/* vars */
-
+
struct s_mercenary_db db[MAX_MERCENARY_CLASS];
/* funcs */
void (*init) (bool minimal);
-
+
bool (*class) (int class_);
struct view_data * (*get_viewdata) (int class_);
-
+
int (*create) (struct map_session_data *sd, int class_, unsigned int lifetime);
int (*data_received) (struct s_mercenary *merc, bool flag);
int (*save) (struct mercenary_data *md);
-
+
void (*heal) (struct mercenary_data *md, int hp, int sp);
int (*dead) (struct mercenary_data *md);
-
+
int (*delete) (struct mercenary_data *md, int reply);
void (*contract_stop) (struct mercenary_data *md);
-
+
int (*get_lifetime) (struct mercenary_data *md);
int (*get_guild) (struct mercenary_data *md);
int (*get_faith) (struct mercenary_data *md);
@@ -82,14 +82,14 @@ struct mercenary_interface {
int (*get_calls) (struct mercenary_data *md);
int (*set_calls) (struct mercenary_data *md, int value);
int (*kills) (struct mercenary_data *md);
-
+
int (*checkskill) (struct mercenary_data *md, uint16 skill_id);
int (*read_db) (void);
int (*read_skilldb) (void);
-
+
int (*killbonus) (struct mercenary_data *md);
int (*search_index) (int class_);
-
+
int (*contract_end_timer) (int tid, int64 tick, int id, intptr_t data);
bool (*read_db_sub) (char* str[], int columns, int current);
bool (*read_skill_db_sub) (char* str[], int columns, int current);
diff --git a/src/map/mob.c b/src/map/mob.c
index 3f1769d37..4db8cb2f6 100644
--- a/src/map/mob.c
+++ b/src/map/mob.c
@@ -34,6 +34,7 @@
#include "script.h"
#include "skill.h"
#include "status.h"
+#include "../common/HPM.h"
#include "../common/cbasetypes.h"
#include "../common/db.h"
#include "../common/ers.h"
@@ -48,17 +49,19 @@
struct mob_interface mob_s;
-#define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode.
+#define ACTIVE_AI_RANGE 2 //Distance added on top of 'AREA_SIZE' at which mobs enter active AI mode.
-#define IDLE_SKILL_INTERVAL 10 //Active idle skills should be triggered every 1 second (1000/MIN_MOBTHINKTIME)
+#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)
#define MOB_MAX_DELAY (24*3600*1000)
-#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs.
-#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used?
+#define MAX_MINCHASE 30 //Max minimum chase value to use for mobs.
+#define RUDE_ATTACKED_COUNT 2 //After how many rude-attacks should the skill be used?
//Dynamic item drop ratio database for per-item drop ratio modifiers overriding global drop ratios.
#define MAX_ITEMRATIO_MOBS 10
@@ -139,14 +142,9 @@ void mvptomb_create(struct mob_data *md, char *killer, time_t time)
if ( md->tomb_nid )
mob->mvptomb_destroy(md);
- CREATE(nd, struct npc_data, 1);
-
- nd->bl.id = md->tomb_nid = npc->get_new_npc_id();
-
+ nd = npc->create_npc(md->bl.m, md->bl.x, md->bl.y);
+ md->tomb_nid = nd->bl.id;
nd->dir = md->ud.dir;
- nd->bl.m = md->bl.m;
- nd->bl.x = md->bl.x;
- nd->bl.y = md->bl.y;
nd->bl.type = BL_NPC;
safestrncpy(nd->name, msg_txt(856), sizeof(nd->name)); // "Tomb"
@@ -418,7 +416,8 @@ bool mob_ksprotected(struct block_list *src, struct block_list *target) {
return true;
} while(0);
- status->change_start(NULL, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks, sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, 0);
+ status->change_start(NULL, target, SC_KSPROTECTED, 10000, sd->bl.id, sd->state.noks,
+ sd->status.party_id, sd->status.guild_id, battle_config.ksprotection, SCFLAG_NONE);
return false;
}
@@ -499,7 +498,7 @@ int mob_once_spawn(struct map_session_data* sd, int16 m, int16 x, int16 y, const
else if( gc->guild_id ) //Guild not yet available, retry in 5.
timer->add(timer->gettick()+5000,mob->spawn_guardian_sub,md->bl.id,gc->guild_id);
}
- } // end addition [Valaris]
+ } // end addition [Valaris]
mob->spawn(md);
@@ -674,8 +673,8 @@ int mob_spawn_guardian(const char* mapname, short x, short y, const char* mobnam
else
g = guild->search(gc->guild_id);
- if( has_index && gc->guardian[guardian].id )
- { //Check if guardian already exists, refuse to spawn if so.
+ if( has_index && gc->guardian[guardian].id ) {
+ //Check if guardian already exists, refuse to spawn if so.
struct mob_data *md2 = (TBL_MOB*)map->id2bl(gc->guardian[guardian].id);
if (md2 && md2->bl.type == BL_MOB
&& md2->guardian_data
@@ -802,7 +801,8 @@ int mob_linksearch(struct block_list *bl,va_list ap) {
&& !md->target_id)
{
md->last_linktime = tick;
- if( mob->can_reach(md,target,md->db->range2, MSS_FOLLOW) ){ // Reachability judging
+ if (mob->can_reach(md,target,md->db->range2, MSS_FOLLOW)) {
+ // Reachability judging
md->target_id = target->id;
md->min_chase=md->db->range3;
return 1;
@@ -850,17 +850,20 @@ int mob_setdelayspawn(struct mob_data *md)
//Apply the spawn delay fix [Skotlex]
db = mob->db(md->spawn->class_);
mode = db->status.mode;
- if (mode & MD_BOSS) { //Bosses
+ if (mode & MD_BOSS) {
+ //Bosses
if (battle_config.boss_spawn_delay != 100) {
// Divide by 100 first to prevent overflows
//(precision loss is minimal as duration is in ms already)
spawntime = spawntime/100*battle_config.boss_spawn_delay;
}
- } else if (mode&MD_PLANT) { //Plants
+ } else if (mode&MD_PLANT) {
+ //Plants
if (battle_config.plant_spawn_delay != 100) {
spawntime = spawntime/100*battle_config.plant_spawn_delay;
}
- } else if (battle_config.mob_spawn_delay != 100) { //Normal mobs
+ } else if (battle_config.mob_spawn_delay != 100) {
+ //Normal mobs
spawntime = spawntime/100*battle_config.mob_spawn_delay;
}
@@ -934,18 +937,19 @@ int mob_spawn (struct mob_data *md)
md->move_fail_count = 0;
md->ud.state.attack_continue = 0;
md->ud.target_to = 0;
+ md->ud.dir = 0;
if( md->spawn_timer != INVALID_TIMER )
{
timer->delete(md->spawn_timer, mob->delayspawn);
md->spawn_timer = INVALID_TIMER;
}
-// md->master_id = 0;
+ //md->master_id = 0;
md->master_dist = 0;
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;
@@ -1024,7 +1028,7 @@ int mob_target(struct mob_data *md,struct block_list *bl,int dist)
if(!status->check_skilluse(&md->bl, bl, 0, 0))
return 0;
- md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
+ md->target_id = bl->id; // Since there was no disturbance, it locks on to target.
if (md->state.provoke_flag && bl->id != md->state.provoke_flag)
md->state.provoke_flag = 0;
md->min_chase=dist+md->db->range3;
@@ -1073,15 +1077,15 @@ 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;
-
- }
-
+#ifdef ACTIVEPATHSEARCH
+ struct walkpath_data wpd;
+ if (!path->search(&wpd, md->bl.m, md->bl.x, md->bl.y, bl->x, bl->y, 0, CELL_CHKNOPASS)) // Count walk path cells
+ return 0;
+ //Standing monsters use range2, walking monsters use range3
+ if ((md->ud.walktimer == INVALID_TIMER && wpd.path_len > md->db->range2)
+ || (md->ud.walktimer != INVALID_TIMER && wpd.path_len > md->db->range3))
+ return 0;
+#endif
(*target) = bl;
md->target_id=bl->id;
md->min_chase= dist + md->db->range3;
@@ -1203,8 +1207,8 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
if (bl->prev == NULL)
return 0; //Master not on a map? Could be warping, do not process.
- if(status_get_mode(&md->bl)&MD_CANMOVE)
- { //If the mob can move, follow around. [Check by Skotlex]
+ if (status_get_mode(&md->bl)&MD_CANMOVE) {
+ //If the mob can move, follow around. [Check by Skotlex]
int old_dist;
// Distance with between slave and master is measured.
@@ -1241,8 +1245,7 @@ int mob_ai_sub_hard_slavemob(struct mob_data *md, int64 tick) {
}
//Avoid attempting to lock the master's target too often to avoid unnecessary overload. [Skotlex]
- if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id)
- {
+ if (DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME && !md->target_id) {
struct unit_data *ud = unit->bl2ud(bl);
md->last_linktime = tick;
@@ -1285,22 +1288,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) {
@@ -1308,6 +1312,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;
}
/*==========================================
@@ -1327,14 +1335,16 @@ int mob_randomwalk(struct mob_data *md, int64 tick) {
d =12-md->move_fail_count;
if(d<5) d=5;
- for(i=0;i<retrycount;i++){ // Search of a movable place
+ 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;
y=r/(d*2+1)%(d*2+1)-d;
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;
}
}
@@ -1357,7 +1367,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;
}
@@ -1403,9 +1413,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]) {
@@ -1433,30 +1440,35 @@ 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;
}
}
// Check for target change.
- if( md->attacked_id && mode&MD_CANATTACK )
- {
- 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_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->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
- { //Escaped
+ if (md->attacked_id && mode&MD_CANATTACK) {
+ 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_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, 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
+ ) {
+ //Escaped
md->attacked_id = 0;
return true;
}
@@ -1470,18 +1482,21 @@ 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)
)
)
) {
// Rude attacked
if (md->state.attacked_count++ >= RUDE_ATTACKED_COUNT
- && !mob->skill_use(md, tick, MSC_RUDEATTACKED) && can_move
- && !tbl && unit->escape(&md->bl, abl, rnd()%10 +1))
- { //Escaped.
+ && !mob->skill_use(md, tick, MSC_RUDEATTACKED) && can_move
+ && !tbl && unit->escape(&md->bl, abl, rnd()%10 +1)
+ ) {
+ //Escaped.
//TODO: Maybe it shouldn't attempt to run if it has another, valid target?
md->attacked_id = 0;
return true;
@@ -1492,9 +1507,11 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
//Can't attack back, but didn't invoke a rude attacked skill...
} else {
//Attackable
- if (!tbl || dist < md->status.rhw.range || !check_distance_bl(&md->bl, tbl, dist)
- || battle->get_target(tbl) != md->bl.id)
- { //Change if the new target is closer than the actual one
+ if (!tbl || dist < md->status.rhw.range
+ || !check_distance_bl(&md->bl, tbl, dist)
+ || battle->get_target(tbl) != md->bl.id
+ ) {
+ //Change if the new target is closer than the actual one
//or if the previous target is not attacking the mob. [Skotlex]
md->target_id = md->attacked_id; // set target
if (md->state.attacked_count)
@@ -1546,26 +1563,26 @@ 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;
}
//Target exists, attack or loot as applicable.
- if (tbl->type == BL_ITEM)
- { //Loot time.
+ if (tbl->type == BL_ITEM) {
+ //Loot time.
struct flooritem_data *fitem;
if (md->ud.target == tbl->id && md->ud.walktimer != INVALID_TIMER)
return true; //Already locked.
- if (md->lootitem == NULL)
- { //Can't loot...
+ if (md->lootitem == NULL) {
+ //Can't loot...
mob->unlocktarget (md, tick);
return true;
}
- if (!check_distance_bl(&md->bl, tbl, 1))
- { //Still not within loot range.
- if (!(mode&MD_CANMOVE))
- { //A looter that can't move? Real smart.
+ if (!check_distance_bl(&md->bl, tbl, 1)) {
+ //Still not within loot range.
+ if (!(mode&MD_CANMOVE)) {
+ //A looter that can't move? Real smart.
mob->unlocktarget(md,tick);
return true;
}
@@ -1586,14 +1603,15 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
if (md->lootitem_count < LOOTITEM_SIZE) {
memcpy (&md->lootitem[md->lootitem_count++], &fitem->item_data, sizeof(md->lootitem[0]));
- } else { //Destroy first looted item...
+ } else {
+ //Destroy first looted item...
if (md->lootitem[0].card[0] == CARD0_PET)
intif->delete_petdata( MakeDWord(md->lootitem[0].card[1],md->lootitem[0].card[2]) );
memmove(&md->lootitem[0], &md->lootitem[1], (LOOTITEM_SIZE-1)*sizeof(md->lootitem[0]));
memcpy (&md->lootitem[LOOTITEM_SIZE-1], &fitem->item_data, sizeof(md->lootitem[0]));
}
- if (pcdb_checkid(md->vd->class_))
- { //Give them walk act/delay to properly mimic players. [Skotlex]
+ if (pcdb_checkid(md->vd->class_)) {
+ //Give them walk act/delay to properly mimic players. [Skotlex]
clif->takeitem(&md->bl,tbl);
md->ud.canact_tick = tick + md->status.amotion;
unit->set_walkdelay(&md->bl, tick, md->status.amotion, 1);
@@ -1603,46 +1621,44 @@ 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)
+ unit->attack(&md->bl,tbl->id,1);
+ }
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;
}
@@ -1654,6 +1670,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);
@@ -1664,8 +1681,8 @@ bool mob_ai_sub_hard(struct mob_data *md, int64 tick) {
int mob_ai_sub_hard_timer(struct block_list *bl, va_list ap) {
struct mob_data *md = (struct mob_data*)bl;
int64 tick = va_arg(ap, int64);
- if (mob->ai_sub_hard(md, tick))
- { //Hard AI triggered.
+ if (mob->ai_sub_hard(md, tick)) {
+ //Hard AI triggered.
if(!md->state.spotted)
md->state.spotted = 1;
md->last_pcneartime = tick;
@@ -1703,11 +1720,11 @@ int mob_ai_sub_lazy(struct mob_data *md, va_list args) {
if (md->bl.prev==NULL || md->status.hp == 0)
return 1;
- if(battle_config.mob_active_time &&
- md->last_pcneartime &&
- !(md->status.mode&MD_BOSS) &&
- DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME)
- {
+ if (battle_config.mob_active_time
+ && md->last_pcneartime
+ && !(md->status.mode&MD_BOSS)
+ && DIFF_TICK(tick,md->last_thinktime) > MIN_MOBTHINKTIME
+ ) {
if (DIFF_TICK(tick,md->last_pcneartime) < battle_config.mob_active_time)
return (int)mob->ai_sub_hard(md, tick);
md->last_pcneartime = 0;
@@ -1734,20 +1751,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;
}
@@ -1840,7 +1854,8 @@ void mob_item_drop(struct mob_data *md, struct item_drop_list *dlist, struct ite
&& sd->bl.m == md->bl.m
&& check_distance_blxy(&sd->bl, dlist->x, dlist->y, AUTOLOOT_DISTANCE)
#endif
- ) { //Autoloot.
+ ) {
+ //Autoloot.
if (party->share_loot(party->search(sd->status.party_id),
sd, &ditem->item_data, sd->status.char_id) == 0
) {
@@ -1995,13 +2010,14 @@ void mob_log_damage(struct mob_data *md, struct block_list *src, int damage)
if(md->dmglog[i].id==char_id &&
md->dmglog[i].flag==flag)
break;
- if(md->dmglog[i].id==0) { //Store data in first empty slot.
+ if(md->dmglog[i].id==0) {
+ //Store data in first empty slot.
md->dmglog[i].id = char_id;
md->dmglog[i].flag= flag;
break;
}
- if(md->dmglog[i].dmg<mindmg && i)
- { //Never overwrite first hit slot (he gets double exp bonus)
+ if (md->dmglog[i].dmg<mindmg && i) {
+ //Never overwrite first hit slot (he gets double exp bonus)
minpos=i;
mindmg=md->dmglog[i].dmg;
}
@@ -2145,8 +2161,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
// determines, if the monster was killed by homunculus' damage only
homkillonly = (bool)( ( dmgbltypes&BL_HOM ) && !( dmgbltypes&~BL_HOM ) );
- if(!battle_config.exp_calc_type && count > 1)
- { //Apply first-attacker 200% exp share bonus
+ if (!battle_config.exp_calc_type && count > 1) {
+ //Apply first-attacker 200% exp share bonus
//TODO: Determine if this should go before calculating the MVP player instead of after.
if (UINT_MAX - md->dmglog[0].dmg > md->tdmg) {
md->tdmg += md->dmglog[0].dmg;
@@ -2203,7 +2219,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
// change experience for different sized monsters [Valaris]
if (battle_config.mob_size_influence) {
switch( md->special_state.size ) {
- case SZ_SMALL:
+ case SZ_MEDIUM:
per /= 2.;
break;
case SZ_BIG:
@@ -2246,7 +2262,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
pnum++;
flag=0;
}
- } else { //Add to total
+ } else {
+ //Add to total
if (pt[j].base_exp > UINT_MAX - base_exp)
pt[j].base_exp = UINT_MAX;
else
@@ -2324,7 +2341,7 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
// change drops depending on monsters size [Valaris]
if (battle_config.mob_size_influence)
{
- if (md->special_state.size == SZ_SMALL && drop_rate >= 2)
+ if (md->special_state.size == SZ_MEDIUM && drop_rate >= 2)
drop_rate /= 2;
else if( md->special_state.size == SZ_BIG)
drop_rate *= 2;
@@ -2445,7 +2462,8 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
timer->add(tick + (!battle_config.delay_battle_damage?500:0), mob->delay_item_drop, 0, (intptr_t)dlist);
else //No drops
ers_free(item_drop_list_ers, dlist);
- } else if (md->lootitem && md->lootitem_count) { //Loot MUST drop!
+ } else if (md->lootitem && md->lootitem_count) {
+ //Loot MUST drop!
struct item_drop_list *dlist = ers_alloc(item_drop_list_ers, struct item_drop_list);
dlist->m = md->bl.m;
dlist->x = md->bl.x;
@@ -2540,9 +2558,10 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) {
logs->mvpdrop(mvp_sd, md->class_, log_mvp);
}
- if (type&2 && !sd && md->class_ == MOBID_EMPERIUM && md->guardian_data)
- //Emperium destroyed by script. Discard mvp character. [Skotlex]
+ if (type&2 && !sd && md->class_ == MOBID_EMPERIUM && md->guardian_data) {
+ //Emperium destroyed by script. Discard mvp character. [Skotlex]
mvp_sd = NULL;
+ }
rebirth = ( md->sc.data[SC_KAIZEL] || (md->sc.data[SC_REBIRTH] && !md->state.rebirth) );
if( !rebirth ) { // Only trigger event on final kill
@@ -2640,10 +2659,10 @@ 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]
+ memset(md->dmglog, 0, sizeof(md->dmglog)); // Reset the damage done on the rebirthed monster, otherwise will grant full exp + damage done. [Valaris]
md->tdmg = 0;
if (!md->bl.prev)
map->addblock(&md->bl);
@@ -2662,8 +2681,8 @@ int mob_guardian_guildchange(struct mob_data *md)
if (!md->guardian_data)
return 0;
- if( md->guardian_data->castle->guild_id == 0 )
- { //Castle with no owner? Delete the guardians.
+ if (md->guardian_data->castle->guild_id == 0) {
+ //Castle with no owner? Delete the guardians.
if( md->class_ == MOBID_EMPERIUM ) //But don't delete the emperium, just clear it's guild-data
md->guardian_data->g = NULL;
else {
@@ -2675,8 +2694,8 @@ int mob_guardian_guildchange(struct mob_data *md)
}
g = guild->search(md->guardian_data->castle->guild_id);
- if( g == NULL )
- { //Properly remove guardian info from Castle data.
+ if (g == NULL) {
+ //Properly remove guardian info from Castle data.
ShowError("mob_guardian_guildchange: New Guild (id %d) does not exists!\n", md->guardian_data->castle->guild_id);
if (md->guardian_data->number >= 0 && md->guardian_data->number < MAX_GUARDIANS)
guild->castledatasave(md->guardian_data->castle->castle_id, 10+md->guardian_data->number, 0);
@@ -2700,7 +2719,7 @@ int mob_random_class (int *value, size_t count)
if (count < 1) {
count = 0;
while(count < 5 && mob->db_checkid(value[count])) count++;
- if(count < 1) // nothing found
+ if(count < 1) // nothing found
return 0;
} else {
// check if at least the first value is valid
@@ -2925,8 +2944,7 @@ int mob_summonslave(struct mob_data *md2,int *value,int amount,uint16 skill_id)
md->status.hp = md->status.max_hp*hp_rate/100;
//Inherit the aggressive mode of the master.
- if (battle_config.slaves_inherit_mode && md->master_id)
- {
+ if (battle_config.slaves_inherit_mode && md->master_id) {
switch (battle_config.slaves_inherit_mode) {
case 1: //Always aggressive
if (!(md->status.mode&MD_AGGRESSIVE))
@@ -3072,7 +3090,6 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
struct block_list *bl;
struct mob_data *fmd = NULL;
int i,j,n;
- short skill_target;
nullpo_ret(md);
nullpo_ret(ms = md->db->skill);
@@ -3117,16 +3134,16 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
{
case MSC_ALWAYS:
flag = 1; break;
- case MSC_MYHPLTMAXRATE: // HP< maxhp%
+ case MSC_MYHPLTMAXRATE: // HP< maxhp%
flag = get_percentage(md->status.hp, md->status.max_hp);
flag = (flag <= c2);
- break;
+ break;
case MSC_MYHPINRATE:
flag = get_percentage(md->status.hp, md->status.max_hp);
flag = (flag >= c2 && flag <= ms[i].val[0]);
break;
- case MSC_MYSTATUSON: // status[num] on
- case MSC_MYSTATUSOFF: // status[num] off
+ case MSC_MYSTATUSON: // status[num] on
+ case MSC_MYSTATUSOFF: // status[num] off
if (!md->sc.count) {
flag = 0;
} else if (ms[i].cond2 == -1) {
@@ -3137,26 +3154,26 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
flag = (md->sc.data[ms[i].cond2]!=NULL);
}
flag ^= (ms[i].cond1 == MSC_MYSTATUSOFF); break;
- case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
+ case MSC_FRIENDHPLTMAXRATE: // friend HP < maxhp%
flag = ((fbl = mob->getfriendhprate(md, 0, ms[i].cond2)) != NULL); break;
- case MSC_FRIENDHPINRATE :
+ case MSC_FRIENDHPINRATE:
flag = ((fbl = mob->getfriendhprate(md, ms[i].cond2, ms[i].val[0])) != NULL); break;
- case MSC_FRIENDSTATUSON: // friend status[num] on
- case MSC_FRIENDSTATUSOFF: // friend status[num] off
+ case MSC_FRIENDSTATUSON: // friend status[num] on
+ case MSC_FRIENDSTATUSOFF: // friend status[num] off
flag = ((fmd = mob->getfriendstatus(md, ms[i].cond1, ms[i].cond2)) != NULL); break;
- case MSC_SLAVELT: // slave < num
+ case MSC_SLAVELT: // slave < num
flag = (mob->countslave(&md->bl) < c2 ); break;
- case MSC_ATTACKPCGT: // attack pc > num
+ case MSC_ATTACKPCGT: // attack pc > num
flag = (unit->counttargeted(&md->bl) > c2); break;
- case MSC_SLAVELE: // slave <= num
+ case MSC_SLAVELE: // slave <= num
flag = (mob->countslave(&md->bl) <= c2 ); break;
- case MSC_ATTACKPCGE: // attack pc >= num
+ case MSC_ATTACKPCGE: // attack pc >= num
flag = (unit->counttargeted(&md->bl) >= c2); break;
case MSC_AFTERSKILL:
flag = (md->ud.skill_id == c2); break;
case MSC_RUDEATTACKED:
flag = (md->state.attacked_count >= RUDE_ATTACKED_COUNT);
- if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
+ if (flag) md->state.attacked_count = 0; //Rude attacked count should be reset after the skill condition is met. Thanks to Komurka [Skotlex]
break;
case MSC_MASTERHPLTMAXRATE:
flag = ((fbl = mob->getmasterhpltmaxrate(md, ms[i].cond2)) != NULL); break;
@@ -3171,12 +3188,10 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
if (!flag)
continue; //Skill requisite failed to be fulfilled.
-
//Execute skill
- skill_target = (md->db->status.mode&MD_RANDOMTARGET)? MST_RANDOM : ms[i].target;
if (skill->get_casttype(ms[i].skill_id) == CAST_GROUND) {//Ground skill.
short x, y;
- switch (skill_target) {
+ switch (ms[i].target) {
case MST_RANDOM: //Pick a random enemy within skill range.
bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),
skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv));
@@ -3204,12 +3219,12 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
if (!bl) continue;
x = bl->x;
- y = bl->y;
+ y = bl->y;
// Look for an area to cast the spell around...
- if (skill_target >= MST_AROUND1 || skill_target >= MST_AROUND5) {
- j = skill_target >= MST_AROUND1?
- (skill_target-MST_AROUND1) +1:
- (skill_target-MST_AROUND5) +1;
+ if (ms[i].target >= MST_AROUND1 || ms[i].target >= MST_AROUND5) {
+ j = ms[i].target >= MST_AROUND1?
+ (ms[i].target-MST_AROUND1) +1:
+ (ms[i].target-MST_AROUND5) +1;
map->search_freecell(&md->bl, md->bl.m, &x, &y, j, j, 3);
}
md->skill_idx = i;
@@ -3222,7 +3237,7 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
}
} else {
//Targeted skill
- switch (skill_target) {
+ switch (ms[i].target) {
case MST_RANDOM: //Pick a random enemy within skill range.
bl = battle->get_enemy(&md->bl, DEFAULT_ENEMY_TYPE(md),
skill->get_range2(&md->bl, ms[i].skill_id, ms[i].skill_lv));
@@ -3263,10 +3278,10 @@ int mobskill_use(struct mob_data *md, int64 tick, int event) {
if ( ms[ i ].msg_id ){ //Display color message [SnakeDrak]
struct mob_chat *mc = mob->chat(ms[i].msg_id);
char temp[CHAT_SIZE_MAX];
- char name[NAME_LENGTH];
- snprintf(name, sizeof name,"%s", md->name);
- strtok(name, "#"); // discard extra name identifier if present [Daegaladh]
- snprintf(temp, sizeof temp,"%s : %s", name, mc->msg);
+ char name[NAME_LENGTH];
+ snprintf(name, sizeof name,"%s", md->name);
+ strtok(name, "#"); // discard extra name identifier if present [Daegaladh]
+ snprintf(temp, sizeof temp,"%s : %s", name, mc->msg);
clif->messagecolor(&md->bl, mc->color, temp);
}
if(!(battle_config.mob_ai&0x200)) { //pass on delay to same skill.
@@ -3508,7 +3523,7 @@ int mob_clone_spawn(struct map_session_data *sd, int16 m, int16 x, int16 y, cons
sd->fd = fd;
//Finally, spawn it.
- md = mob->once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, m, x, y, "--en--", class_, event, SZ_SMALL, AI_NONE);
if (!md) return 0; //Failed?
md->special_state.clone = 1;
@@ -3536,8 +3551,7 @@ int mob_clone_delete(struct mob_data *md)
const int class_ = md->class_;
if (class_ >= MOB_CLONE_START && class_ < MOB_CLONE_END
&& mob->db_data[class_]!=NULL) {
- aFree(mob->db_data[class_]);
- mob->db_data[class_]=NULL;
+ mob->destroy_mob_db(class_);
//Clear references to the db
md->db = mob->dummy;
md->vd = NULL;
@@ -3558,10 +3572,9 @@ int mob_makedummymobdb(int class_)
{
if (mob->db(class_) == mob->dummy)
return 1; //Using the mob->dummy data already. [Skotlex]
- if (class_ > 0 && class_ <= MAX_MOB_DB)
- { //Remove the mob data so that it uses the dummy data instead.
- aFree(mob->db_data[class_]);
- mob->db_data[class_] = NULL;
+ if (class_ > 0 && class_ <= MAX_MOB_DB) {
+ //Remove the mob data so that it uses the dummy data instead.
+ mob->destroy_mob_db(class_);
}
return 0;
}
@@ -3701,7 +3714,12 @@ bool mob_parse_dbrow(char** str) {
mstatus->int_ = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[17]));
mstatus->dex = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[18]));
mstatus->luk = mob_parse_dbrow_cap_value(class_,UINT16_MIN,UINT16_MAX,atoi(str[19]));
-
+
+ /*
+ * Disabled for renewal since difference of 0 and 1 still has an impact in the formulas
+ * Just in case there is a mishandled division by zero please let us know. [malufett]
+ */
+#ifndef RENEWAL
//All status should be min 1 to prevent divisions by zero from some skills. [Skotlex]
if (mstatus->str < 1) mstatus->str = 1;
if (mstatus->agi < 1) mstatus->agi = 1;
@@ -3709,6 +3727,11 @@ bool mob_parse_dbrow(char** str) {
if (mstatus->int_< 1) mstatus->int_= 1;
if (mstatus->dex < 1) mstatus->dex = 1;
if (mstatus->luk < 1) mstatus->luk = 1;
+#endif
+
+ //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]);
@@ -3818,8 +3841,8 @@ bool mob_parse_dbrow(char** str) {
id = itemdb->search(db->dropitem[i].nameid);
type = id->type;
rate = atoi(str[k+1]);
- if( (class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946) )
- { //Treasure box drop rates [Skotlex]
+ if( (class_ >= 1324 && class_ <= 1363) || (class_ >= 1938 && class_ <= 1946) ) {
+ //Treasure box drop rates [Skotlex]
rate_adjust = battle_config.item_rate_treasure;
ratemin = battle_config.item_drop_treasure_min;
ratemax = battle_config.item_drop_treasure_max;
@@ -3919,7 +3942,13 @@ void mob_readdb(void) {
* mob_db table reading
*------------------------------------------*/
int mob_read_sqldb(void) {
- const char* mob_db_name[] = { map->mob_db_db, map->mob_db2_db };
+ const char* mob_db_name[] = {
+#ifdef RENEWAL
+ map->mob_db_re_db
+#else
+ map->mob_db_db
+#endif
+ , map->mob_db2_db };
int fi;
for( fi = 0; fi < ARRAYLENGTH(mob_db_name); ++fi ) {
@@ -3989,8 +4018,8 @@ bool mob_readdb_mobavail(char* str[], int columns, int current)
class_=atoi(str[0]);
- if(mob->db(class_) == mob->dummy) // invalid class (probably undefined in db)
- {
+ if(mob->db(class_) == mob->dummy) {
+ // invalid class (probably undefined in db)
ShowWarning("mob_readdb_mobavail: Unknown mob id %d.\n", class_);
return false;
}
@@ -4041,7 +4070,7 @@ int mob_read_randommonster(void)
for( i = 0; i < ARRAYLENGTH(mobfile) && i < MAX_RANDOMMONSTER; i++ ) {
unsigned int count = 0;
- mob->db_data[0]->summonper[i] = 1002; // Default fallback value, in case the database does not provide one
+ mob->db_data[0]->summonper[i] = 1002; // Default fallback value, in case the database does not provide one
sprintf(line, "%s/%s", map->db_path, mobfile[i]);
fp=fopen(line,"r");
if(fp==NULL){
@@ -4208,16 +4237,16 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
char str[32];
enum MobSkillState id;
} state[] = {
- { "any", MSS_ANY }, //All states except Dead
- { "idle", MSS_IDLE },
- { "walk", MSS_WALK },
- { "loot", MSS_LOOT },
- { "dead", MSS_DEAD },
- { "attack", MSS_BERSERK }, //Retaliating attack
- { "angry", MSS_ANGRY }, //Preemptive attack (aggressive mobs)
- { "chase", MSS_RUSH }, //Chase escaping target
- { "follow", MSS_FOLLOW }, //Preemptive chase (aggressive mobs)
- { "anytarget",MSS_ANYTARGET }, //Berserk+Angry+Rush+Follow
+ { "any", MSS_ANY }, //All states except Dead
+ { "idle", MSS_IDLE },
+ { "walk", MSS_WALK },
+ { "loot", MSS_LOOT },
+ { "dead", MSS_DEAD },
+ { "attack", MSS_BERSERK }, //Retaliating attack
+ { "angry", MSS_ANGRY }, //Preemptive attack (aggressive mobs)
+ { "chase", MSS_RUSH }, //Chase escaping target
+ { "follow", MSS_FOLLOW }, //Preemptive chase (aggressive mobs)
+ { "anytarget", MSS_ANYTARGET }, //Berserk+Angry+Rush+Follow
};
static const struct {
char str[32];
@@ -4247,33 +4276,33 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
{ "alchemist", MSC_ALCHEMIST },
{ "onspawn", MSC_SPAWN },
}, cond2[] ={
- { "anybad", -1 },
- { "stone", SC_STONE },
- { "freeze", SC_FREEZE },
- { "stun", SC_STUN },
- { "sleep", SC_SLEEP },
- { "poison", SC_POISON },
- { "curse", SC_CURSE },
- { "silence", SC_SILENCE },
- { "confusion", SC_CONFUSION },
- { "blind", SC_BLIND },
- { "hiding", SC_HIDING },
- { "sight", SC_SIGHT },
+ { "anybad", -1 },
+ { "stone", SC_STONE },
+ { "freeze", SC_FREEZE },
+ { "stun", SC_STUN },
+ { "sleep", SC_SLEEP },
+ { "poison", SC_POISON },
+ { "curse", SC_CURSE },
+ { "silence", SC_SILENCE },
+ { "confusion", SC_CONFUSION },
+ { "blind", SC_BLIND },
+ { "hiding", SC_HIDING },
+ { "sight", SC_SIGHT },
}, target[] = {
- { "target", MST_TARGET },
- { "randomtarget", MST_RANDOM },
- { "self", MST_SELF },
- { "friend", MST_FRIEND },
- { "master", MST_MASTER },
- { "around5", MST_AROUND5 },
- { "around6", MST_AROUND6 },
- { "around7", MST_AROUND7 },
- { "around8", MST_AROUND8 },
- { "around1", MST_AROUND1 },
- { "around2", MST_AROUND2 },
- { "around3", MST_AROUND3 },
- { "around4", MST_AROUND4 },
- { "around", MST_AROUND },
+ { "target", MST_TARGET },
+ { "randomtarget", MST_RANDOM },
+ { "self", MST_SELF },
+ { "friend", MST_FRIEND },
+ { "master", MST_MASTER },
+ { "around5", MST_AROUND5 },
+ { "around6", MST_AROUND6 },
+ { "around7", MST_AROUND7 },
+ { "around8", MST_AROUND8 },
+ { "around1", MST_AROUND1 },
+ { "around2", MST_AROUND2 },
+ { "around3", MST_AROUND3 },
+ { "around4", MST_AROUND4 },
+ { "around", MST_AROUND },
};
static int last_mob_id = 0; // ensures that only one error message per mob id is printed
@@ -4300,8 +4329,8 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
return true;
}
- if (mob_id < 0)
- { //Prepare global skill. [Skotlex]
+ if (mob_id < 0) {
+ //Prepare global skill. [Skotlex]
memset(&gms, 0, sizeof (struct mob_skill));
ms = &gms;
} else {
@@ -4412,8 +4441,8 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
ms->val[1] = 0;
ms->val[4] = 1; //request to return mode to normal.
}
- if(ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1])
- { //Adds a mode to the mob.
+ if (ms->skill_id == NPC_EMOTION_ON && mob_id>0 && ms->val[1]) {
+ //Adds a mode to the mob.
//Remove aggressive mode when the new mob type is passive.
if (!(ms->val[1]&MD_AGGRESSIVE))
ms->val[3]|=MD_AGGRESSIVE;
@@ -4431,8 +4460,8 @@ bool mob_parse_row_mobskilldb(char** str, int columns, int current)
else
ms->msg_id=0;
- if (mob_id < 0)
- { //Set this skill to ALL mobs. [Skotlex]
+ if (mob_id < 0) {
+ //Set this skill to ALL mobs. [Skotlex]
mob_id *= -1;
for (i = 1; i < MAX_MOB_DB; i++)
{
@@ -4492,7 +4521,13 @@ void mob_readskilldb(void) {
* seems to work though...
*/
int mob_read_sqlskilldb(void) {
- const char* mob_skill_db_name[] = { map->mob_skill_db_db, map->mob_skill_db2_db };
+ const char* mob_skill_db_name[] = {
+#ifdef RENEWAL
+ map->mob_skill_db_re_db
+#else
+ map->mob_skill_db_db
+#endif
+ , map->mob_skill_db2_db };
int fi;
if( battle_config.mob_skill_rate == 0 ) {
@@ -4637,8 +4672,11 @@ void mob_reload(void) {
mob->load(false);
}
+/**
+ * Clears spawn related information for a script reload.
+ */
void mob_clear_spawninfo()
-{ //Clears spawn related information for a script reload.
+{
int i;
for (i = 0; i < MAX_MOB_DB; i++)
if (mob->db_data[i])
@@ -4674,6 +4712,22 @@ int do_init_mob(bool minimal) {
return 0;
}
+void mob_destroy_mob_db(int index)
+{
+ struct mob_db *data = mob->db_data[index];
+ int v;
+ for (v = 0; v < data->hdatac; v++ ) {
+ if (data->hdata[v]->flag.free ) {
+ aFree(data->hdata[v]->data);
+ }
+ aFree(data->hdata[v]);
+ }
+ if (data->hdata)
+ aFree(data->hdata);
+ aFree(data);
+ mob->db_data[index] = NULL;
+}
+
/*==========================================
* Clean memory usage.
*------------------------------------------*/
@@ -4689,8 +4743,7 @@ int do_final_mob(void)
{
if (mob->db_data[i] != NULL)
{
- aFree(mob->db_data[i]);
- mob->db_data[i] = NULL;
+ mob->destroy_mob_db(i);
}
}
for (i = 0; i <= MAX_MOB_CHAT; i++)
@@ -4825,4 +4878,5 @@ void mob_defaults(void) {
mob->readdb_itemratio = mob_readdb_itemratio;
mob->load = mob_load;
mob->clear_spawninfo = mob_clear_spawninfo;
+ mob->destroy_mob_db = mob_destroy_mob_db;
}
diff --git a/src/map/mob.h b/src/map/mob.h
index c8d43dbb2..9aac2c664 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
@@ -40,6 +42,15 @@
#define MAX_MOB_CHAT 250 //Max Skill's messages
+// On official servers, monsters will only seek targets that are closer to walk to than their
+// search range. The search range is affected depending on if the monster is walking or not.
+// On some maps there can be a quite long path for just walking two cells in a direction and
+// the client does not support displaying walk paths that are longer than 14 cells, so this
+// option reduces position lag in such situation. But doing a complex search for every possible
+// target, might be CPU intensive.
+// Disable this to make monsters not do any path search when looking for a target (old behavior).
+#define ACTIVEPATHSEARCH
+
//Mob skill states.
enum MobSkillState {
MSS_ANY = -1,
@@ -62,8 +73,8 @@ enum MobDamageLogFlag
};
enum size {
- SZ_MEDIUM = 0,
- SZ_SMALL,
+ SZ_SMALL = 0,
+ SZ_MEDIUM,
SZ_BIG,
};
@@ -104,7 +115,7 @@ struct mob_db {
unsigned int base_exp,job_exp;
unsigned int mexp;
short range2,range3;
- short race2; // celest
+ short race2; // celest
unsigned short lv;
struct { int nameid,p; } dropitem[MAX_MOB_DROP];
struct { int nameid,p; } mvpitem[MAX_MVP_DROP];
@@ -115,6 +126,10 @@ struct mob_db {
int maxskill;
struct mob_skill skill[MAX_MOBSKILL];
struct spawn_info spawn[10];
+
+ /* HPM Custom Struct */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
};
struct mob_data {
@@ -123,7 +138,7 @@ struct mob_data {
struct view_data *vd;
struct status_data status, *base_status; //Second one is in case of leveling up mobs, or tiny/large mobs.
struct status_change sc;
- struct mob_db *db; //For quick data access (saves doing mob_db(md->class_) all the time) [Skotlex]
+ struct mob_db *db; //For quick data access (saves doing mob_db(md->class_) all the time) [Skotlex]
char name[NAME_LENGTH];
struct {
unsigned int size : 2; //Small/Big monsters.
@@ -169,6 +184,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;
@@ -185,13 +201,17 @@ struct mob_data {
* MvP Tombstone NPC ID
**/
int tomb_nid;
+
+ /* HPM Custom Struct */
+ struct HPluginData **hdata;
+ unsigned int hdatac;
};
enum {
- MST_TARGET = 0,
- MST_RANDOM, //Random Target!
+ MST_TARGET = 0,
+ MST_RANDOM, //Random Target!
MST_SELF,
MST_FRIEND,
MST_MASTER,
@@ -203,9 +223,9 @@ enum {
MST_AROUND2,
MST_AROUND3,
MST_AROUND4,
- MST_AROUND = MST_AROUND4,
+ MST_AROUND = MST_AROUND4,
- MSC_ALWAYS = 0x0000,
+ MSC_ALWAYS = 0x0000,
MSC_MYHPLTMAXRATE,
MSC_MYHPINRATE,
MSC_FRIENDHPLTMAXRATE,
@@ -357,6 +377,7 @@ struct mob_interface {
bool (*readdb_itemratio) (char *str[], int columns, int current);
void (*load) (bool minimal);
void (*clear_spawninfo) ();
+ void (*destroy_mob_db) (int index);
};
struct mob_interface *mob;
diff --git a/src/map/npc.c b/src/map/npc.c
index f1c6f4fbd..8b5bbc83e 100644
--- a/src/map/npc.c
+++ b/src/map/npc.c
@@ -63,14 +63,16 @@ static struct view_data npc_viewdb2[MAX_NPC_CLASS2_END-MAX_NPC_CLASS2_START];
unsigned int npc_market_qty[MAX_INVENTORY];
static struct script_event_s
-{ //Holds pointers to the commonly executed scripts for speedup. [Skotlex]
+{
+ //Holds pointers to the commonly executed scripts for speedup. [Skotlex]
struct event_data *event[UCHAR_MAX];
const char *event_name[UCHAR_MAX];
uint8 event_count;
} script_event[NPCE_MAX];
struct view_data* npc_get_viewdata(int class_)
-{ //Returns the viewdata for normal npc classes.
+{
+ //Returns the viewdata for normal npc classes.
if( class_ == INVISIBLE_CLASS )
return &npc_viewdb[0];
if (npcdb_checkid(class_) || class_ == WARP_CLASS){
@@ -103,12 +105,12 @@ int npc_get_new_npc_id(void) {
}
int npc_isnear_sub(struct block_list* bl, va_list args) {
- struct npc_data *nd = (struct npc_data*)bl;
-
- if( nd->option & (OPTION_HIDE|OPTION_INVISIBLE) )
- return 0;
+ struct npc_data *nd = (struct npc_data*)bl;
- return 1;
+ if( nd->option & (OPTION_HIDE|OPTION_INVISIBLE) )
+ return 0;
+
+ return 1;
}
bool npc_isnear(struct block_list * bl) {
@@ -137,11 +139,22 @@ int npc_ontouch2_event(struct map_session_data *sd, struct npc_data *nd)
{
char name[EVENT_NAME_LENGTH];
- if( sd->areanpc_id == nd->bl.id )
+ if (sd->areanpc_id == nd->bl.id)
return 0;
snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.ontouch2_name);
- return npc->event(sd,name,2);
+ return npc->event(sd, name, 2);
+}
+
+int npc_onuntouch_event(struct map_session_data *sd, struct npc_data *nd)
+{
+ char name[EVENT_NAME_LENGTH];
+
+ if (sd->areanpc_id != nd->bl.id)
+ return 0;
+
+ snprintf(name, ARRAYLENGTH(name), "%s::%s", nd->exname, script->config.onuntouch_name);
+ return npc->event(sd, name, 2);
}
/*==========================================
@@ -885,9 +898,10 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
nullpo_retr(1, sd);
- // Why not enqueue it? [Inkfish]
- //if(sd->npc_id)
- // return 1;
+#if 0 // Why not enqueue it? [Inkfish]
+ if(sd->npc_id)
+ return 1;
+#endif // 0
for(i=0;i<map->list[m].npc_num;i++) {
if (map->list[m].npc[i]->option&OPTION_INVISIBLE) {
@@ -961,6 +975,23 @@ int npc_touch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
return 0;
}
+/*==========================================
+ * Exec OnUnTouch for player if out range of area event
+ *------------------------------------------*/
+int npc_untouch_areanpc(struct map_session_data* sd, int16 m, int16 x, int16 y)
+{
+ struct npc_data *nd;
+ nullpo_retr(1, sd);
+
+ if (!sd->areanpc_id)
+ return 0;
+
+ nd = (struct npc_data *) map->id2bl(sd->areanpc_id);
+ npc->onuntouch_event(sd, nd);
+ sd->areanpc_id = 0;
+ return 0;
+}
+
// OnTouch NPC or Warp for Mobs
// Return 1 if Warped
int npc_touch_areanpc2(struct mob_data *md)
@@ -1083,22 +1114,28 @@ int npc_check_areanpc(int flag, int16 m, int16 x, int16 y, int16 range) {
struct npc_data* npc_checknear(struct map_session_data* sd, struct block_list* bl)
{
struct npc_data *nd;
+ int distance = AREA_SIZE + 1;
nullpo_retr(NULL, sd);
- if(bl == NULL) return NULL;
- if(bl->type != BL_NPC) return NULL;
+ if (bl == NULL) return NULL;
+ if (bl->type != BL_NPC) return NULL;
nd = (TBL_NPC*)bl;
- if(sd->state.using_fake_npc && sd->npc_id == bl->id)
+ if (sd->npc_id == bl->id)
return nd;
if (nd->class_<0) //Class-less npc, enable click from anywhere.
return nd;
- if (bl->m!=sd->bl.m ||
- bl->x<sd->bl.x-AREA_SIZE-1 || bl->x>sd->bl.x+AREA_SIZE+1 ||
- bl->y<sd->bl.y-AREA_SIZE-1 || bl->y>sd->bl.y+AREA_SIZE+1)
+ if (distance > nd->area_size)
+ distance = nd->area_size;
+
+ if (bl->m != sd->bl.m ||
+ bl->x < sd->bl.x - distance || bl->x > sd->bl.x + distance ||
+ bl->y < sd->bl.y - distance || bl->y > sd->bl.y + distance)
+ {
return NULL;
+ }
return nd;
}
@@ -1211,7 +1248,7 @@ int npc_scriptcont(struct map_session_data* sd, int id, bool closing) {
TBL_NPC* nd = BL_CAST(BL_NPC, target);
ShowDebug("npc_scriptcont: %s (sd->npc_id=%d) is not %s (id=%d).\n",
nd_sd?(char*)nd_sd->name:"'Unknown NPC'", (int)sd->npc_id,
- nd?(char*)nd->name:"'Unknown NPC'", (int)id);
+ nd?(char*)nd->name:"'Unknown NPC'", (int)id);
return 1;
}
@@ -1270,7 +1307,7 @@ int npc_buysellsel(struct map_session_data* sd, int id, int type) {
sd->npc_id = 0;
return 1;
}
-
+
if (nd->option & OPTION_INVISIBLE) // can't buy if npc is not visible (hack?)
return 1;
@@ -1807,22 +1844,22 @@ int npc_buylist(struct map_session_data* sd, int n, unsigned short* item_list) {
return npc->buylist_sub(sd,n,item_list,nd->master_nd);
if( z > (double)sd->status.zeny )
- return 1; // Not enough Zeny
+ return 1; // Not enough Zeny
if( w + sd->weight > sd->max_weight )
- return 2; // Too heavy
+ return 2; // Too heavy
if( pc->inventoryblank(sd) < new_ )
- return 3; // Not enough space to store items
+ return 3; // Not enough space to store items
pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
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;
@@ -1920,20 +1957,19 @@ int npc_market_buylist(struct map_session_data* sd, unsigned short list_size, st
}
if( z > (double)sd->status.zeny ) /* TODO find official response for this */
- return 1; // Not enough Zeny
+ return 1; // Not enough Zeny
if( w + sd->weight > sd->max_weight ) /* TODO find official response for this */
- return 1; // Too heavy
+ return 1; // Too heavy
if( pc->inventoryblank(sd) < new_ ) /* TODO find official response for this */
- return 1; // Not enough space to store items
+ return 1; // Not enough space to store items
pc->payzeny(sd,(int)z,LOG_TYPE_NPC, NULL);
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 +1980,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;
@@ -2179,6 +2216,10 @@ int npc_unload(struct npc_data* nd, bool single) {
nullpo_ret(nd);
+ if( nd->ud && nd->ud != &npc->base_ud ) {
+ skill->clear_unitgroup(&nd->bl);
+ }
+
npc->remove_map(nd);
map->deliddb(&nd->bl);
if( single )
@@ -2216,7 +2257,7 @@ int npc_unload(struct npc_data* nd, bool single) {
npc->ev_db->foreach(npc->ev_db,npc->unload_ev,nd->exname); //Clean up all events related
npc->ev_label_db->foreach(npc->ev_label_db,npc->unload_ev_label,nd);
}
-
+
iter = mapit_geteachpc();
for( bl = (struct block_list*)mapit->first(iter); mapit->exists(iter); bl = (struct block_list*)mapit->next(iter) ) {
struct map_session_data *sd = ((TBL_PC*)bl);
@@ -2263,7 +2304,7 @@ int npc_unload(struct npc_data* nd, bool single) {
guild->flag_remove(nd);
}
- if( nd->ud != &npc->base_ud ) {
+ if( nd->ud && nd->ud != &npc->base_ud ) {
aFree(nd->ud);
nd->ud = NULL;
}
@@ -2445,7 +2486,7 @@ void npc_parsename(struct npc_data* nd, const char* name, const char* start, con
// Support for using Constants in place of NPC View IDs.
int npc_parseview(const char* w4, const char* start, const char* buffer, const char* filepath) {
int val = -1, i = 0;
- char viewid[1024]; // Max size of name from const.txt, see script->read_constdb.
+ char viewid[1024]; // Max size of name from const.txt, see script->read_constdb.
// Extract view ID / constant
while (w4[i] != '\0') {
@@ -2485,7 +2526,22 @@ bool npc_viewisid(const char * viewid)
}
}
- return true;
+ return true;
+}
+
+struct npc_data* npc_create_npc(int m, int x, int y)
+{
+ struct npc_data *nd;
+
+ CREATE(nd, struct npc_data, 1);
+ nd->bl.id = npc->get_new_npc_id();
+ nd->bl.prev = nd->bl.next = NULL;
+ nd->bl.m = m;
+ nd->bl.x = x;
+ nd->bl.y = y;
+ nd->area_size = AREA_SIZE + 1;
+
+ return nd;
}
//Add then display an npc warp on map
@@ -2493,13 +2549,8 @@ struct npc_data* npc_add_warp(char* name, short from_mapid, short from_x, short
int i, flag = 0;
struct npc_data *nd;
- CREATE(nd, struct npc_data, 1);
- nd->bl.id = npc->get_new_npc_id();
+ nd = npc->create_npc(from_mapid, from_x, from_y);
map->addnpc(from_mapid, nd);
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = from_mapid;
- nd->bl.x = from_x;
- nd->bl.y = from_y;
safestrncpy(nd->exname, name, ARRAYLENGTH(nd->exname));
if (npc->name2id(nd->exname) != NULL)
@@ -2567,14 +2618,8 @@ const char* npc_parse_warp(char* w1, char* w2, char* w3, char* w4, const char* s
return strchr(start,'\n');;//try next
}
- CREATE(nd, struct npc_data, 1);
-
- nd->bl.id = npc->get_new_npc_id();
+ nd = npc->create_npc(m, x, y);
map->addnpc(m, nd);
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
npc->parsename(nd, w3, start, buffer, filepath);
if (!battle_config.warp_point_debug)
@@ -2709,17 +2754,12 @@ const char* npc_parse_shop(char* w1, char* w2, char* w3, char* w4, const char* s
return strchr(start,'\n');// continue
}
- CREATE(nd, struct npc_data, 1);
+ nd = npc->create_npc(m, x, y);
CREATE(nd->u.shop.shop_item, struct npc_item_list, i);
memcpy(nd->u.shop.shop_item, items, sizeof(items[0])*i);
aFree(items);
nd->u.shop.count = i;
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
- nd->bl.id = npc->get_new_npc_id();
npc->parsename(nd, w3, start, buffer, filepath);
nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
@@ -2835,7 +2875,7 @@ const char* npc_skip_script(const char* start, const char* buffer, const char* f
/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,{<code>}
/// <map name>,<x>,<y>,<facing>%TAB%script%TAB%<NPC Name>%TAB%<sprite id>,<triggerX>,<triggerY>,{<code>}
const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int options, int *retval) {
- int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov
+ int x, y, dir = 0, m, xs = 0, ys = 0; // [Valaris] thanks to fov
char mapname[32];
struct script_code *scriptroot;
int i;
@@ -2883,8 +2923,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
npc->convertlabel_db(label_list,filepath);
}
- CREATE(nd, struct npc_data, 1);
-
+ nd = npc->create_npc(m, x, y);
if( sscanf(w4, "%*[^,],%d,%d", &xs, &ys) == 2 )
{// OnTouch area defined
nd->u.scr.xs = xs;
@@ -2896,12 +2935,7 @@ const char* npc_parse_script(char* w1, char* w2, char* w3, char* w4, const char*
nd->u.scr.ys = -1;
}
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
npc->parsename(nd, w3, start, buffer, filepath);
- nd->bl.id = npc->get_new_npc_id();
nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->u.scr.script = scriptroot;
@@ -3033,14 +3067,8 @@ const char* npc_parse_duplicate(char* w1, char* w2, char* w3, char* w4, const ch
return end;// next line, try to continue
}
- CREATE(nd, struct npc_data, 1);
-
- nd->bl.prev = nd->bl.next = NULL;
- nd->bl.m = m;
- nd->bl.x = x;
- nd->bl.y = y;
+ nd = npc->create_npc(m, x, y);
npc->parsename(nd, w3, start, buffer, filepath);
- nd->bl.id = npc->get_new_npc_id();
nd->class_ = m == -1 ? -1 : npc->parseview(w4, start, buffer, filepath);
nd->speed = 200;
nd->src_id = src_id;
@@ -3152,13 +3180,8 @@ int npc_duplicate4instance(struct npc_data *snd, int16 m) {
return 1;
}
- CREATE(wnd, struct npc_data, 1);
- wnd->bl.id = npc->get_new_npc_id();
+ wnd = npc->create_npc(m, snd->bl.x, snd->bl.y);
map->addnpc(m, wnd);
- wnd->bl.prev = wnd->bl.next = NULL;
- wnd->bl.m = m;
- wnd->bl.x = snd->bl.x;
- wnd->bl.y = snd->bl.y;
safestrncpy(wnd->name, "", ARRAYLENGTH(wnd->name));
safestrncpy(wnd->exname, newname, ARRAYLENGTH(wnd->exname));
wnd->class_ = WARP_CLASS;
@@ -3320,8 +3343,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);
@@ -3349,27 +3372,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;
@@ -3447,7 +3472,7 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
// w4=<mob id>,<amount>,<delay1>,<delay2>,<event>{,<mob size>,<mob ai>}
if( sscanf(w1, "%31[^,],%d,%d,%d,%d", mapname, &x, &y, &xs, &ys) < 3
|| sscanf(w3, "%23[^,],%d", mobname, &mob_lv) < 1
- || sscanf(w4, "%d,%d,%u,%u,%127[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2
+ || sscanf(w4, "%d,%d,%u,%u,%50[^,],%d,%d[^\t\r\n]", &class_, &num, &mobspawn.delay1, &mobspawn.delay2, mobspawn.eventname, &size, &ai) < 2
) {
ShowError("npc_parse_mob: Invalid mob definition in file '%s', line '%d'.\n * w1=%s\n * w2=%s\n * w3=%s\n * w4=%s\n", filepath, strline(buffer,start-buffer), w1, w2, w3, w4);
if (retval) *retval = EXIT_FAILURE;
@@ -3597,9 +3622,17 @@ const char* npc_parse_mob(char* w1, char* w2, char* w3, char* w4, const char* st
return strchr(start,'\n');// continue
}
+
+void npc_parse_unknown_mapflag(const char *name, char *w3, char *w4, const char* start, const char* buffer, const char* filepath, int *retval)
+{
+ ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
+ if (retval)
+ *retval = EXIT_FAILURE;
+}
+
/*==========================================
* Set or disable mapflag on map
- * eg : bat_c01 mapflag battleground 2
+ * eg : bat_c01<TAB>mapflag<TAB>battleground<TAB>2
* also chking if mapflag conflict with another
*------------------------------------------*/
const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char* start, const char* buffer, const char* filepath, int *retval) {
@@ -3623,7 +3656,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
}
if (w4 && !strcmpi(w4, "off"))
- state = 0; //Disable mapflag rather than enable it. [Skotlex]
+ state = 0; //Disable mapflag rather than enable it. [Skotlex]
if (!strcmpi(w3, "nosave")) {
char savemap[32];
@@ -3689,7 +3722,7 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
if( state && (zone = strdb_get(map->zone_db, MAP_ZONE_PVP_NAME)) && map->list[m].zone != zone ) {
map->zone_change(m,zone,start,buffer,filepath);
} else if ( !state ) {
- map->list[m].zone = &map->zone_pk;
+ map->list[m].zone = &map->zone_all;
}
}
else if (!strcmpi(w3,"pvp_noparty"))
@@ -4004,13 +4037,20 @@ const char* npc_parse_mapflag(char* w1, char* w2, char* w3, char* w4, const char
} else if ( !strcmpi(w3,"nocashshop") ) {
map->list[m].flag.nocashshop = (state) ? 1 : 0;
} else {
- ShowError("npc_parse_mapflag: unrecognized mapflag '%s' in file '%s', line '%d'.\n", w3, filepath, strline(buffer,start-buffer));
- if (retval) *retval = EXIT_FAILURE;
+ npc->parse_unknown_mapflag(mapname, w3, w4, start, buffer, filepath, retval);
}
return strchr(start,'\n');// continue
}
+const char* npc_parse_unknown_object(char *w1, char *w2, char *w3, char *w4, const char* start, const char* buffer, const char* filepath, int *retval)
+{
+ 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,start-buffer), w1, w2, w3, w4);
+ start = strchr(start,'\n');// skip and continue
+ *retval = EXIT_FAILURE;
+ return start;
+}
+
/**
* Parses a script file and creates NPCs/functions/mapflags/monsters/etc
* accordingly.
@@ -4175,9 +4215,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);
}
}
@@ -4202,25 +4239,7 @@ 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;
+ p = npc->parse_unknown_object(w1, w2, w3, w4, p, buffer, filepath, &success);
}
}
aFree(buffer);
@@ -4289,7 +4308,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
}
}
@@ -4623,6 +4642,7 @@ void npc_defaults(void) {
npc->isnear = npc_isnear;
npc->ontouch_event = npc_ontouch_event;
npc->ontouch2_event = npc_ontouch2_event;
+ npc->onuntouch_event = npc_onuntouch_event;
npc->enable_sub = npc_enable_sub;
npc->enable = npc_enable;
npc->name2id = npc_name2id;
@@ -4647,6 +4667,7 @@ void npc_defaults(void) {
npc->touch_areanpc_sub = npc_touch_areanpc_sub;
npc->touchnext_areanpc = npc_touchnext_areanpc;
npc->touch_areanpc = npc_touch_areanpc;
+ npc->untouch_areanpc = npc_untouch_areanpc;
npc->touch_areanpc2 = npc_touch_areanpc2;
npc->check_areanpc = npc_check_areanpc;
npc->checknear = npc_checknear;
@@ -4673,6 +4694,7 @@ void npc_defaults(void) {
npc->parsename = npc_parsename;
npc->parseview = npc_parseview;
npc->viewisid = npc_viewisid;
+ npc->create_npc = npc_create_npc;
npc->add_warp = npc_add_warp;
npc->parse_warp = npc_parse_warp;
npc->parse_shop = npc_parse_shop;
@@ -4692,7 +4714,9 @@ void npc_defaults(void) {
npc->parse_mob2 = npc_parse_mob2;
npc->parse_mob = npc_parse_mob;
npc->parse_mapflag = npc_parse_mapflag;
+ npc->parse_unknown_mapflag = npc_parse_unknown_mapflag;
npc->parsesrcfile = npc_parsesrcfile;
+ npc->parse_unknown_object = npc_parse_unknown_object;
npc->script_event = npc_script_event;
npc->read_event_script = npc_read_event_script;
npc->path_db_clear_sub = npc_path_db_clear_sub;
diff --git a/src/map/npc.h b/src/map/npc.h
index 4c904e1ac..a5a2b4676 100644
--- a/src/map/npc.h
+++ b/src/map/npc.h
@@ -61,7 +61,8 @@ struct npc_data {
int touching_id;
int64 next_walktime;
uint8 dir;
-
+ uint8 area_size;
+
unsigned size : 2;
struct status_data status;
@@ -181,6 +182,7 @@ struct npc_interface {
bool (*isnear) (struct block_list *bl);
int (*ontouch_event) (struct map_session_data *sd, struct npc_data *nd);
int (*ontouch2_event) (struct map_session_data *sd, struct npc_data *nd);
+ int (*onuntouch_event) (struct map_session_data *sd, struct npc_data *nd);
int (*enable_sub) (struct block_list *bl, va_list ap);
int (*enable) (const char *name, int flag);
struct npc_data* (*name2id) (const char *name);
@@ -205,6 +207,7 @@ struct npc_interface {
int (*touch_areanpc_sub) (struct block_list *bl, va_list ap);
int (*touchnext_areanpc) (struct map_session_data *sd, bool leavemap);
int (*touch_areanpc) (struct map_session_data *sd, int16 m, int16 x, int16 y);
+ int (*untouch_areanpc) (struct map_session_data *sd, int16 m, int16 x, int16 y);
int (*touch_areanpc2) (struct mob_data *md);
int (*check_areanpc) (int flag, int16 m, int16 x, int16 y, int16 range);
struct npc_data* (*checknear) (struct map_session_data *sd, struct block_list *bl);
@@ -231,9 +234,11 @@ struct npc_interface {
void (*parsename) (struct npc_data *nd, const char *name, const char *start, const char *buffer, const char *filepath);
int (*parseview) (const char *w4, const char *start, const char *buffer, const char *filepath);
bool (*viewisid) (const char *viewid);
+ struct npc_data* (*create_npc) (int m, int x, int y);
struct npc_data* (*add_warp) (char *name, short from_mapid, short from_x, short from_y, short xs, short ys, unsigned short to_mapindex, short to_x, short to_y);
const char* (*parse_warp) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
const char* (*parse_shop) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ const char* (*parse_unknown_object) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
void (*convertlabel_db) (struct npc_label_list *label_list, const char *filepath);
const char* (*skip_script) (const char *start, const char *buffer, const char *filepath, int *retval);
const char* (*parse_script) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int options, int *retval);
@@ -250,6 +255,7 @@ struct npc_interface {
void (*parse_mob2) (struct spawn_data *mobspawn);
const char* (*parse_mob) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
const char* (*parse_mapflag) (char *w1, char *w2, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
+ void (*parse_unknown_mapflag) (const char *name, char *w3, char *w4, const char *start, const char *buffer, const char *filepath, int *retval);
int (*parsesrcfile) (const char *filepath, bool runOnInit);
int (*script_event) (struct map_session_data *sd, enum npce_event type);
void (*read_event_script) (void);
diff --git a/src/map/packets.h b/src/map/packets.h
index 810f341d4..bb5222e93 100644
--- a/src/map/packets.h
+++ b/src/map/packets.h
@@ -1654,128 +1654,128 @@ packet(0x020d,-1);
packet(0x0802,18,clif->pPartyBookingRegisterReq,2,4,6); // Booking System
packet(0x0803,4);
packet(0x0804,8); // Booking System
- packet(0x0805,-1);
- packet(0x0806,4,clif->pPartyBookingDeleteReq,2);// Booking System
- //packet(0x0807,2);
- packet(0x0808,4); // Booking System
- //packet(0x0809,14);
- //packet(0x080A,50);
- //packet(0x080B,18);
- //packet(0x080C,6);
-#endif
-
- //2009-12-29aRagexeRE
+ packet(0x0805,-1);
+ packet(0x0806,4,clif->pPartyBookingDeleteReq,2);// Booking System
+ //packet(0x0807,2);
+ packet(0x0808,4); // Booking System
+ //packet(0x0809,14);
+ //packet(0x080A,50);
+ //packet(0x080B,18);
+ //packet(0x080C,6);
+#endif
+
+ //2009-12-29aRagexeRE
#if PACKETVER >= 20091229
- packet(0x0804,14,clif->pPartyBookingSearchReq,2,4,6,8,12);// Booking System
- packet(0x0806,2,clif->pPartyBookingDeleteReq,0);// Booking System
- packet(0x0807,4);
- packet(0x0808,14,clif->pPartyBookingUpdateReq,2); // Booking System
- packet(0x0809,50);
- packet(0x080A,18);
- packet(0x080B,6);// Booking System
-#endif
-
- //2010-01-05aRagexeRE
+ packet(0x0804,14,clif->pPartyBookingSearchReq,2,4,6,8,12);// Booking System
+ packet(0x0806,2,clif->pPartyBookingDeleteReq,0);// Booking System
+ packet(0x0807,4);
+ packet(0x0808,14,clif->pPartyBookingUpdateReq,2); // Booking System
+ packet(0x0809,50);
+ packet(0x080A,18);
+ packet(0x080B,6);// Booking System
+#endif
+
+ //2010-01-05aRagexeRE
#if PACKETVER >= 20100105
- packet(0x0801,-1,clif->pPurchaseReq2,2,4,8,12);
+ packet(0x0801,-1,clif->pPurchaseReq2,2,4,8,12);
#endif
-
- //2010-01-26aRagexeRE
+
+ //2010-01-26aRagexeRE
#if PACKETVER >= 20100126
- //packet(0x080C,2);
- //packet(0x080D,3);
- packet(0x080E,14);
+ //packet(0x080C,2);
+ //packet(0x080D,3);
+ packet(0x080E,14);
#endif
-
- //2010-02-09aRagexeRE
+
+ //2010-02-09aRagexeRE
#if PACKETVER >= 20100209
- //packet(0x07F0,6);
+ //packet(0x07F0,6);
#endif
-
- //2010-02-23aRagexeRE
+
+ //2010-02-23aRagexeRE
#if PACKETVER >= 20100223
- packet(0x080F,20);
+ packet(0x080F,20);
#endif
-
- //2010-03-03aRagexeRE
+
+ //2010-03-03aRagexeRE
#if PACKETVER >= 20100303
- packet(0x0810,3);
- packet(0x0811,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
- //packet(0x0812,86);
- //packet(0x0813,6);
- //packet(0x0814,6);
- //packet(0x0815,-1);
- //packet(0x0817,-1);
- //packet(0x0818,6);
- //packet(0x0819,4);
-#endif
-
- //2010-03-09aRagexeRE
+ packet(0x0810,3);
+ packet(0x0811,-1,clif->pReqOpenBuyingStore,2,4,8,9,89);
+ //packet(0x0812,86);
+ //packet(0x0813,6);
+ //packet(0x0814,6);
+ //packet(0x0815,-1);
+ //packet(0x0817,-1);
+ //packet(0x0818,6);
+ //packet(0x0819,4);
+#endif
+
+ //2010-03-09aRagexeRE
#if PACKETVER >= 20100309
- packet(0x0813,-1);
- //packet(0x0814,2);
- //packet(0x0815,6);
- packet(0x0816,6);
- packet(0x0818,-1);
- //packet(0x0819,10);
- //packet(0x081A,4);
- //packet(0x081B,4);
- //packet(0x081C,6);
- packet(0x081d,22);
- packet(0x081e,8);
-#endif
-
- //2010-03-23aRagexeRE
+ packet(0x0813,-1);
+ //packet(0x0814,2);
+ //packet(0x0815,6);
+ packet(0x0816,6);
+ packet(0x0818,-1);
+ //packet(0x0819,10);
+ //packet(0x081A,4);
+ //packet(0x081B,4);
+ //packet(0x081C,6);
+ packet(0x081d,22);
+ packet(0x081e,8);
+#endif
+
+ //2010-03-23aRagexeRE
#if PACKETVER >= 20100323
- //packet(0x081F,-1);
+ //packet(0x081F,-1);
#endif
-
- //2010-04-06aRagexeRE
+
+ //2010-04-06aRagexeRE
#if PACKETVER >= 20100406
- //packet(0x081A,6);
+ //packet(0x081A,6);
#endif
-
- //2010-04-13aRagexeRE
+
+ //2010-04-13aRagexeRE
#if PACKETVER >= 20100413
- //packet(0x081A,10);
- packet(0x0820,11);
- //packet(0x0821,2);
- //packet(0x0822,9);
- //packet(0x0823,-1);
-#endif
-
- //2010-04-14dRagexeRE
+ //packet(0x081A,10);
+ packet(0x0820,11);
+ //packet(0x0821,2);
+ //packet(0x0822,9);
+ //packet(0x0823,-1);
+#endif
+
+ //2010-04-14dRagexeRE
#if PACKETVER >= 20100414
- //packet(0x081B,8);
+ //packet(0x081B,8);
#endif
-
- //2010-04-20aRagexeRE
+
+ //2010-04-20aRagexeRE
#if PACKETVER >= 20100420
- packet(0x0812,8);
- packet(0x0814,86);
- packet(0x0815,2,clif->pReqCloseBuyingStore,0);
- packet(0x0817,6,clif->pReqClickBuyingStore,2);
- packet(0x0819,-1,clif->pReqTradeBuyingStore,2,4,8,12);
- packet(0x081a,4);
- packet(0x081b,10);
- packet(0x081c,10);
- packet(0x0824,6);
-#endif
-
- //2010-06-01aRagexeRE
+ packet(0x0812,8);
+ packet(0x0814,86);
+ packet(0x0815,2,clif->pReqCloseBuyingStore,0);
+ packet(0x0817,6,clif->pReqClickBuyingStore,2);
+ packet(0x0819,-1,clif->pReqTradeBuyingStore,2,4,8,12);
+ packet(0x081a,4);
+ packet(0x081b,10);
+ packet(0x081c,10);
+ packet(0x0824,6);
+#endif
+
+ //2010-06-01aRagexeRE
#if PACKETVER >= 20100601
- //packet(0x0825,-1);
- //packet(0x0826,4);
- packet(0x0835,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
- packet(0x0836,-1);
- packet(0x0837,3);
- //packet(0x0838,3);
-#endif
-
- //2010-06-08aRagexeRE
+ //packet(0x0825,-1);
+ //packet(0x0826,4);
+ packet(0x0835,-1,clif->pSearchStoreInfo,2,4,5,9,13,14,15);
+ packet(0x0836,-1);
+ packet(0x0837,3);
+ //packet(0x0838,3);
+#endif
+
+ //2010-06-08aRagexeRE
#if PACKETVER >= 20100608
- packet(0x0838,2,clif->pSearchStoreInfoNextPage,0);
- packet(0x083A,4); // Search Stalls Feature
+ packet(0x0838,2,clif->pSearchStoreInfoNextPage,0);
+ packet(0x083A,4); // Search Stalls Feature
packet(0x083B,2,clif->pCloseSearchStoreInfo,0);
packet(0x083C,12,clif->pSearchStoreInfoListItemClick,2,6,10);
packet(0x083D,6);
@@ -2415,7 +2415,7 @@ packet(0x020d,-1);
packet(0x0873,36,clif->pStoragePassword,0);
packet(0x097C,4,clif->pRanklist);
#endif
-
+
//2013-08-07Ragexe (Shakto)
#if PACKETVER >= 20130807
packet(0x0369,7,clif->pActionRequest,2,6);
@@ -2700,7 +2700,7 @@ packet(0x020d,-1);
#endif
// 2014-04-02gRagexe - Themon
-#if PACKETVER >= 20140402
+#if PACKETVER >= 20140402
packet(0x0946,7,clif->pActionRequest,2,6);
packet(0x0868,10,clif->pUseSkillToId,2,4,6);
packet(0x093F,5,clif->pWalkToXY,2);
@@ -2734,7 +2734,7 @@ packet(0x020d,-1);
#endif
// 2014-04-16aRagexe - Themon
-#if PACKETVER >= 20140416
+#if PACKETVER >= 20140416
packet(0x0369,7,clif->pActionRequest,2,6);
packet(0x083C,10,clif->pUseSkillToId,2,4,6);
packet(0x0437,5,clif->pWalkToXY,2);
@@ -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..71471e5c6 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
@@ -273,10 +279,10 @@ struct EQUIPITEM_INFO {
int HireExpireDate;
#endif
#if PACKETVER >= 20080102
- unsigned short bindOnEquipType;
+ unsigned short bindOnEquipType;
#endif
#if PACKETVER >= 20100629
- unsigned short wItemSpriteNumber;
+ unsigned short wItemSpriteNumber;
#endif
#if PACKETVER >= 20120925
struct {
@@ -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 {
@@ -663,7 +672,7 @@ struct packet_bgqueue_register {
struct packet_bgqueue_update_info {
short PacketType;
char bg_name[NAME_LENGTH];
- int position;
+ int position;
} __attribute__((packed));
struct packet_bgqueue_checkstate {
@@ -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..668251b5d 100644
--- a/src/map/party.c
+++ b/src/map/party.c
@@ -11,7 +11,7 @@
#include <stdlib.h>
#include <string.h>
-#include "atcommand.h" //msg_txt()
+#include "atcommand.h" //msg_txt()
#include "battle.h"
#include "clif.h"
#include "instance.h"
@@ -41,7 +41,7 @@ struct party_interface party_s;
* Used when creating/adding people to a party. [Skotlex]
*------------------------------------------*/
void party_fill_member(struct party_member* member, struct map_session_data* sd, unsigned int leader) {
- member->account_id = sd->status.account_id;
+ member->account_id = sd->status.account_id;
member->char_id = sd->status.char_id;
safestrncpy(member->name, sd->status.name, NAME_LENGTH);
member->class_ = sd->status.class_;
@@ -87,8 +87,8 @@ TBL_PC* party_sd_check(int party_id, int account_id, int char_id) {
if( sd->status.party_id == 0 )
sd->status.party_id = party_id;// auto-join if not in a party
- if (sd->status.party_id != party_id)
- { //If player belongs to a different party, kick him out.
+ if (sd->status.party_id != party_id) {
+ //If player belongs to a different party, kick him out.
intif->party_leave(party_id,account_id,char_id);
return NULL;
}
@@ -674,8 +674,8 @@ bool party_changeleader(struct map_session_data *sd, struct map_session_data *ts
if (mi == MAX_PARTY)
return false; //Shouldn't happen
- if (!p->party.member[mi].leader)
- { //Need to be a party leader.
+ if (!p->party.member[mi].leader) {
+ //Need to be a party leader.
clif->message(sd->fd, msg_txt(282));
return false;
}
@@ -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);
@@ -981,14 +979,14 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
if (p && p->party.item&2 && (first_charid || !(battle_config.party_share_type&1)))
{
//item distribution to party members.
- if (battle_config.party_share_type&2)
- { //Round Robin
+ if (battle_config.party_share_type&2) {
+ //Round Robin
TBL_PC* psd;
i = p->itemc;
do {
i++;
if (i >= MAX_PARTY)
- i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc"
+ i = 0; // reset counter to 1st person in party so it'll stop when it reaches "itemc"
if( (psd = p->data[i].sd) == NULL || sd->bl.m != psd->bl.m || pc_isdead(psd) || (battle_config.idle_no_share && pc_isidle(psd)) )
continue;
@@ -1001,9 +999,8 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
target = psd;
break;
} while (i != p->itemc);
- }
- else
- { //Random pick
+ } else {
+ //Random pick
TBL_PC* psd[MAX_PARTY];
int count = 0;
//Collect pick candidates
@@ -1015,11 +1012,12 @@ int party_share_loot(struct party_data* p, struct map_session_data* sd, struct i
}
while (count > 0) { //Pick a random member.
i = rnd()%count;
- if (pc->additem(psd[i],item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER))
- { //Discard this receiver.
+ if (pc->additem(psd[i],item_data,item_data->amount,LOG_TYPE_PICKDROP_PLAYER)) {
+ //Discard this receiver.
psd[i] = psd[count-1];
count--;
- } else { //Successful pick.
+ } else {
+ //Successful pick.
target = psd[i];
break;
}
@@ -1174,7 +1172,7 @@ void party_recruit_register(struct map_session_data *sd, short level, const char
memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH);
pb_ad->expiretime = (int)time(NULL);
- pb_ad->p_detail.level = level;
+ pb_ad->p_detail.level = level;
safestrncpy(pb_ad->p_detail.notice, notice, PB_NOTICE_LENGTH);
clif->PartyRecruitRegisterAck(sd, 0);
@@ -1187,7 +1185,7 @@ void party_recruit_register(struct map_session_data *sd, short level, const char
void party_booking_register(struct map_session_data *sd, short level, short mapid, short* job) {
#ifndef PARTY_RECRUIT
struct party_booking_ad_info *pb_ad;
- int i;
+ int i;
pb_ad = (struct party_booking_ad_info*)idb_get(party->booking_db, sd->status.char_id);
@@ -1204,7 +1202,7 @@ void party_booking_register(struct map_session_data *sd, short level, short mapi
memcpy(pb_ad->charname,sd->status.name,NAME_LENGTH);
pb_ad->expiretime = (int)time(NULL);
- pb_ad->p_detail.level = level;
+ pb_ad->p_detail.level = level;
pb_ad->p_detail.mapid = mapid;
for(i=0;i<PARTY_BOOKING_JOBS;i++)
diff --git a/src/map/party.h b/src/map/party.h
index d62db23a7..f6cd448a6 100644
--- a/src/map/party.h
+++ b/src/map/party.h
@@ -30,12 +30,12 @@ struct party_data {
short *instance;
unsigned short instances;
struct {
- unsigned monk : 1; //There's at least one monk in party?
- unsigned sg : 1; //There's at least one Star Gladiator in party?
- unsigned snovice :1; //There's a Super Novice
- unsigned tk : 1; //There's a taekwon
+ unsigned monk : 1; ///< There's at least one monk in party?
+ unsigned sg : 1; ///< There's at least one Star Gladiator in party?
+ unsigned snovice :1; ///< There's a Super Novice
+ unsigned tk : 1; ///< There's a taekwon
} state;
-
+
/* HPM Custom Struct */
struct HPluginData **hdata;
unsigned int hdatac;
@@ -46,8 +46,8 @@ struct party_data {
#ifndef PARTY_RECRUIT
struct party_booking_detail {
short level;
- short mapid;
- short job[PARTY_BOOKING_JOBS];
+ short mapid;
+ short job[PARTY_BOOKING_JOBS];
};
struct party_booking_ad_info {
@@ -87,7 +87,7 @@ struct party_interface {
struct party_data* (*searchname) (const char* str);
int (*getmemberid) (struct party_data* p, struct map_session_data* sd);
struct map_session_data* (*getavailablesd) (struct party_data *p);
-
+
int (*create) (struct map_session_data *sd,char *name, int item, int item2);
void (*created) (int account_id,int char_id,int fail,int party_id,char *name);
int (*request_info) (int party_id, int char_id);
diff --git a/src/map/path.c b/src/map/path.c
index 5a9ddf9c7..a7315da3c 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"
@@ -52,7 +53,7 @@ BHEAP_STRUCT_DECL(node_heap, struct path_node*);
/// Estimates the cost from (x0,y0) to (x1,y1).
/// This is inadmissible (overestimating) heuristic used by game client.
-#define heuristic(x0, y0, x1, y1) (MOVE_COST * (abs((x1) - (x0)) + abs((y1) - (y0)))) // Manhattan distance
+#define heuristic(x0, y0, x1, y1) (MOVE_COST * (abs((x1) - (x0)) + abs((y1) - (y0)))) // Manhattan distance
/// @}
// Translates dx,dy into walking direction
@@ -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.
@@ -444,7 +435,7 @@ unsigned int distance(int dx, int dy)
min = dy;
max = dx;
}
- // coefficients equivalent to ( 123/128 * max ) and ( 51/128 * min )
+ // coefficients equivalent to ( 123/128 * max ) and ( 51/128 * min )
return ((( max << 8 ) + ( max << 3 ) - ( max << 4 ) - ( max << 1 ) +
( min << 7 ) - ( min << 5 ) + ( min << 3 ) - ( min << 1 )) >> 8 );
#else
@@ -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 a6619fad2..e39ddbff2 100644
--- a/src/map/pc.c
+++ b/src/map/pc.c
@@ -262,9 +262,6 @@ int pc_check_banding( struct block_list *bl, va_list ap ) {
sc = status->get_sc(bl);
- if( bl == src )
- return 0;
-
if( sc && sc->data[SC_BANDING] )
{
b_sd[(*c)++] = tsd->bl.id;
@@ -391,7 +388,8 @@ int pc_setrestartvalue(struct map_session_data *sd,int type) {
bst = &sd->base_status;
st = &sd->battle_status;
- if (type&1) { //Normal resurrection
+ if (type&1) {
+ //Normal resurrection
st->hp = 1; //Otherwise status->heal may fail if dead.
status->heal(&sd->bl, bst->hp, 0, 1);
if( st->sp < bst->sp )
@@ -557,7 +555,7 @@ int pc_makesavestatus(struct map_session_data *sd)
if(!battle_config.save_clothcolor)
sd->status.clothes_color=0;
- //Only copy the Cart/Peco/Falcon options, the rest are handled via
+ //Only copy the Cart/Peco/Falcon options, the rest are handled via
//status change load/saving. [Skotlex]
#ifdef NEW_CARTS
sd->status.option = sd->sc.option&(OPTION_INVISIBLE|OPTION_FALCON|OPTION_RIDING|OPTION_DRAGON|OPTION_WUG|OPTION_WUGRIDER|OPTION_MADOGEAR);
@@ -588,7 +586,7 @@ int pc_makesavestatus(struct map_session_data *sd)
sd->status.last_point.y = sd->bl.y;
}
- if(map->list[sd->bl.m].flag.nosave || map->list[sd->bl.m].instance_id >= 0) {
+ if( ( map->list[sd->bl.m].flag.nosave && sd->state.autotrade != 2 ) || map->list[sd->bl.m].instance_id >= 0) {
struct map_data *m=&map->list[sd->bl.m];
if(m->save.map)
memcpy(&sd->status.last_point,&m->save,sizeof(sd->status.last_point));
@@ -646,12 +644,15 @@ int pc_equippoint(struct map_session_data *sd,int n)
return 0; //Not equippable by players.
ep = sd->inventory_data[n]->equip;
- if(sd->inventory_data[n]->look == W_DAGGER ||
- sd->inventory_data[n]->look == W_1HSWORD ||
- sd->inventory_data[n]->look == W_1HAXE) {
- if( (pc->checkskill(sd,AS_LEFT) > 0 ||
- (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN ||
- (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO) ) { //Kagerou and Oboro can dual wield daggers. [Rytech]
+ if (sd->inventory_data[n]->look == W_DAGGER
+ || sd->inventory_data[n]->look == W_1HSWORD
+ || sd->inventory_data[n]->look == W_1HAXE
+ ) {
+ if (pc->checkskill(sd,AS_LEFT) > 0
+ || (sd->class_&MAPID_UPPERMASK) == MAPID_ASSASSIN
+ || (sd->class_&MAPID_UPPERMASK) == MAPID_KAGEROUOBORO
+ ) {
+ //Kagerou and Oboro can dual wield daggers. [Rytech]
if( ep == EQP_HAND_R )
return EQP_ARMS;
if( ep == EQP_SHADOW_WEAPON )
@@ -756,24 +757,6 @@ int pc_setequipindex(struct map_session_data *sd)
return 0;
}
-//static int pc_isAllowedCardOn(struct map_session_data *sd,int s,int eqindex,int flag)
-//{
-// int i;
-// struct item *item = &sd->status.inventory[eqindex];
-// struct item_data *data;
-//
-// //Crafted/made/hatched items.
-// if (itemdb_isspecial(item->card[0]))
-// return 1;
-//
-// /* scan for enchant armor gems */
-// if( item->card[MAX_SLOTS - 1] && s < MAX_SLOTS - 1 )
-// s = MAX_SLOTS - 1;
-//
-// ARR_FIND( 0, s, i, item->card[i] && (data = itemdb->exists(item->card[i])) != NULL && data->flag.no_equip&flag );
-// return( i < s ) ? 0 : 1;
-//}
-
bool pc_isequipped(struct map_session_data *sd, int nameid)
{
@@ -919,6 +902,16 @@ int pc_isequip(struct map_session_data *sd,int n)
if(item->sex != 2 && sd->status.sex != item->sex)
return 0;
+ if ( item->equip & EQP_AMMO ) {
+ if ( !pc_iscarton(sd) && (sd->status.class_ == JOB_GENETIC_T || sd->status.class_ == JOB_GENETIC) ) {
+ clif->msg(sd, 0x5EF);
+ return 0;
+ }
+ if ( !pc_ismadogear(sd) && (sd->status.class_ == JOB_MECHANIC_T || sd->status.class_ == JOB_MECHANIC) ) {
+ clif->msg(sd, 0x59B);
+ return 0;
+ }
+ }
if (sd->sc.count) {
if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_NOEQUIPWEAPON]) // Also works with left-hand weapons [DracoRPG]
@@ -962,6 +955,23 @@ int pc_isequip(struct map_session_data *sd,int n)
return 0;
}
+ if ( battle_config.unequip_restricted_equipment & 1 ) {
+ int i;
+ for ( i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++ )
+ if ( map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].nameid )
+ return 0;
+ }
+
+ if ( battle_config.unequip_restricted_equipment & 2 ) {
+ if ( !itemdb_isspecial( sd->status.inventory[n].card[0] ) ) {
+ int i, slot;
+ for ( slot = 0; slot < MAX_SLOTS; slot++ )
+ for ( i = 0; i < map->list[sd->bl.m].zone->disabled_items_count; i++ )
+ if ( map->list[sd->bl.m].zone->disabled_items[i] == sd->status.inventory[n].card[slot] )
+ return 0;
+ }
+ }
+
return 1;
}
@@ -1205,8 +1215,8 @@ int pc_set_hate_mob(struct map_session_data *sd, int pos, struct block_list *bl)
int class_;
if (!sd || !bl || pos < 0 || pos > 2)
return 0;
- if (sd->hate_mob[pos] != -1)
- { //Can't change hate targets.
+ if (sd->hate_mob[pos] != -1) {
+ //Can't change hate targets.
clif->hate_info(sd, pos, sd->hate_mob[pos], 0); //Display current
return 0;
}
@@ -1324,7 +1334,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
@@ -1733,7 +1743,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;
}
@@ -1834,10 +1844,10 @@ int pc_bonus_autospell_onskill(struct s_autospell *spell, int max, short src_ski
return 0;
}
- spell[i].flag = src_skill;
- spell[i].id = id;
- spell[i].lv = lv;
- spell[i].rate = rate;
+ spell[i].flag = src_skill;
+ spell[i].id = id;
+ spell[i].lv = lv;
+ spell[i].rate = rate;
spell[i].card_id = card_id;
return 1;
}
@@ -1914,8 +1924,8 @@ int pc_bonus_item_drop(struct s_add_drop *drop, const short max, short id, short
&& race > 0
) {
drop[i].race |= race;
- if(drop[i].rate > 0 && rate > 0)
- { //Both are absolute rates.
+ if (drop[i].rate > 0 && rate > 0) {
+ //Both are absolute rates.
if (drop[i].rate < rate)
drop[i].rate = rate;
} else
@@ -2312,19 +2322,19 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
break;
}
break;
- case SP_SPEED_RATE: //Non stackable increase
+ case SP_SPEED_RATE: //Non stackable increase
if(sd->state.lr_flag != 2)
sd->bonus.speed_rate = min(sd->bonus.speed_rate, -val);
break;
- case SP_SPEED_ADDRATE: //Stackable increase
+ case SP_SPEED_ADDRATE: //Stackable increase
if(sd->state.lr_flag != 2)
sd->bonus.speed_add_rate -= val;
break;
- case SP_ASPD: //Raw increase
+ case SP_ASPD: //Raw increase
if(sd->state.lr_flag != 2)
sd->bonus.aspd_add -= 10*val;
break;
- case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone
+ case SP_ASPD_RATE: //Stackable increase - Made it linear as per rodatazone
if(sd->state.lr_flag != 2)
#ifndef RENEWAL_ASPD
bst->aspd_rate -= 10*val;
@@ -2537,7 +2547,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
if(sd->state.lr_flag != 2)
sd->bonus.magic_damage_return += val;
break;
- case SP_ALL_STATS: // [Valaris]
+ case SP_ALL_STATS: // [Valaris]
if(sd->state.lr_flag!=2) {
sd->param_bonus[SP_STR-SP_STR]+=val;
sd->param_bonus[SP_AGI-SP_STR]+=val;
@@ -2547,13 +2557,13 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
sd->param_bonus[SP_LUK-SP_STR]+=val;
}
break;
- case SP_AGI_VIT: // [Valaris]
+ case SP_AGI_VIT: // [Valaris]
if(sd->state.lr_flag!=2) {
sd->param_bonus[SP_AGI-SP_STR]+=val;
sd->param_bonus[SP_VIT-SP_STR]+=val;
}
break;
- case SP_AGI_DEX_STR: // [Valaris]
+ case SP_AGI_DEX_STR: // [Valaris]
if(sd->state.lr_flag!=2) {
sd->param_bonus[SP_AGI-SP_STR]+=val;
sd->param_bonus[SP_DEX-SP_STR]+=val;
@@ -2597,7 +2607,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) {
sd->bonus.classchange=val;
break;
case SP_LONG_ATK_RATE:
- if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses
+ if(sd->state.lr_flag != 2) //[Lupus] it should stack, too. As any other cards rate bonuses
sd->bonus.long_attack_atk_rate+=val;
break;
case SP_BREAK_WEAPON_RATE:
@@ -3106,11 +3116,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;
@@ -3924,10 +3934,10 @@ int pc_getzeny(struct map_session_data *sd,int zeny, enum e_log_pick_type type,
/**
* Searches for the specified item ID in inventory and return its inventory index.
- *
+ *
* If the item is found, the returned value is guaranteed to be a valid index
* (non-negative, smaller than MAX_INVENTORY).
- *
+ *
* @param sd Character to search on.
* @param item_id The item ID to search.
* @return the inventory index of the first instance of the requested item.
@@ -3944,14 +3954,14 @@ int pc_search_inventory(struct map_session_data *sd, int item_id) {
/*==========================================
* Attempt to add a new item to inventory.
* Return:
- 0 = success
- 1 = invalid itemid not found or negative amount
- 2 = overweight
- 3 = ?
- 4 = no free place found
- 5 = max amount reached
- 6 = ?
- 7 = stack limitation
+ * 0 = success
+ * 1 = invalid itemid not found or negative amount
+ * 2 = overweight
+ * 3 = ?
+ * 4 = no free place found
+ * 5 = max amount reached
+ * 6 = ?
+ * 7 = stack limitation
*------------------------------------------*/
int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type)
{
@@ -4064,11 +4074,11 @@ int pc_additem(struct map_session_data *sd,struct item *item_data,int amount,e_l
* Remove an item at index n from inventory by amount.
* Parameters :
* @type
- * 1 : don't notify deletion
- * 2 : don't notify weight change
+ * 1 : don't notify deletion
+ * 2 : don't notify weight change
* Return:
- * 0 = success
- * 1 = invalid itemid or negative amount
+ * 0 = success
+ * 1 = invalid itemid or negative amount
*------------------------------------------*/
int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reason, e_log_pick_type log_type)
{
@@ -4098,8 +4108,8 @@ int pc_delitem(struct map_session_data *sd,int n,int amount,int type, short reas
/*==========================================
* Attempt to drop an item.
* Return:
- * 0 = fail
- * 1 = success
+ * 0 = fail
+ * 1 = success
*------------------------------------------*/
int pc_dropitem(struct map_session_data *sd,int n,int amount)
{
@@ -4141,8 +4151,8 @@ int pc_dropitem(struct map_session_data *sd,int n,int amount)
/*==========================================
* Attempt to pick up an item.
* Return:
- * 0 = fail
- * 1 = success
+ * 0 = fail
+ * 1 = success
*------------------------------------------*/
int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
{
@@ -4155,7 +4165,10 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
nullpo_ret(fitem);
if(!check_distance_bl(&fitem->bl, &sd->bl, 2) && sd->ud.skill_id!=BS_GREED)
- return 0; // Distance is too far
+ return 0; // Distance is too far
+
+ if( pc_has_permission(sd,PC_PERM_DISABLE_PICK_UP) )
+ return 0;
if (sd->status.party_id)
p = party->search(sd->status.party_id);
@@ -4209,8 +4222,8 @@ int pc_takeitem(struct map_session_data *sd,struct flooritem_data *fitem)
/*==========================================
* Check if item is usable.
* Return:
- * 0 = no
- * 1 = yes
+ * 0 = no
+ * 1 = yes
*------------------------------------------*/
int pc_isUseitem(struct map_session_data *sd,int n)
{
@@ -4225,7 +4238,7 @@ int pc_isUseitem(struct map_session_data *sd,int n)
if( item == NULL )
return 0;
//Not consumable item
- if( item->type != IT_HEALING && item->type != IT_USABLE && item->type != IT_CASH )
+ if (!itemdb->is_item_usable(item))
return 0;
if( !item->script ) //if it has no script, you can't really consume it!
return 0;
@@ -4393,8 +4406,8 @@ int pc_isUseitem(struct map_session_data *sd,int n)
/*==========================================
* Last checks to use an item.
* Return:
- * 0 = fail
- * 1 = success
+ * 0 = fail
+ * 1 = success
*------------------------------------------*/
int pc_useitem(struct map_session_data *sd,int n) {
int64 tick = timer->gettick();
@@ -4475,7 +4488,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);
@@ -4516,7 +4529,7 @@ int pc_useitem(struct map_session_data *sd,int n) {
if( sd->inventory_data[n]->flag.delay_consume )
clif->useitemack(sd,n,amount,true);
else {
- if( sd->status.inventory[n].expire_time == 0 ) {
+ if (sd->status.inventory[n].expire_time == 0 && !(sd->inventory_data[n]->flag.keepafteruse)) {
clif->useitemack(sd,n,amount-1,true);
pc->delitem(sd,n,1,1,0,LOG_TYPE_CONSUME); // Rental Usable Items are not deleted until expiration
} else
@@ -4548,8 +4561,8 @@ int pc_useitem(struct map_session_data *sd,int n) {
/*==========================================
* Add item on cart for given index.
* Return:
- * 0 = success
- * 1 = fail
+ * 0 = success
+ * 1 = fail
*------------------------------------------*/
int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type)
{
@@ -4568,8 +4581,8 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
return 1;
}
- if( !itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd)))
- { // Check item trade restrictions [Skotlex]
+ if (!itemdb_cancartstore(item_data, pc_get_group_level(sd)) || (item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd))) {
+ // Check item trade restrictions
clif->message (sd->fd, msg_txt(264));
return 1;/* TODO: there is no official response to this? */
}
@@ -4582,7 +4595,7 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
{
ARR_FIND( 0, MAX_CART, i,
sd->status.cart[i].nameid == item_data->nameid && sd->status.cart[i].bound == item_data->bound &&
- sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
+ sd->status.cart[i].card[0] == item_data->card[0] && sd->status.cart[i].card[1] == item_data->card[1] &&
sd->status.cart[i].card[2] == item_data->card[2] && sd->status.cart[i].card[3] == item_data->card[3] );
};
@@ -4617,8 +4630,8 @@ int pc_cart_additem(struct map_session_data *sd,struct item *item_data,int amoun
/*==========================================
* Delete item on cart for given index.
* Return:
- * 0 = success
- * 1 = fail
+ * 0 = success
+ * 1 = fail
*------------------------------------------*/
int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type) {
struct item_data * data;
@@ -4646,8 +4659,8 @@ int pc_cart_delitem(struct map_session_data *sd,int n,int amount,int type,e_log_
/*==========================================
* Transfer item from inventory to cart.
* Return:
- * 0 = fail
- * 1 = succes
+ * 0 = fail
+ * 1 = succes
*------------------------------------------*/
int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
{
@@ -4673,8 +4686,8 @@ int pc_putitemtocart(struct map_session_data *sd,int idx,int amount)
/*==========================================
* Get number of item in cart.
* Return:
- -1 = itemid not found or no amount found
- x = remaining itemid on cart after get
+ * -1 = itemid not found or no amount found
+ * x = remaining itemid on cart after get
*------------------------------------------*/
int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount)
{
@@ -4692,8 +4705,8 @@ int pc_cartitem_amount(struct map_session_data* sd, int idx, int amount)
/*==========================================
* Retrieve an item at index idx from cart.
* Return:
- * 0 = player not found or (FIXME) succes (from pc->cart_delitem)
- * 1 = failure
+ * 0 = player not found or (FIXME) succes (from pc->cart_delitem)
+ * 1 = failure
*------------------------------------------*/
int pc_getitemfromcart(struct map_session_data *sd,int idx,int amount)
{
@@ -4732,7 +4745,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) {
@@ -4773,8 +4786,8 @@ int pc_show_steal(struct block_list *bl,va_list ap)
/*==========================================
* Steal an item from bl (mob).
* Return:
- * 0 = fail
- * 1 = succes
+ * 0 = fail
+ * 1 = succes
*------------------------------------------*/
int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skill_lv)
{
@@ -4800,7 +4813,7 @@ int pc_steal_item(struct map_session_data *sd,struct block_list *bl, uint16 skil
map->list[bl->m].flag.nomobloot || // check noloot map flag [Lorky]
(battle_config.skill_steal_max_tries && //Reached limit of steal attempts. [Lupus]
md->state.steal_flag++ >= battle_config.skill_steal_max_tries)
- ) { //Can't steal from
+ ) { //Can't steal from
md->state.steal_flag = UCHAR_MAX;
return 0;
}
@@ -5022,7 +5035,7 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int
vending->close(sd);
}
- if( hChSys.local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id) ) {
+ if (clif->hChSys->local && map->list[sd->bl.m].channel && idb_exists(map->list[sd->bl.m].channel->users, sd->status.char_id)) {
clif->chsys_left(map->list[sd->bl.m].channel,sd);
}
}
@@ -5119,8 +5132,8 @@ int pc_setpos(struct map_session_data* sd, unsigned short map_index, int x, int
* Warp player sd to random location on current map.
* May fail if no walkable cell found (1000 attempts).
* Return:
- * 0 = fail or FIXME success (from pc->setpos)
- * x(1|2) = fail
+ * 0 = fail or FIXME success (from pc->setpos)
+ * x(1|2) = fail
*------------------------------------------*/
int pc_randomwarp(struct map_session_data *sd, clr_type type) {
int x,y,i=0;
@@ -5240,7 +5253,7 @@ int pc_checkskill2(struct map_session_data *sd,uint16 index) {
* Chk if we still have the correct weapon to continue the skill (actually status)
* If not ending it
* Return
- * 0 - No status found or all done
+ * 0 - No status found or all done
*------------------------------------------*/
int pc_checkallowskill(struct map_session_data *sd)
{
@@ -5736,7 +5749,7 @@ const char* job_name(int class_)
case JOB_ARCH_BISHOP_T: // 659
case JOB_MECHANIC_T: // 660
case JOB_GUILLOTINE_CROSS_T: // 661
- return msg_txt(656 - JOB_RUNE_KNIGHT_T+class_);
+ return msg_txt(656 - JOB_RUNE_KNIGHT_T+class_);
case JOB_ROYAL_GUARD: // 631
case JOB_SORCERER: // 632
@@ -5754,7 +5767,7 @@ const char* job_name(int class_)
case JOB_SURA_T: // 666
case JOB_GENETIC_T: // 667
case JOB_SHADOW_CHASER_T: // 668
- return msg_txt(662 - JOB_ROYAL_GUARD_T+class_);
+ return msg_txt(662 - JOB_ROYAL_GUARD_T+class_);
case JOB_RUNE_KNIGHT2:
return msg_txt(625);
@@ -5856,7 +5869,7 @@ int pc_follow_timer(int tid, int64 tick, int id, intptr_t data) {
pc->setpos(sd, map_id2index(tbl->m), tbl->x, tbl->y, CLR_TELEPORT);
}
sd->followtimer = timer->add(
- tick + 1000, // increase time a bit to loosen up map's load
+ tick + 1000, // increase time a bit to loosen up map's load
pc->follow_timer, sd->bl.id, 0);
return 0;
}
@@ -5908,7 +5921,7 @@ int pc_checkbaselevelup(struct map_session_data *sd) {
} while ((next=pc->nextbaseexp(sd)) > 0 && sd->status.base_exp >= next);
- if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level
+ if (battle_config.pet_lv_rate && sd->pd) //<Skotlex> update pet's level
status_calc_pet(sd->pd,SCO_NONE);
clif->updatestatus(sd,SP_STATUSPOINT);
@@ -6033,6 +6046,9 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
if(!battle_config.pvp_exp && map->list[sd->bl.m].flag.pvp) // [MouseJstr]
return false; // no exp on pvp maps
+ if( pc_has_permission(sd,PC_PERM_DISABLE_EXP) )
+ return false;
+
if(sd->status.guild_id>0)
base_exp-=guild->payexp(sd,base_exp);
@@ -6107,12 +6123,12 @@ bool pc_gainexp(struct map_session_data *sd, struct block_list *src, unsigned in
*------------------------------------------*/
unsigned int pc_maxbaselv(struct map_session_data *sd)
{
- return pc->max_level[pc->class2idx(sd->status.class_)][0];
+ return pc->max_level[pc->class2idx(sd->status.class_)][0];
}
unsigned int pc_maxjoblv(struct map_session_data *sd)
{
- return pc->max_level[pc->class2idx(sd->status.class_)][1];
+ return pc->max_level[pc->class2idx(sd->status.class_)][1];
}
/*==========================================
@@ -6143,8 +6159,8 @@ unsigned int pc_thisbaseexp(struct map_session_data *sd)
/*==========================================
* job level exp lookup
* Return:
- * 0 = not found
- * x = exp for level
+ * 0 = not found
+ * x = exp for level
*------------------------------------------*/
//Job exp needed for next level.
@@ -6468,7 +6484,7 @@ int pc_allskillup(struct map_session_data *sd)
continue; //Cannot be learned normally.
sd->status.skill[idx].id = id;
- sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
+ sd->status.skill[idx].lv = skill->tree_get_max(id, sd->status.class_); // celest
}
}
status_calc_pc(sd,SCO_NONE);
@@ -6506,7 +6522,7 @@ int pc_resetlvl(struct map_session_data* sd,int type)
sd->status.dex=1;
sd->status.luk=1;
if(sd->status.class_ == JOB_NOVICE_HIGH) {
- sd->status.status_point=100; // not 88 [celest]
+ sd->status.status_point=100; // not 88 [celest]
// give platinum skills upon changing
pc->skill(sd,142,1,0);
pc->skill(sd,143,1,0);
@@ -6545,12 +6561,12 @@ int pc_resetlvl(struct map_session_data* sd,int type)
clif->updatestatus(sd,SP_NEXTJOBEXP);
clif->updatestatus(sd,SP_SKILLPOINT);
- clif->updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris
+ clif->updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris
clif->updatestatus(sd,SP_UAGI);
clif->updatestatus(sd,SP_UVIT);
clif->updatestatus(sd,SP_UINT);
clif->updatestatus(sd,SP_UDEX);
- clif->updatestatus(sd,SP_ULUK); // End Addition
+ clif->updatestatus(sd,SP_ULUK); // End Addition
for(i=0;i<EQI_MAX;i++) { // unequip items that can't be equipped by base 1 [Valaris]
if(sd->equip_index[i] >= 0)
@@ -6573,10 +6589,10 @@ int pc_resetstate(struct map_session_data* sd)
{
nullpo_ret(sd);
- if (battle_config.use_statpoint_table)
- { // New statpoint table used here - Dexity
- if (sd->status.base_level > MAX_LEVEL)
- { //pc->statp[] goes out of bounds, can't reset!
+ if (battle_config.use_statpoint_table) {
+ // New statpoint table used here - Dexity
+ if (sd->status.base_level > MAX_LEVEL) {
+ //pc->statp[] goes out of bounds, can't reset!
ShowError("pc_resetstate: Can't reset stats of %d:%d, the base level (%d) is greater than the max level supported (%d)\n",
sd->status.account_id, sd->status.char_id, sd->status.base_level, MAX_LEVEL);
return 0;
@@ -6611,12 +6627,12 @@ int pc_resetstate(struct map_session_data* sd)
clif->updatestatus(sd,SP_DEX);
clif->updatestatus(sd,SP_LUK);
- clif->updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris
+ clif->updatestatus(sd,SP_USTR); // Updates needed stat points - Valaris
clif->updatestatus(sd,SP_UAGI);
clif->updatestatus(sd,SP_UVIT);
clif->updatestatus(sd,SP_UINT);
clif->updatestatus(sd,SP_UDEX);
- clif->updatestatus(sd,SP_ULUK); // End Addition
+ clif->updatestatus(sd,SP_ULUK); // End Addition
clif->updatestatus(sd,SP_STATUSPOINT);
@@ -6974,7 +6990,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
sd->st->state = END;
}
- /* e.g. not killed thru pc->damage */
+ /* e.g. not killed through pc->damage */
if( pc_issit(sd) ) {
clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT);
}
@@ -6988,23 +7004,23 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
//Reset ticks.
sd->hp_loss.tick = sd->sp_loss.tick = sd->hp_regen.tick = sd->sp_regen.tick = 0;
- if ( sd && sd->spiritball )
- pc->delspiritball(sd,sd->spiritball,0);
-
- for(i = 1; i < 5; i++)
- pc->del_charm(sd, sd->charm[i], i);
+ if ( sd->spiritball )
+ pc->delspiritball(sd, sd->spiritball, 0);
+ for ( i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++ )
+ pc->del_charm(sd, sd->spiritcharm[i], i);
if (src) {
switch (src->type) {
case BL_MOB:
{
struct mob_data *md=(struct mob_data *)src;
- if(md->target_id==sd->bl.id)
+ if (md->target_id==sd->bl.id)
mob->unlocktarget(md,tick);
- if(battle_config.mobs_level_up && md->status.hp &&
- (unsigned int)md->level < pc->maxbaselv(sd) &&
- !md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex]
- ) { // monster level up [Valaris]
+ if (battle_config.mobs_level_up && md->status.hp
+ && (unsigned int)md->level < pc->maxbaselv(sd)
+ && !md->guardian_data && !md->special_state.ai// Guardians/summons should not level. [Skotlex]
+ ) {
+ // monster level up [Valaris]
clif->misceffect(&md->bl,0);
md->level++;
status_calc_mob(md, SCO_NONE);
@@ -7046,19 +7062,20 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
// karma going down = more 'good' / more honourable.
// The Karma System way...
- if (sd->status.karma > ssd->status.karma) { // If player killed was more evil
+ if (sd->status.karma > ssd->status.karma) {
+ // If player killed was more evil
sd->status.karma--;
ssd->status.karma--;
}
- else if (sd->status.karma < ssd->status.karma) // If player killed was more good
+ else if (sd->status.karma < ssd->status.karma) // If player killed was more good
ssd->status.karma++;
// or the PK System way...
- if (sd->status.karma > 0) // player killed is dishonourable?
+ if (sd->status.karma > 0) // player killed is dishonourable?
ssd->status.karma--; // honour points earned
- sd->status.karma++; // honour points lost
+ sd->status.karma++; // honour points lost
// To-do: Receive exp on certain occasions
#endif
@@ -7116,7 +7133,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
if(base_penalty) {
- if (battle_config.pk_mode && src && src->type==BL_PC)
+ if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
if( sd->status.mod_death != 100 )
base_penalty = base_penalty * sd->status.mod_death / 100;
@@ -7138,7 +7155,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) {
}
if(base_penalty) {
- if (battle_config.pk_mode && src && src->type==BL_PC)
+ if (battle_config.pk_mode && src && src->type==BL_PC)
base_penalty*=2;
if( sd->status.mod_death != 100 )
base_penalty = base_penalty * sd->status.mod_death / 100;
@@ -7307,32 +7324,32 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_FAME: val = sd->status.fame; break;
case SP_KILLERRID: val = sd->killerrid; break;
case SP_KILLEDRID: val = sd->killedrid; break;
- case SP_SLOTCHANGE: val = sd->status.slotchange; break;
- case SP_CHARRENAME: val = sd->status.rename; break;
+ case SP_SLOTCHANGE: val = sd->status.slotchange; break;
+ case SP_CHARRENAME: val = sd->status.rename; break;
case SP_MOD_EXP: val = sd->status.mod_exp; break;
case SP_MOD_DROP: val = sd->status.mod_drop; break;
case SP_MOD_DEATH: val = sd->status.mod_death; break;
case SP_CRITICAL: val = sd->battle_status.cri/10; break;
case SP_ASPD: val = (2000-sd->battle_status.amotion)/10; break;
- case SP_BASE_ATK: val = sd->battle_status.batk; break;
- case SP_DEF1: val = sd->battle_status.def; break;
- case SP_DEF2: val = sd->battle_status.def2; break;
- case SP_MDEF1: val = sd->battle_status.mdef; break;
- case SP_MDEF2: val = sd->battle_status.mdef2; break;
- case SP_HIT: val = sd->battle_status.hit; break;
- case SP_FLEE1: val = sd->battle_status.flee; break;
- case SP_FLEE2: val = sd->battle_status.flee2; break;
- case SP_DEFELE: val = sd->battle_status.def_ele; break;
+ case SP_BASE_ATK: val = sd->battle_status.batk; break;
+ case SP_DEF1: val = sd->battle_status.def; break;
+ case SP_DEF2: val = sd->battle_status.def2; break;
+ case SP_MDEF1: val = sd->battle_status.mdef; break;
+ case SP_MDEF2: val = sd->battle_status.mdef2; break;
+ case SP_HIT: val = sd->battle_status.hit; break;
+ case SP_FLEE1: val = sd->battle_status.flee; break;
+ case SP_FLEE2: val = sd->battle_status.flee2; break;
+ case SP_DEFELE: val = sd->battle_status.def_ele; break;
#ifndef RENEWAL_CAST
case SP_VARCASTRATE:
#endif
case SP_CASTRATE:
val = sd->castrate+=val;
break;
- case SP_MAXHPRATE: val = sd->hprate; break;
- case SP_MAXSPRATE: val = sd->sprate; break;
- case SP_SPRATE: val = sd->dsprate; break;
- case SP_SPEED_RATE: val = sd->bonus.speed_rate; break;
+ case SP_MAXHPRATE: val = sd->hprate; break;
+ case SP_MAXSPRATE: val = sd->sprate; break;
+ case SP_SPRATE: val = sd->dsprate; break;
+ case SP_SPEED_RATE: val = sd->bonus.speed_rate; break;
case SP_SPEED_ADDRATE: val = sd->bonus.speed_add_rate; break;
case SP_ASPD_RATE:
#ifndef RENEWAL_ASPD
@@ -7637,6 +7654,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)
@@ -7841,7 +7862,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
for(i=0;i<EQI_MAX;i++) {
if(sd->equip_index[i] >= 0)
if(!pc->isequip(sd,sd->equip_index[i]))
- pc->unequipitem(sd,sd->equip_index[i],2); // unequip invalid item for class
+ pc->unequipitem(sd,sd->equip_index[i],2); // unequip invalid item for class
}
//Change look, if disguised, you need to undisguise
@@ -7905,7 +7926,7 @@ int pc_jobchange(struct map_session_data *sd,int job, int upper)
chrif->buildfamelist();
} else if (sd->status.fame > 0) {
//It may be that now they are famous?
- switch (sd->class_&MAPID_UPPERMASK) {
+ switch (sd->class_&MAPID_UPPERMASK) {
case MAPID_BLACKSMITH:
case MAPID_ALCHEMIST:
case MAPID_TAEKWON:
@@ -7952,7 +7973,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
clif->skillinfoblock(sd);
return 0;
break;
- case LOOK_HAIR: //Use the battle_config limits! [Skotlex]
+ case LOOK_HAIR: //Use the battle_config limits! [Skotlex]
val = cap_value(val, MIN_HAIR_STYLE, MAX_HAIR_STYLE);
if (sd->status.hair != val) {
@@ -7974,7 +7995,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
case LOOK_HEAD_MID:
sd->status.head_mid=val;
break;
- case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex]
+ case LOOK_HAIR_COLOR: //Use the battle_config limits! [Skotlex]
val = cap_value(val, MIN_HAIR_COLOR, MAX_HAIR_COLOR);
if (sd->status.hair_color != val) {
@@ -7984,7 +8005,7 @@ int pc_changelook(struct map_session_data *sd,int type,int val)
GMI_HAIR_COLOR,&sd->status.hair_color,sizeof(sd->status.hair_color));
}
break;
- case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex]
+ case LOOK_CLOTHES_COLOR: //Use the battle_config limits! [Skotlex]
val = cap_value(val, MIN_CLOTH_COLOR, MAX_CLOTH_COLOR);
sd->status.clothes_color=val;
@@ -8035,6 +8056,8 @@ int pc_setoption(struct map_session_data *sd,int type)
clif->clearcart(sd->fd);
if(pc->checkskill(sd, MC_PUSHCART) < 10)
status_calc_pc(sd,SCO_NONE); //Remove speed penalty.
+ if ( sd->equip_index[EQI_AMMO] > 0 )
+ pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2);
}
#endif
@@ -8070,6 +8093,8 @@ int pc_setoption(struct map_session_data *sd,int type)
}
status_change_end(&sd->bl, (sc_type)i, INVALID_TIMER);
}
+ if ( sd->equip_index[EQI_AMMO] > 0 )
+ pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2);
}
if (type&OPTION_FLYING && !(p_type&OPTION_FLYING))
@@ -8122,6 +8147,8 @@ int pc_setcart(struct map_session_data *sd,int type) {
status_change_end(&sd->bl,SC_PUSH_CART,INVALID_TIMER);
clif->clearcart(sd->fd);
clif->updatestatus(sd, SP_CARTINFO);
+ if ( sd->equip_index[EQI_AMMO] > 0 )
+ pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2);
break;
default:/* everything else is an allowed ID so we can move on */
if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */
@@ -8147,48 +8174,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
+ }
}
/**
@@ -8241,7 +8331,7 @@ bool pc_can_talk( struct map_session_data *sd ) {
int pc_candrop(struct map_session_data *sd, struct item *item)
{
if( item && (item->expire_time || (item->bound && !pc_can_give_bound_items(sd))) )
- return 0;
+ return 0;
if( !pc_can_give_items(sd) ) //check if this GM level can drop items
return 0;
return (itemdb_isdropable(item, pc_get_group_level(sd)));
@@ -8750,6 +8840,89 @@ int pc_load_combo(struct map_session_data *sd) {
}
return ret;
}
+
+void pc_equipitem_pos(struct map_session_data *sd, struct item_data *id, int pos)
+{
+ if (pos & (EQP_HAND_R|EQP_SHADOW_WEAPON)) {
+ if(id)
+ sd->weapontype1 = id->look;
+ else
+ sd->weapontype1 = 0;
+ pc->calcweapontype(sd);
+ clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
+ }
+ if (pos & (EQP_HAND_L|EQP_SHADOW_SHIELD)) {
+ if (id) {
+ if(id->type == IT_WEAPON) {
+ sd->status.shield = 0;
+ sd->weapontype2 = id->look;
+ } else if(id->type == IT_ARMOR) {
+ sd->status.shield = id->look;
+ sd->weapontype2 = 0;
+ }
+ } else
+ sd->status.shield = sd->weapontype2 = 0;
+ pc->calcweapontype(sd);
+ clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
+ }
+ //Added check to prevent sending the same look on multiple slots ->
+ //causes client to redraw item on top of itself. (suggested by Lupus)
+ if (pos & EQP_HEAD_LOW && pc->checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) {
+ if (id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID)))
+ sd->status.head_bottom = id->look;
+ else
+ sd->status.head_bottom = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ }
+ if (pos & EQP_HEAD_TOP && pc->checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) {
+ if (id)
+ sd->status.head_top = id->look;
+ else
+ sd->status.head_top = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ }
+ if (pos & EQP_HEAD_MID && pc->checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) {
+ if (id && !(pos&EQP_HEAD_TOP))
+ sd->status.head_mid = id->look;
+ else
+ sd->status.head_mid = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ }
+ if (pos & EQP_COSTUME_HEAD_TOP) {
+ if (id){
+ sd->status.head_top = id->look;
+ } else
+ sd->status.head_top = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ }
+ if (pos & EQP_COSTUME_HEAD_MID) {
+ if(id && !(pos&EQP_HEAD_TOP)){
+ sd->status.head_mid = id->look;
+ } else
+ sd->status.head_mid = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ }
+ if (pos & EQP_COSTUME_HEAD_LOW) {
+ if (id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))){
+ sd->status.head_bottom = id->look;
+ } else
+ sd->status.head_bottom = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ }
+
+ if (pos & EQP_SHOES)
+ clif->changelook(&sd->bl,LOOK_SHOES,0);
+ if (pos&EQP_GARMENT && pc->checkequip(sd,EQP_COSTUME_GARMENT) == -1) {
+ sd->status.robe = id ? id->look : 0;
+ clif->changelook(&sd->bl, LOOK_ROBE, sd->status.robe);
+ }
+
+ if (pos & EQP_COSTUME_GARMENT) {
+ sd->status.robe = id ? id->look : 0;
+ clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
+ }
+}
+
/*==========================================
* Equip item on player sd at req_pos from inventory index n
*------------------------------------------*/
@@ -8778,13 +8951,13 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
ShowInfo("equip %d(%d) %x:%x\n",sd->status.inventory[n].nameid,n,id?id->equip:0,req_pos);
if(!pc->isequip(sd,n) || !(pos&req_pos) || sd->status.inventory[n].equip != 0 || sd->status.inventory[n].attribute==1 ) { // [Valaris]
// FIXME: pc->isequip: equip level failure uses 2 instead of 0
- clif->equipitemack(sd,n,0,EIA_FAIL); // fail
+ clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
}
if (sd->sc.data[SC_BERSERK] || sd->sc.data[SC_NO_SWITCH_EQUIP])
{
- clif->equipitemack(sd,n,0,EIA_FAIL); // fail
+ clif->equipitemack(sd,n,0,EIA_FAIL); // fail
return 0;
}
@@ -8799,7 +8972,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
if (pos == EQP_ACC) //User specified both slots..
pos = sd->equip_index[EQI_ACC_R] >= 0 ? EQP_ACC_L : EQP_ACC_R;
} else if(pos == EQP_ARMS && id->equip == EQP_HAND_R) { //Dual wield capable weapon.
- pos = (req_pos&EQP_ARMS);
+ pos = (req_pos&EQP_ARMS);
if (pos == EQP_ARMS) //User specified both slots, pick one for them.
pos = sd->equip_index[EQI_HAND_R] >= 0 ? EQP_HAND_L : EQP_HAND_R;
} else if(pos == EQP_SHADOW_ACC) { //Accesories should only go in one of the two,
@@ -8807,13 +8980,13 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
if (pos == EQP_SHADOW_ACC) //User specified both slots..
pos = sd->equip_index[EQI_SHADOW_ACC_R] >= 0 ? EQP_SHADOW_ACC_L : EQP_SHADOW_ACC_R;
} else if( pos == EQP_SHADOW_ARMS && id->equip == EQP_SHADOW_WEAPON) { //Dual wield capable weapon.
- pos = (req_pos&EQP_SHADOW_ARMS);
+ pos = (req_pos&EQP_SHADOW_ARMS);
if (pos == EQP_SHADOW_ARMS) //User specified both slots, pick one for them.
pos = sd->equip_index[EQI_SHADOW_WEAPON] >= 0 ? EQP_SHADOW_SHIELD : EQP_SHADOW_WEAPON;
}
- if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC)
- { //Update skill-block range database when weapon range changes. [Skotlex]
+ if (pos&EQP_HAND_R && battle_config.use_weapon_skill_range&BL_PC) {
+ //Update skill-block range database when weapon range changes. [Skotlex]
i = sd->equip_index[EQI_HAND_R];
if (i < 0 || !sd->inventory_data[i]) //No data, or no weapon equipped
flag = 1;
@@ -8839,86 +9012,8 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
sd->status.inventory[n].equip=pos;
- if(pos & (EQP_HAND_R|EQP_SHADOW_WEAPON)) {
- if(id)
- sd->weapontype1 = id->look;
- else
- sd->weapontype1 = 0;
- pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
- }
- if(pos & (EQP_HAND_L|EQP_SHADOW_SHIELD)) {
- if(id) {
- if(id->type == IT_WEAPON) {
- sd->status.shield = 0;
- sd->weapontype2 = id->look;
- } else if(id->type == IT_ARMOR) {
- sd->status.shield = id->look;
- sd->weapontype2 = 0;
- }
- } else
- sd->status.shield = sd->weapontype2 = 0;
- pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
- }
- //Added check to prevent sending the same look on multiple slots ->
- //causes client to redraw item on top of itself. (suggested by Lupus)
- if(pos & EQP_HEAD_LOW && pc->checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) {
- if(id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID)))
- sd->status.head_bottom = id->look;
- else
- sd->status.head_bottom = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
- }
- if(pos & EQP_HEAD_TOP && pc->checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) {
- if(id)
- sd->status.head_top = id->look;
- else
- sd->status.head_top = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
- }
- if(pos & EQP_HEAD_MID && pc->checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) {
- if(id && !(pos&EQP_HEAD_TOP))
- sd->status.head_mid = id->look;
- else
- sd->status.head_mid = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
- }
- if(pos & EQP_COSTUME_HEAD_TOP) {
- if(id){
- sd->status.head_top = id->look;
- } else
- sd->status.head_top = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
- }
- if(pos & EQP_COSTUME_HEAD_MID) {
- if(id && !(pos&EQP_HEAD_TOP)){
- sd->status.head_mid = id->look;
- } else
- sd->status.head_mid = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
- }
- if(pos & EQP_COSTUME_HEAD_LOW) {
- if(id && !(pos&(EQP_HEAD_TOP|EQP_HEAD_MID))){
- sd->status.head_bottom = id->look;
- } else
- sd->status.head_bottom = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
- }
-
- if(pos & EQP_SHOES)
- clif->changelook(&sd->bl,LOOK_SHOES,0);
- if( pos&EQP_GARMENT && pc->checkequip(sd,EQP_COSTUME_GARMENT) == -1 ) {
- sd->status.robe = id ? id->look : 0;
- clif->changelook(&sd->bl, LOOK_ROBE, sd->status.robe);
- }
-
- if(pos & EQP_COSTUME_GARMENT) {
- sd->status.robe = id ? id->look : 0;
- clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
- }
+ pc->equipitem_pos(sd, id, pos);
-
pc->checkallowskill(sd); //Check if status changes should be halted.
iflag = sd->npc_item_flag;
@@ -8968,6 +9063,63 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
return 0;
}
+void pc_unequipitem_pos(struct map_session_data *sd, int n, int pos)
+{
+ if (pos & EQP_HAND_R) {
+ sd->weapontype1 = 0;
+ sd->status.weapon = sd->weapontype2;
+ pc->calcweapontype(sd);
+ clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
+ if (!battle_config.dancing_weaponswitch_fix)
+ status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing.
+ }
+ if (pos & EQP_HAND_L) {
+ sd->status.shield = sd->weapontype2 = 0;
+ pc->calcweapontype(sd);
+ clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
+ }
+ if (pos & EQP_HEAD_LOW && pc->checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1) {
+ sd->status.head_bottom = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ }
+ if (pos & EQP_HEAD_TOP && pc->checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1) {
+ sd->status.head_top = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ }
+ if (pos & EQP_HEAD_MID && pc->checkequip(sd,EQP_COSTUME_HEAD_MID) == -1) {
+ sd->status.head_mid = 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ }
+
+ if (pos & EQP_COSTUME_HEAD_TOP) {
+ sd->status.head_top = ( pc->checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_TOP)]->look : 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
+ }
+
+ if (pos & EQP_COSTUME_HEAD_MID) {
+ sd->status.head_mid = ( pc->checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_MID)]->look : 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
+ }
+
+ if (pos & EQP_COSTUME_HEAD_LOW) {
+ sd->status.head_bottom = ( pc->checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_LOW)]->look : 0;
+ clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
+ }
+
+ if (pos & EQP_SHOES)
+ clif->changelook(&sd->bl,LOOK_SHOES,0);
+
+ if (pos & EQP_GARMENT && pc->checkequip(sd,EQP_COSTUME_GARMENT) == -1) {
+ sd->status.robe = 0;
+ clif->changelook(&sd->bl, LOOK_ROBE, 0);
+ }
+
+ if (pos & EQP_COSTUME_GARMENT) {
+ sd->status.robe = ( pc->checkequip(sd,EQP_GARMENT) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_GARMENT)]->look : 0;
+ clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
+ }
+}
+
/*==========================================
* Called when attemting to unequip an item from player
* type:
@@ -8978,6 +9130,7 @@ int pc_equipitem(struct map_session_data *sd,int n,int req_pos)
int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
int i,iflag;
bool status_cacl = false;
+ int pos;
nullpo_ret(sd);
if( n < 0 || n >= MAX_INVENTORY ) {
@@ -9010,73 +9163,22 @@ int pc_unequipitem(struct map_session_data *sd,int n,int flag) {
sd->equip_index[i] = -1;
}
- if(sd->status.inventory[n].equip & EQP_HAND_R) {
- sd->weapontype1 = 0;
- sd->status.weapon = sd->weapontype2;
- pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
- if( !battle_config.dancing_weaponswitch_fix )
- status_change_end(&sd->bl, SC_DANCING, INVALID_TIMER); // Unequipping => stop dancing.
- }
- if(sd->status.inventory[n].equip & EQP_HAND_L) {
- sd->status.shield = sd->weapontype2 = 0;
- pc->calcweapontype(sd);
- clif->changelook(&sd->bl,LOOK_SHIELD,sd->status.shield);
- }
- if(sd->status.inventory[n].equip & EQP_HEAD_LOW && pc->checkequip(sd,EQP_COSTUME_HEAD_LOW) == -1 ) {
- sd->status.head_bottom = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
- }
- if(sd->status.inventory[n].equip & EQP_HEAD_TOP && pc->checkequip(sd,EQP_COSTUME_HEAD_TOP) == -1 ) {
- sd->status.head_top = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
- }
- if(sd->status.inventory[n].equip & EQP_HEAD_MID && pc->checkequip(sd,EQP_COSTUME_HEAD_MID) == -1 ) {
- sd->status.head_mid = 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
- }
+ pos = sd->status.inventory[n].equip;
+ pc->unequipitem_pos(sd, n, pos);
- if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_TOP) {
- sd->status.head_top = ( pc->checkequip(sd,EQP_HEAD_TOP) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_TOP)]->look : 0;
- clif->changelook(&sd->bl,LOOK_HEAD_TOP,sd->status.head_top);
- }
-
- if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_MID) {
- sd->status.head_mid = ( pc->checkequip(sd,EQP_HEAD_MID) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_MID)]->look : 0;
- clif->changelook(&sd->bl,LOOK_HEAD_MID,sd->status.head_mid);
- }
+ clif->unequipitemack(sd,n,pos,UIA_SUCCESS);
- if(sd->status.inventory[n].equip & EQP_COSTUME_HEAD_LOW) {
- sd->status.head_bottom = ( pc->checkequip(sd,EQP_HEAD_LOW) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_HEAD_LOW)]->look : 0;
- clif->changelook(&sd->bl,LOOK_HEAD_BOTTOM,sd->status.head_bottom);
- }
-
- if(sd->status.inventory[n].equip & EQP_SHOES)
- clif->changelook(&sd->bl,LOOK_SHOES,0);
-
- if( sd->status.inventory[n].equip&EQP_GARMENT && pc->checkequip(sd,EQP_COSTUME_GARMENT) == -1 ) {
- sd->status.robe = 0;
- clif->changelook(&sd->bl, LOOK_ROBE, 0);
- }
-
- if(sd->status.inventory[n].equip & EQP_COSTUME_GARMENT) {
- sd->status.robe = ( pc->checkequip(sd,EQP_GARMENT) >= 0 ) ? sd->inventory_data[pc->checkequip(sd,EQP_GARMENT)]->look : 0;
- clif->changelook(&sd->bl,LOOK_ROBE,sd->status.robe);
- }
-
- clif->unequipitemack(sd,n,sd->status.inventory[n].equip,UIA_SUCCESS);
-
- if((sd->status.inventory[n].equip & EQP_ARMS) &&
+ if((pos & EQP_ARMS) &&
sd->weapontype1 == 0 && sd->weapontype2 == 0 && (!sd->sc.data[SC_TK_SEVENWIND] || sd->sc.data[SC_ASPERSIO])) //Check for seven wind (but not level seven!)
skill->enchant_elemental_end(&sd->bl,-1);
- if(sd->status.inventory[n].equip & EQP_ARMOR) {
+ if(pos & EQP_ARMOR) {
// On Armor Change...
status_change_end(&sd->bl, SC_BENEDICTIO, INVALID_TIMER);
status_change_end(&sd->bl, SC_ARMOR_RESIST, INVALID_TIMER);
}
- if( sd->state.autobonus&sd->status.inventory[n].equip )
+ if( sd->state.autobonus&pos )
sd->state.autobonus &= ~sd->status.inventory[n].equip; //Check for activated autobonus [Inkfish]
sd->status.inventory[n].equip=0;
@@ -9114,8 +9216,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 {
@@ -9125,8 +9234,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);
+ }
}
}
@@ -9201,7 +9318,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;
@@ -9238,8 +9355,32 @@ int pc_checkitem(struct map_session_data *sd)
continue;
}
+ if ( battle_config.unequip_restricted_equipment & 1 ) {
+ int j;
+ for ( j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++ ) {
+ if ( map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].nameid ) {
+ pc->unequipitem( sd, i, 2 );
+ calc_flag = 1;
+ }
+ }
+ }
+
+ if ( battle_config.unequip_restricted_equipment & 2 ) {
+ if ( !itemdb_isspecial( sd->status.inventory[i].card[0] ) ) {
+ int j, slot;
+ for ( slot = 0; slot < MAX_SLOTS; slot++ ) {
+ for ( j = 0; j < map->list[sd->bl.m].zone->disabled_items_count; j++ ) {
+ if ( map->list[sd->bl.m].zone->disabled_items[j] == sd->status.inventory[i].card[slot] ) {
+ pc->unequipitem( sd, i, 2 );
+ calc_flag = 1;
+ }
+ }
+ }
+ }
+ }
+
}
-
+
if( calc_flag && sd->state.active ) {
pc->checkallowskill(sd);
status_calc_pc(sd,SCO_NONE);
@@ -9258,8 +9399,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;
}
@@ -9293,8 +9434,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;
}
@@ -9306,8 +9447,8 @@ int pc_calc_pvprank_timer(int tid, int64 tick, int id, intptr_t data) {
/*==========================================
* Checking if sd is married
* Return:
- * partner_id = yes
- * 0 = no
+ * partner_id = yes
+ * 0 = no
*------------------------------------------*/
int pc_ismarried(struct map_session_data *sd)
{
@@ -9321,8 +9462,8 @@ int pc_ismarried(struct map_session_data *sd)
/*==========================================
* Marry player sd to player dstsd
* Return:
- * -1 = fail
- * 0 = success
+ * -1 = fail
+ * 0 = success
*------------------------------------------*/
int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
{
@@ -9338,8 +9479,8 @@ int pc_marriage(struct map_session_data *sd,struct map_session_data *dstsd)
/*==========================================
* Divorce sd from its partner
* Return:
- * -1 = fail
- * 0 = success
+ * -1 = fail
+ * 0 = success
*------------------------------------------*/
int pc_divorce(struct map_session_data *sd)
{
@@ -9655,28 +9796,28 @@ int pc_charm_timer(int tid, int64 tick, int id, intptr_t data) {
if( (sd=(struct map_session_data *)map->id2sd(id)) == NULL || sd->bl.type!=BL_PC )
return 1;
- ARR_FIND(1, 5, type, sd->charm[type] > 0);
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, type, sd->spiritcharm[type] > 0);
- if( sd->charm[type] <= 0 )
+ if( sd->spiritcharm[type] <= 0 )
{
- ShowError("pc_charm_timer: %d charm's available. (aid=%d cid=%d tid=%d)\n", sd->charm[type], sd->status.account_id, sd->status.char_id, tid);
- sd->charm[type] = 0;
+ ShowError("pc_charm_timer: %d spiritcharm's available. (aid=%d cid=%d tid=%d)\n", sd->spiritcharm[type], sd->status.account_id, sd->status.char_id, tid);
+ sd->spiritcharm[type] = 0;
return 0;
}
- ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == tid);
- if( i == sd->charm[type] )
+ ARR_FIND(0, sd->spiritcharm[type], i, sd->charm_timer[type][i] == tid);
+ if( i == sd->spiritcharm[type] )
{
ShowError("pc_charm_timer: timer not found (aid=%d cid=%d tid=%d)\n", sd->status.account_id, sd->status.char_id, tid);
return 0;
}
- sd->charm[type]--;
- if( i != sd->charm[type] )
- memmove(sd->charm_timer[type]+i, sd->charm_timer[type]+i+1, (sd->charm[type]-i)*sizeof(int));
- sd->charm_timer[type][sd->charm[type]] = INVALID_TIMER;
+ sd->spiritcharm[type]--;
+ if( i != sd->spiritcharm[type] )
+ memmove(sd->charm_timer[type]+i, sd->charm_timer[type]+i+1, (sd->spiritcharm[type]-i)*sizeof(int));
+ sd->charm_timer[type][sd->spiritcharm[type]] = INVALID_TIMER;
- clif->charm(sd, type);
+ clif->spiritcharm(sd, type);
return 0;
}
@@ -9689,27 +9830,27 @@ int pc_add_charm(struct map_session_data *sd,int interval,int max,int type)
if(max > 10)
max = 10;
- if(sd->charm[type] < 0)
- sd->charm[type] = 0;
+ if(sd->spiritcharm[type] < 0)
+ sd->spiritcharm[type] = 0;
- if( sd->charm[type] && sd->charm[type] >= max )
+ if( sd->spiritcharm[type] && sd->spiritcharm[type] >= max )
{
if(sd->charm_timer[type][0] != INVALID_TIMER)
timer->delete(sd->charm_timer[type][0],pc->charm_timer);
- sd->charm[type]--;
- if( sd->charm[type] != 0 )
- memmove(sd->charm_timer[type]+0, sd->charm_timer[type]+1, (sd->charm[type])*sizeof(int));
- sd->charm_timer[type][sd->charm[type]] = INVALID_TIMER;
+ sd->spiritcharm[type]--;
+ if( sd->spiritcharm[type] != 0 )
+ memmove(sd->charm_timer[type]+0, sd->charm_timer[type]+1, (sd->spiritcharm[type])*sizeof(int));
+ sd->charm_timer[type][sd->spiritcharm[type]] = INVALID_TIMER;
}
tid = timer->add(timer->gettick()+interval, pc->charm_timer, sd->bl.id, 0);
- ARR_FIND(0, sd->charm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->charm_timer[type][i])->tick) < 0);
- if( i != sd->charm[type] )
- memmove(sd->charm_timer[type]+i+1, sd->charm_timer[type]+i, (sd->charm[type]-i)*sizeof(int));
+ ARR_FIND(0, sd->spiritcharm[type], i, sd->charm_timer[type][i] == INVALID_TIMER || DIFF_TICK(timer->get(tid)->tick, timer->get(sd->charm_timer[type][i])->tick) < 0);
+ if( i != sd->spiritcharm[type] )
+ memmove(sd->charm_timer[type]+i+1, sd->charm_timer[type]+i, (sd->spiritcharm[type]-i)*sizeof(int));
sd->charm_timer[type][i] = tid;
- sd->charm[type]++;
+ sd->spiritcharm[type]++;
- clif->charm(sd, type);
+ clif->spiritcharm(sd, type);
return 0;
}
@@ -9719,16 +9860,16 @@ int pc_del_charm(struct map_session_data *sd,int count,int type)
nullpo_ret(sd);
- if( sd->charm[type] <= 0 ) {
- sd->charm[type] = 0;
+ if( sd->spiritcharm[type] <= 0 ) {
+ sd->spiritcharm[type] = 0;
return 0;
}
if( count <= 0 )
return 0;
- if( count > sd->charm[type] )
- count = sd->charm[type];
- sd->charm[type] -= count;
+ if( count > sd->spiritcharm[type] )
+ count = sd->spiritcharm[type];
+ sd->spiritcharm[type] -= count;
if( count > 10 )
count = 10;
@@ -9743,7 +9884,7 @@ int pc_del_charm(struct map_session_data *sd,int count,int type)
sd->charm_timer[type][i] = INVALID_TIMER;
}
- clif->charm(sd, type);
+ clif->spiritcharm(sd, type);
return 0;
}
/*==========================================
@@ -10091,11 +10232,11 @@ void pc_read_skill_tree(void) {
libconfig->destroy(&skill_tree_conf);
- /* lets update all players skill tree */
- iter = mapit_getallusers();
- for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
- clif->skillinfoblock(sd);
- mapit->free(iter);
+ /* lets update all players skill tree */
+ iter = mapit_getallusers();
+ for( sd = (TBL_PC*)mapit->first(iter); mapit->exists(iter); sd = (TBL_PC*)mapit->next(iter) )
+ clif->skillinfoblock(sd);
+ mapit->free(iter);
}
bool pc_readdb_levelpenalty(char* fields[], int columns, int current) {
#if defined(RENEWAL_DROP) || defined(RENEWAL_EXP)
@@ -10183,7 +10324,7 @@ int pc_readdb(void) {
//Reverse check in case the array has a bunch of trailing zeros... [Skotlex]
//The reasoning behind the -2 is this... if the max level is 5, then the array
//should look like this:
- //0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
+ //0: x, 1: x, 2: x: 3: x 4: 0 <- last valid value is at 3.
while ((ui = pc->max_level[job][type]) >= 2 && pc->exp_table[job][type][ui-2] <= 0)
pc->max_level[job][type]--;
if (pc->max_level[job][type] < maxlv) {
@@ -10195,7 +10336,7 @@ int pc_readdb(void) {
pc->exp_table[job][type][ui] = pc->exp_table[job][type][ui-1];
pc->max_level[job][type] = maxlv;
}
-// ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
+ //ShowDebug("%s - Class %d: %d\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
for (i = 1; i < job_count; i++) {
job_id = jobs[i];
if (!pcdb_checkid(job_id)) {
@@ -10205,7 +10346,7 @@ int pc_readdb(void) {
job = pc->class2idx(job_id);
memcpy(pc->exp_table[job][type], pc->exp_table[jobs[0]][type], sizeof(pc->exp_table[0][0]));
pc->max_level[job][type] = maxlv;
-// ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
+ //ShowDebug("%s - Class %d: %u\n", type?"Job":"Base", job_id, pc->max_level[job][type]);
}
}
fclose(fp);
@@ -10445,8 +10586,8 @@ int pc_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-/* this timer exists only when a character with a expire timer > 24h is online */
-/* it loops thru online players once an hour to check whether a new < 24h is available */
+/* This timer exists only when a character with an expire timer > 24h is online */
+/* It loops through online players once an hour to check whether a new < 24h is available */
int pc_global_expiration_timer(int tid, int64 tick, int id, intptr_t data) {
struct s_mapiterator* iter;
struct map_session_data* sd;
@@ -10914,7 +11055,9 @@ void pc_defaults(void) {
pc->resetfeel = pc_resetfeel;
pc->resethate = pc_resethate;
pc->equipitem = pc_equipitem;
+ pc->equipitem_pos = pc_equipitem_pos;
pc->unequipitem = pc_unequipitem;
+ pc->unequipitem_pos = pc_unequipitem_pos;
pc->checkitem = pc_checkitem;
pc->useitem = pc_useitem;
@@ -10932,8 +11075,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 bec4522df..8472eb34e 100644
--- a/src/map/pc.h
+++ b/src/map/pc.h
@@ -29,7 +29,7 @@
#define MAX_PC_BONUS 10
#define MAX_PC_SKILL_REQUIRE 5
#define MAX_PC_FEELHATE 3
-#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval
+#define PVP_CALCRANK_INTERVAL 1000 // PVP calculation interval
//Equip indexes constants. (eg: sd->equip_index[EQI_AMMO] returns the index
//where the arrows are equipped)
@@ -80,7 +80,7 @@ struct weapon_data {
} hp_drain[RC_MAX], sp_drain[RC_MAX];
struct {
short class_, rate;
- } add_dmg[MAX_PC_BONUS];
+ } add_dmg[MAX_PC_BONUS];
struct {
short flag, rate;
unsigned char ele;
@@ -145,7 +145,7 @@ struct map_session_data {
unsigned int snovice_dead_flag : 1; //Explosion spirits on death: 0 off, 1 used.
unsigned int abra_flag : 2; // Abracadabra bugfix by Aru
unsigned int autocast : 1; // Autospell flag [Inkfish]
- unsigned int autotrade : 1; //By Fantik
+ unsigned int autotrade : 2; //By Fantik
unsigned int showdelay :1;
unsigned int showexp :1;
unsigned int showzeny :1;
@@ -202,13 +202,13 @@ struct map_session_data {
unsigned int bonus_coma : 1;
} special_state;
int login_id1, login_id2;
- unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
-
+ unsigned short class_; //This is the internal job ID used by the map server to simplify comparisons/queries/etc. [Skotlex]
+
/// Groups & permissions
int group_id;
GroupSettings *group;
unsigned int extra_temp_permissions; /* permissions from @addperm */
-
+
struct mmo_charstatus status;
struct item_data* inventory_data[MAX_INVENTORY]; // direct pointers to itemdb entries (faster than doing item_id lookups)
short equip_index[EQI_MAX];
@@ -301,7 +301,7 @@ struct map_session_data {
} hp_loss, sp_loss, hp_regen, sp_regen;
struct {
short class_, rate;
- } add_def[MAX_PC_BONUS], add_mdef[MAX_PC_BONUS], add_mdmg[MAX_PC_BONUS];
+ } add_def[MAX_PC_BONUS], add_mdef[MAX_PC_BONUS], add_mdmg[MAX_PC_BONUS];
struct s_add_drop add_drop[MAX_PC_BONUS];
struct {
int nameid;
@@ -349,7 +349,7 @@ struct map_session_data {
short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value;
short sp_vanish_rate;
short sp_vanish_per, sp_vanish_trigger;
- unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest]
+ unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest]
unsigned short unbreakable_equip; //100% break resistance on certain equipment
unsigned short unstripable_equip;
int fixcastrate,varcastrate;
@@ -362,12 +362,12 @@ struct map_session_data {
int matk_rate;
int critical_rate,hit_rate,flee_rate,flee2_rate,def_rate,def2_rate,mdef_rate,mdef2_rate;
int itemid;
- short itemindex; //Used item's index in sd->inventory [Skotlex]
+ short itemindex; //Used item's index in sd->inventory [Skotlex]
short catch_target_class; // pet catching, stores a pet class to catch (short now) [zzo]
short spiritball, spiritball_old;
int spirit_timer[MAX_SPIRITBALL];
- short charm[ELE_POISON+1]; // There are actually 5 charm Fire, Ice, Wind, Earth & Poison maybe because its color violet.
- int charm_timer[ELE_POISON+1][10];
+ short spiritcharm[SPIRITS_TYPE_END];
+ int charm_timer[SPIRITS_TYPE_END][MAX_SPIRITCHARM];
unsigned char potion_success_counter; //Potion successes in row counter
unsigned char mission_count; //Stores the bounty kill count for TK_MISSION
short mission_mobid; //Stores the target mob_id for TK_MISSION
@@ -400,7 +400,7 @@ struct map_session_data {
struct s_search_store_info searchstore;
struct pet_data *pd;
- struct homun_data *hd; // [blackhole89]
+ struct homun_data *hd; // [blackhole89]
struct mercenary_data *md;
struct elemental_data *ed;
@@ -481,14 +481,14 @@ struct map_session_data {
struct pc_combos *combos;
unsigned char combo_count;
-
+
/**
* Guarantees your friend request is legit (for bugreport:4629)
**/
int friend_req;
int shadowform_id;
-
+
/* [Ind/Hercules] */
struct hChSysCh **channels;
unsigned char channel_count;
@@ -497,14 +497,14 @@ struct map_session_data {
unsigned char fontcolor;
unsigned int fontcolor_tid;
int64 hchsysch_tick;
-
+
/* [Ind/Hercules] */
struct sc_display_entry **sc_display;
unsigned char sc_display_count;
-
+
short *instance;
unsigned short instances;
-
+
/* Possible Thanks to Yommy~! */
struct {
unsigned int ready : 1;/* did he accept the 'match is about to start, enter' dialog? */
@@ -515,26 +515,26 @@ struct map_session_data {
int *queues;
unsigned int queues_count;
-
+
/* Made Possible Thanks to Yommy~! */
unsigned int cryptKey; ///< Packet obfuscation key to be used for the next received packet
unsigned short (*parse_cmd_func)(int fd, struct map_session_data *sd); ///< parse_cmd_func used by this player
-
+
unsigned char delayed_damage;//ref. counter bugreport:7307 [Ind/Hercules]
-
+
/* HPM Custom Struct */
struct HPluginData **hdata;
unsigned int hdatac;
-
+
/* expiration_time timer id */
int expiration_tid;
time_t expiration_time;
-
+
/* */
struct {
unsigned int second,third;
} sktree;
-
+
/**
* Account/Char variables & array control of those variables
**/
@@ -542,7 +542,14 @@ struct map_session_data {
unsigned char vars_received;/* char loading is only complete when you get it all. */
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)))
@@ -614,13 +622,13 @@ struct map_session_data {
//JOB_NOVICE isn't checked for class_ is supposed to be unsigned
#define pcdb_checkid_sub(class_) \
( \
- ( (class_) < JOB_MAX_BASIC ) \
-|| ( (class_) >= JOB_NOVICE_HIGH && (class_) <= JOB_DARK_COLLECTOR ) \
-|| ( (class_) >= JOB_RUNE_KNIGHT && (class_) <= JOB_MECHANIC_T2 ) \
-|| ( (class_) >= JOB_BABY_RUNE && (class_) <= JOB_BABY_MECHANIC2 ) \
-|| ( (class_) >= JOB_SUPER_NOVICE_E && (class_) <= JOB_SUPER_BABY_E ) \
-|| ( (class_) >= JOB_KAGEROU && (class_) <= JOB_OBORO ) \
-|| ( (class_) >= JOB_REBELLION && (class_) < JOB_MAX ) \
+ ( (class_) < JOB_MAX_BASIC ) \
+ || ( (class_) >= JOB_NOVICE_HIGH && (class_) <= JOB_DARK_COLLECTOR ) \
+ || ( (class_) >= JOB_RUNE_KNIGHT && (class_) <= JOB_MECHANIC_T2 ) \
+ || ( (class_) >= JOB_BABY_RUNE && (class_) <= JOB_BABY_MECHANIC2 ) \
+ || ( (class_) >= JOB_SUPER_NOVICE_E && (class_) <= JOB_SUPER_BABY_E ) \
+ || ( (class_) >= JOB_KAGEROU && (class_) <= JOB_OBORO ) \
+ || ( (class_) >= JOB_REBELLION && (class_) < JOB_MAX ) \
)
#define pcdb_checkid(class_) pcdb_checkid_sub((unsigned int)(class_))
@@ -632,8 +640,8 @@ struct map_session_data {
#define pc_rightside_def(sd) ((sd)->battle_status.def)
#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2)
#define pc_rightside_mdef(sd) ((sd)->battle_status.mdef)
-#define pc_leftside_matk(sd) (status->base_matk(status->get_status_data(&(sd)->bl), (sd)->status.base_level))
-#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk)
+ #define pc_leftside_matk(sd) (status->base_matk(&(sd)->bl, status->get_status_data(&(sd)->bl), (sd)->status.base_level))
+ #define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk)
#else
#define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk)
#define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2)
@@ -641,18 +649,16 @@ struct map_session_data {
#define pc_rightside_def(sd) ((sd)->battle_status.def2)
#define pc_leftside_mdef(sd) ((sd)->battle_status.mdef)
#define pc_rightside_mdef(sd) ( (sd)->battle_status.mdef2 - ((sd)->battle_status.vit>>1) )
-#define pc_leftside_matk(sd) \
- (\
- ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \
+#define pc_leftside_matk(sd) (\
+ ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \
?((sd)->battle_status.matk_min * 100 + 50) / ((sd)->sc.data[SC_MAGICPOWER]->val3+100) \
- :(sd)->battle_status.matk_min \
- )
-#define pc_rightside_matk(sd) \
- (\
- ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \
+ :(sd)->battle_status.matk_min \
+)
+#define pc_rightside_matk(sd) (\
+ ((sd)->sc.data[SC_MAGICPOWER] && (sd)->sc.data[SC_MAGICPOWER]->val4) \
?((sd)->battle_status.matk_max * 100 + 50) / ((sd)->sc.data[SC_MAGICPOWER]->val3+100) \
- :(sd)->battle_status.matk_max \
- )
+ :(sd)->battle_status.matk_max \
+)
#endif
#define pc_get_group_id(sd) ( (sd)->group_id )
@@ -769,15 +775,12 @@ struct pc_interface {
/* funcs */
void (*init) (bool minimal);
void (*final) (void);
-
+
struct map_session_data* (*get_dummy_sd) (void);
int (*class2idx) (int class_);
- //int (*getrefinebonus) (int lv,int type); FIXME: This function does not exist, nor it is ever called
- bool (*can_give_items) (struct map_session_data *sd);
- bool (*can_give_bound_items) (struct map_session_data *sd);
bool (*can_talk) (struct map_session_data *sd);
bool (*can_attack) ( struct map_session_data *sd, int target_id );
-
+
bool (*can_use_command) (struct map_session_data *sd, const char *command);
int (*set_group) (struct map_session_data *sd, int group_id);
bool (*should_log_commands) (struct map_session_data *sd);
@@ -789,25 +792,25 @@ struct pc_interface {
bool (*authok) (struct map_session_data *sd, int login_id2, time_t expiration_time, int group_id, struct mmo_charstatus *st, bool changing_mapservers);
void (*authfail) (struct map_session_data *sd);
int (*reg_received) (struct map_session_data *sd);
-
+
int (*isequip) (struct map_session_data *sd,int n);
int (*equippoint) (struct map_session_data *sd,int n);
int (*setinventorydata) (struct map_session_data *sd);
-
+
int (*checkskill) (struct map_session_data *sd,uint16 skill_id);
int (*checkskill2) (struct map_session_data *sd,uint16 index);
int (*checkallowskill) (struct map_session_data *sd);
int (*checkequip) (struct map_session_data *sd,int pos);
-
+
int (*calc_skilltree) (struct map_session_data *sd);
int (*calc_skilltree_normalize_job) (struct map_session_data *sd);
int (*clean_skilltree) (struct map_session_data *sd);
-
+
int (*setpos) (struct map_session_data* sd, unsigned short map_index, int x, int y, clr_type clrtype);
int (*setsavepoint) (struct map_session_data *sd, short map_index, int x, int y);
int (*randomwarp) (struct map_session_data *sd,clr_type type);
int (*memo) (struct map_session_data* sd, int pos);
-
+
int (*checkadditem) (struct map_session_data *sd,int nameid,int amount);
int (*inventoryblank) (struct map_session_data *sd);
int (*search_inventory) (struct map_session_data *sd,int item_id);
@@ -819,45 +822,45 @@ struct pc_interface {
// Special Shop System
int (*paycash) (struct map_session_data *sd, int price, int points);
int (*getcash) (struct map_session_data *sd, int cash, int points);
-
+
int (*cart_additem) (struct map_session_data *sd,struct item *item_data,int amount,e_log_pick_type log_type);
int (*cart_delitem) (struct map_session_data *sd,int n,int amount,int type,e_log_pick_type log_type);
int (*putitemtocart) (struct map_session_data *sd,int idx,int amount);
int (*getitemfromcart) (struct map_session_data *sd,int idx,int amount);
int (*cartitem_amount) (struct map_session_data *sd,int idx,int amount);
-
+
int (*takeitem) (struct map_session_data *sd,struct flooritem_data *fitem);
int (*dropitem) (struct map_session_data *sd,int n,int amount);
-
+
bool (*isequipped) (struct map_session_data *sd, int nameid);
bool (*can_Adopt) (struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd);
bool (*adoption) (struct map_session_data *p1_sd, struct map_session_data *p2_sd, struct map_session_data *b_sd);
-
+
int (*updateweightstatus) (struct map_session_data *sd);
-
+
int (*addautobonus) (struct s_autobonus *bonus,char max,const char *bonus_script,short rate,unsigned int dur,short atk_type,const char *o_script,unsigned short pos,bool onskill);
int (*exeautobonus) (struct map_session_data* sd,struct s_autobonus *bonus);
int (*endautobonus) (int tid, int64 tick, int id, intptr_t data);
int (*delautobonus) (struct map_session_data* sd,struct s_autobonus *bonus,char max,bool restore);
-
+
int (*bonus) (struct map_session_data *sd,int type,int val);
int (*bonus2) (struct map_session_data *sd,int type,int type2,int val);
int (*bonus3) (struct map_session_data *sd,int type,int type2,int type3,int val);
int (*bonus4) (struct map_session_data *sd,int type,int type2,int type3,int type4,int val);
int (*bonus5) (struct map_session_data *sd,int type,int type2,int type3,int type4,int type5,int val);
int (*skill) (struct map_session_data *sd, int id, int level, int flag);
-
+
int (*insert_card) (struct map_session_data *sd,int idx_card,int idx_equip);
-
+
int (*steal_item) (struct map_session_data *sd,struct block_list *bl, uint16 skill_lv);
int (*steal_coin) (struct map_session_data *sd,struct block_list *bl);
-
+
int (*modifybuyvalue) (struct map_session_data *sd,int orig_value);
int (*modifysellvalue) (struct map_session_data *sd,int orig_value);
-
+
int (*follow) (struct map_session_data *sd, int target_id); // [MouseJstr]
int (*stop_following) (struct map_session_data *sd);
-
+
unsigned int (*maxbaselv) (struct map_session_data *sd);
unsigned int (*maxjoblv) (struct map_session_data *sd);
int (*checkbaselevelup) (struct map_session_data *sd);
@@ -880,14 +883,16 @@ struct pc_interface {
int (*resetfeel) (struct map_session_data *sd);
int (*resethate) (struct map_session_data *sd);
int (*equipitem) (struct map_session_data *sd,int n,int req_pos);
+ void (*equipitem_pos) (struct map_session_data *sd, struct item_data *id, int pos);
int (*unequipitem) (struct map_session_data *sd,int n,int flag);
+ void (*unequipitem_pos) (struct map_session_data *sd, int n, int pos);
int (*checkitem) (struct map_session_data *sd);
int (*useitem) (struct map_session_data *sd,int n);
-
+
int (*skillatk_bonus) (struct map_session_data *sd, uint16 skill_id);
int (*skillheal_bonus) (struct map_session_data *sd, uint16 skill_id);
int (*skillheal2_bonus) (struct map_session_data *sd, uint16 skill_id);
-
+
void (*damage) (struct map_session_data *sd,struct block_list *src,unsigned int hp, unsigned int sp);
int (*dead) (struct map_session_data *sd,struct block_list *src);
void (*revive) (struct map_session_data *sd,unsigned int hp, unsigned int sp);
@@ -897,12 +902,14 @@ 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);
-
+
int (*readparam) (struct map_session_data *sd,int type);
int (*setparam) (struct map_session_data *sd,int type,int val);
int (*readreg) (struct map_session_data *sd, int64 reg);
@@ -913,15 +920,15 @@ struct pc_interface {
int (*setregistry) (struct map_session_data *sd, int64 reg, int val);
char * (*readregistry_str) (struct map_session_data *sd, int64 reg);
int (*setregistry_str) (struct map_session_data *sd, int64 reg, const char *val);
-
+
int (*addeventtimer) (struct map_session_data *sd,int tick,const char *name);
int (*deleventtimer) (struct map_session_data *sd,const char *name);
int (*cleareventtimer) (struct map_session_data *sd);
int (*addeventtimercount) (struct map_session_data *sd,const char *name,int tick);
-
+
int (*calc_pvprank) (struct map_session_data *sd);
int (*calc_pvprank_timer) (int tid, int64 tick, int id, intptr_t data);
-
+
int (*ismarried) (struct map_session_data *sd);
int (*marriage) (struct map_session_data *sd,struct map_session_data *dstsd);
int (*divorce) (struct map_session_data *sd);
@@ -929,27 +936,27 @@ struct pc_interface {
struct map_session_data * (*get_father) (struct map_session_data *sd);
struct map_session_data * (*get_mother) (struct map_session_data *sd);
struct map_session_data * (*get_child) (struct map_session_data *sd);
-
+
void (*bleeding) (struct map_session_data *sd, unsigned int diff_tick);
void (*regen) (struct map_session_data *sd, unsigned int diff_tick);
-
+
void (*setstand) (struct map_session_data *sd);
int (*candrop) (struct map_session_data *sd,struct item *item);
-
+
int (*jobid2mapid) (unsigned short b_class); // Skotlex
int (*mapid2jobid) (unsigned short class_, int sex); // Skotlex
-
+
const char * (*job_name) (int class_);
-
+
void (*setinvincibletimer) (struct map_session_data* sd, int val);
void (*delinvincibletimer) (struct map_session_data* sd);
-
+
int (*addspiritball) (struct map_session_data *sd,int interval,int max);
int (*delspiritball) (struct map_session_data *sd,int count,int type);
void (*addfame) (struct map_session_data *sd,int count);
unsigned char (*famerank) (int char_id, int job);
int (*set_hate_mob) (struct map_session_data *sd, int pos, struct block_list *bl);
-
+
int (*readdb) (void);
int (*map_day_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor]
int (*map_night_timer) (int tid, int64 tick, int id, intptr_t data); // by [yor]
@@ -957,25 +964,25 @@ struct pc_interface {
void (*inventory_rentals) (struct map_session_data *sd);
int (*inventory_rental_clear) (struct map_session_data *sd);
void (*inventory_rental_add) (struct map_session_data *sd, int seconds);
-
+
int (*disguise) (struct map_session_data *sd, int class_);
bool (*isautolooting) (struct map_session_data *sd, int nameid);
-
+
void (*overheat) (struct map_session_data *sd, int val);
-
+
int (*banding) (struct map_session_data *sd, uint16 skill_lv);
-
+
void (*itemcd_do) (struct map_session_data *sd, bool load);
-
+
int (*load_combo) (struct map_session_data *sd);
-
+
int (*add_charm) (struct map_session_data *sd,int interval,int max,int type);
int (*del_charm) (struct map_session_data *sd,int count,int type);
-
+
void (*baselevelchanged) (struct map_session_data *sd);
int (*level_penalty_mod) (int diff, unsigned char race, unsigned short mode, int type);
int (*calc_skillpoint) (struct map_session_data* sd);
-
+
int (*invincible_timer) (int tid, int64 tick, int id, intptr_t data);
int (*spiritball_timer) (int tid, int64 tick, int id, intptr_t data);
int (*check_banding) ( struct block_list *bl, va_list ap );
@@ -1003,19 +1010,19 @@ struct pc_interface {
int (*checkcombo) (struct map_session_data *sd, struct item_data *data );
int (*calcweapontype) (struct map_session_data *sd);
int (*removecombo) (struct map_session_data *sd, struct item_data *data );
-
+
void (*bank_deposit) (struct map_session_data *sd, int money);
void (*bank_withdraw) (struct map_session_data *sd, int money);
-
+
void (*rental_expire) (struct map_session_data *sd, int i);
void (*scdata_received) (struct map_session_data *sd);
-
+
void (*bound_clear) (struct map_session_data *sd, enum e_item_bound_type type);
-
+
int (*expiration_timer) (int tid, int64 tick, int id, intptr_t data);
int (*global_expiration_timer) (int tid, int64 tick, int id, intptr_t data);
void (*expire_check) (struct map_session_data *sd);
-
+
/**
* Autotrade persistency [Ind/Hercules <3]
**/
diff --git a/src/map/pc_groups.c b/src/map/pc_groups.c
index e577c642f..9cd478b3f 100644
--- a/src/map/pc_groups.c
+++ b/src/map/pc_groups.c
@@ -420,6 +420,10 @@ void do_init_pc_groups(void) {
{ "disable_commands_when_dead", PC_PERM_DISABLE_CMD_DEAD },
{ "hchsys_admin", PC_PERM_HCHSYS_ADMIN },
{ "can_trade_bound", PC_PERM_TRADE_BOUND },
+ { "disable_pickup", PC_PERM_DISABLE_PICK_UP },
+ { "disable_store", PC_PERM_DISABLE_STORE },
+ { "disable_exp", PC_PERM_DISABLE_EXP },
+ { "disable_skill_usage", PC_PERM_DISABLE_SKILL_USAGE },
};
unsigned char i, len = ARRAYLENGTH(pc_g_defaults);
diff --git a/src/map/pc_groups.h b/src/map/pc_groups.h
index f52e2ba22..48ff782dd 100644
--- a/src/map/pc_groups.h
+++ b/src/map/pc_groups.h
@@ -35,6 +35,10 @@ enum e_pc_permission {
PC_PERM_DISABLE_CMD_DEAD = 0x100000,
PC_PERM_HCHSYS_ADMIN = 0x200000,
PC_PERM_TRADE_BOUND = 0x400000,
+ PC_PERM_DISABLE_PICK_UP = 0x800000,
+ PC_PERM_DISABLE_STORE = 0x1000000,
+ PC_PERM_DISABLE_EXP = 0x2000000,
+ PC_PERM_DISABLE_SKILL_USAGE = 0x4000000,
};
// Cached config settings for quick lookup
diff --git a/src/map/pet.c b/src/map/pet.c
index 9275a6de5..71dd39401 100644
--- a/src/map/pet.c
+++ b/src/map/pet.c
@@ -510,7 +510,7 @@ int pet_catch_process2(struct map_session_data* sd, int target_id) {
if (sd->catch_target_class == 0 && !(md->status.mode&MD_BOSS))
sd->catch_target_class = md->class_;
if(i < 0 || sd->catch_target_class != md->class_) {
- clif->emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them.
+ clif->emotion(&md->bl, E_AG); //mob will do /ag if wrong lure is used on them.
clif->pet_roulette(sd,0);
sd->catch_target_class = -1;
return 1;
@@ -688,10 +688,7 @@ int pet_equipitem(struct map_session_data *sd,int index) {
//Skotlex: start support timers if need
int64 tick = timer->gettick();
if (pd->s_skill && pd->s_skill->timer == INVALID_TIMER) {
- if (pd->s_skill->id)
- pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->skill_support_timer, sd->bl.id, 0);
- else
- pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->heal_timer, sd->bl.id, 0);
+ pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000, pet->skill_support_timer, sd->bl.id, 0);
}
if (pd->bonus && pd->bonus->timer == INVALID_TIMER)
pd->bonus->timer=timer->add(tick+pd->bonus->delay*1000, pet->skill_bonus_timer, sd->bl.id, 0);
@@ -725,12 +722,8 @@ int pet_unequipitem(struct map_session_data *sd, struct pet_data *pd) {
pd->state.skillbonus = 0;
status_calc_pc(sd,SCO_NONE);
}
- if( pd->s_skill && pd->s_skill->timer != INVALID_TIMER )
- {
- if( pd->s_skill->id )
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
+ if (pd->s_skill && pd->s_skill->timer != INVALID_TIMER) {
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
pd->s_skill->timer = INVALID_TIMER;
}
if( pd->bonus && pd->bonus->timer != INVALID_TIMER )
@@ -821,7 +814,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;
}
@@ -911,17 +904,18 @@ int pet_ai_sub_hard(struct pet_data *pd, struct map_session_data *sd, int64 tick
if (target->type != BL_ITEM)
{ //enemy targetted
- if(!battle->check_range(&pd->bl,target,pd->status.rhw.range))
- { //Chase
+ if(!battle->check_range(&pd->bl,target,pd->status.rhw.range)) {
+ //Chase
if(!unit->walktobl(&pd->bl, target, pd->status.rhw.range, 2))
pet->unlocktarget(pd); //Unreachable target.
return 0;
}
//Continuous attack.
unit->attack(&pd->bl, pd->target_id, 1);
- } else { //Item Targeted, attempt loot
- if (!check_distance_bl(&pd->bl, target, 1))
- { //Out of range
+ } else {
+ //Item Targeted, attempt loot
+ if (!check_distance_bl(&pd->bl, target, 1)) {
+ //Out of range
if(!unit->walktobl(&pd->bl, target, 1, 1)) //Unreachable target.
pet->unlocktarget(pd);
return 0;
@@ -1036,7 +1030,7 @@ int pet_lootitem_drop(struct pet_data *pd,struct map_session_data *sd)
memset(pd->loot->item,0,pd->loot->max * sizeof(struct item));
pd->loot->count = 0;
pd->loot->weight = 0;
- pd->ud.canact_tick = timer->gettick()+10000; //prevent picked up during 10*1000ms
+ pd->ud.canact_tick = timer->gettick()+10000; //prevent picked up during 10*1000ms
if (dlist->item)
timer->add(timer->gettick()+540,pet->delay_item_drop,0,(intptr_t)dlist);
@@ -1103,8 +1097,8 @@ int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
- if(sd->sc.data[pd->recovery->type])
- { //Display a heal animation?
+ if (sd->sc.data[pd->recovery->type]) {
+ //Display a heal animation?
//Detoxify is chosen for now.
clif->skill_nodamage(&pd->bl,&sd->bl,TF_DETOXIFY,1,1);
status_change_end(&sd->bl, pd->recovery->type, INVALID_TIMER);
@@ -1116,40 +1110,6 @@ int pet_recovery_timer(int tid, int64 tick, int id, intptr_t data) {
return 0;
}
-int pet_heal_timer(int tid, int64 tick, int id, intptr_t data) {
- struct map_session_data *sd=map->id2sd(id);
- struct status_data *st;
- struct pet_data *pd;
- unsigned int rate = 100;
-
- if(sd==NULL || sd->pd == NULL || sd->pd->s_skill == NULL)
- return 1;
-
- pd=sd->pd;
-
- if(pd->s_skill->timer != tid) {
- ShowError("pet_heal_timer %d != %d\n",pd->s_skill->timer,tid);
- return 0;
- }
-
- st = status->get_status_data(&sd->bl);
-
- if(pc_isdead(sd) ||
- (rate = get_percentage(st->sp, st->max_sp)) > pd->s_skill->sp ||
- (rate = get_percentage(st->hp, st->max_hp)) > pd->s_skill->hp ||
- (rate = (pd->ud.skilltimer != INVALID_TIMER)) //Another skill is in effect
- ) { //Wait (how long? 1 sec for every 10% of remaining)
- pd->s_skill->timer=timer->add(timer->gettick()+(rate>10?rate:10)*100,pet->heal_timer,sd->bl.id,0);
- return 0;
- }
- pet_stop_attack(pd);
- pet_stop_walking(pd,1);
- clif->skill_nodamage(&pd->bl,&sd->bl,AL_HEAL,pd->s_skill->lv,1);
- status->heal(&sd->bl, pd->s_skill->lv,0, 0);
- pd->s_skill->timer=timer->add(tick+pd->s_skill->delay*1000,pet->heal_timer,sd->bl.id,0);
- return 0;
-}
-
/*==========================================
* pet support skills [Skotlex]
*------------------------------------------*/
@@ -1170,8 +1130,8 @@ int pet_skill_support_timer(int tid, int64 tick, int id, intptr_t data) {
st = status->get_status_data(&sd->bl);
- if (DIFF_TICK(pd->ud.canact_tick, tick) > 0)
- { //Wait until the pet can act again.
+ if (DIFF_TICK(pd->ud.canact_tick, tick) > 0) {
+ //Wait until the pet can act again.
pd->s_skill->timer=timer->add(pd->ud.canact_tick,pet->skill_support_timer,sd->bl.id,0);
return 0;
}
@@ -1360,7 +1320,6 @@ int do_init_pet(bool minimal) {
timer->add_func_list(pet->delay_item_drop,"pet_delay_item_drop");
timer->add_func_list(pet->skill_support_timer, "pet_skill_support_timer"); // [Skotlex]
timer->add_func_list(pet->recovery_timer,"pet_recovery_timer"); // [Valaris]
- timer->add_func_list(pet->heal_timer,"pet_heal_timer"); // [Valaris]
timer->add_interval(timer->gettick()+MIN_PETTHINKTIME,pet->ai_hard,0,0,MIN_PETTHINKTIME);
return 0;
@@ -1432,7 +1391,6 @@ void pet_defaults(void) {
pet->lootitem_drop = pet_lootitem_drop;
pet->skill_bonus_timer = pet_skill_bonus_timer;
pet->recovery_timer = pet_recovery_timer;
- pet->heal_timer = pet_heal_timer;
pet->skill_support_timer = pet_skill_support_timer;
pet->read_db = read_petdb;
}
diff --git a/src/map/pet.h b/src/map/pet.h
index 5c890ef85..cffcf7dd0 100644
--- a/src/map/pet.h
+++ b/src/map/pet.h
@@ -41,16 +41,16 @@ struct s_pet_db {
enum { PET_CLASS,PET_CATCH,PET_EGG,PET_EQUIP,PET_FOOD };
struct pet_recovery { //Stat recovery
- enum sc_type type; //Status Change id
- unsigned short delay; //How long before curing (secs).
+ enum sc_type type; ///< Status Change id
+ unsigned short delay; ///< How long before curing (secs).
int timer;
};
struct pet_bonus {
- unsigned short type; //bStr, bVit?
- unsigned short val; //Qty
+ unsigned short type; //bStr, bVit?
+ unsigned short val; //Qty
unsigned short duration; //in secs
- unsigned short delay; //Time before RENEWAL_CAST (secs)
+ unsigned short delay; //Time before RENEWAL_CAST (secs)
int timer;
};
@@ -93,7 +93,7 @@ struct pet_data {
} state;
int move_fail_count;
int64 next_walktime, last_thinktime;
- short rate_fix; //Support rate as modified by intimacy (1000 = 100%) [Skotlex]
+ short rate_fix; //Support rate as modified by intimacy (1000 = 100%) [Skotlex]
struct pet_recovery* recovery;
struct pet_bonus* bonus;
@@ -149,7 +149,6 @@ struct pet_interface {
int (*lootitem_drop) (struct pet_data *pd, struct map_session_data *sd);
int (*skill_bonus_timer) (int tid, int64 tick, int id, intptr_t data);
int (*recovery_timer) (int tid, int64 tick, int id, intptr_t data);
- int (*heal_timer) (int tid, int64 tick, int id, intptr_t data);
int (*skill_support_timer) (int tid, int64 tick, int id, intptr_t data);
int (*read_db) ();
};
diff --git a/src/map/script.c b/src/map/script.c
index ecd12a3c1..031dfc21b 100644
--- a/src/map/script.c
+++ b/src/map/script.c
@@ -55,6 +55,7 @@
#include "../common/sysinfo.h"
#include "../common/timer.h"
#include "../common/utils.h"
+#include "../common/HPM.h"
#ifndef WIN32
#include <sys/time.h>
@@ -140,7 +141,7 @@ static void script_dump_stack(struct script_state* st)
for( i = 0; i < st->stack->sp; ++i )
{
struct script_data* data = &st->stack->stack_data[i];
- ShowMessage("\t[%d] %s", i, script_op2name(data->type));
+ ShowMessage("\t[%d] %s", i, script->op2name(data->type));
switch( data->type )
{
case C_INT:
@@ -154,7 +155,7 @@ static void script_dump_stack(struct script_state* st)
break;
case C_NAME:
- ShowMessage(" \"%s\" (id=%d ref=%p subtype=%s)\n", reference_getname(data), data->u.num, data->ref, script_op2name(script->str_data[data->u.num].type));
+ ShowMessage(" \"%s\" (id=%d ref=%p subtype=%s)\n", reference_getname(data), data->u.num, data->ref, script->op2name(script->str_data[data->u.num].type));
break;
case C_RETINFO:
@@ -526,7 +527,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 +773,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 +1352,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 +1434,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 +1505,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 +1544,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 +1597,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 +1634,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 +1736,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 +1753,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 +1777,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 +1787,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 +1810,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 +1878,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 +1886,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 +1894,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 +1920,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 +1932,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);
@@ -2908,7 +2866,7 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co
}
} else {
ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name);
- script_reportsrc(st);
+ script->reportsrc(st);
}
return 1;
default:
@@ -2974,7 +2932,7 @@ int set_reg(struct script_state* st, TBL_PC* sd, int64 num, const char* name, co
}
} else {
ShowError("script_set_reg: cannot write instance variable '%s', NPC not in a instance!\n", name);
- script_reportsrc(st);
+ script->reportsrc(st);
}
return 1;
default:
@@ -4184,7 +4142,9 @@ int script_config_read(char *cfgName) {
else if(strcmpi(w1,"import")==0) {
script->config_read(w2);
}
- else {
+ else if(HPM->parseConf(w1, w2, HPCT_SCRIPT)) {
+ ; // handled by plugin
+ } else {
ShowWarning("Unknown setting '%s' in file %s\n", w1, cfgName);
}
}
@@ -5681,7 +5641,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 +5651,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 +5662,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 +5672,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 +5699,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 +5711,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 +6973,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 +6999,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 +7030,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;
@@ -7407,6 +7362,49 @@ BUILDIN(getguildmasterid)
}
/*==========================================
+ * Get the information of the members of a guild by type.
+ * getguildmember <guild_id>{,<type>};
+ * @param guild_id: ID of guild
+ * @param type:
+ * 0 : name (default)
+ * 1 : character ID
+ * 2 : account ID
+ *------------------------------------------*/
+BUILDIN(getguildmember)
+{
+ struct guild *g = NULL;
+ int j = 0;
+
+ g = guild->search(script_getnum(st,2));
+
+ if (g) {
+ int i, type = 0;
+
+ if (script_hasdata(st,3))
+ type = script_getnum(st,3);
+
+ for ( i = 0; i < MAX_GUILD; i++ ) {
+ if ( g->member[i].account_id ) {
+ switch (type) {
+ case 2:
+ mapreg->setreg(reference_uid(script->add_str("$@guildmemberaid"), j),g->member[i].account_id);
+ break;
+ case 1:
+ mapreg->setreg(reference_uid(script->add_str("$@guildmembercid"), j), g->member[i].char_id);
+ break;
+ default:
+ mapreg->setregstr(reference_uid(script->add_str("$@guildmembername$"), j), g->member[i].name);
+ break;
+ }
+ j++;
+ }
+ }
+ }
+ mapreg->setreg(script->add_str("$@guildmembercount"), j);
+ return true;
+}
+
+/*==========================================
* Get char string information by type :
* Return by @type :
* 0 : char_name
@@ -7615,6 +7613,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)
@@ -8569,10 +8590,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);
@@ -8587,59 +8608,147 @@ 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);
return true;
}
-/// Returns if the player is riding.
-///
-/// checkriding() -> <bool>
-///
-/// @author Valaris
-BUILDIN(checkriding)
+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 (sd == NULL)
+ return true; // no player attached, report source
- if( pc_isriding(sd) || pc_isridingwug(sd) || pc_isridingdragon(sd) )
- script_pushint(st, 1);
- else
- script_pushint(st, 0);
+ 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;
}
-/// Sets if the player is riding.
-/// <flag> defaults to 1
-///
-/// setriding <flag>;
-/// setriding;
-BUILDIN(setriding)
+/**
+ * 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 = 1;
+ int flag = SETMOUNT_TYPE_AUTODETECT;
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);
+
+ // 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;
}
@@ -8664,47 +8773,6 @@ BUILDIN(checkwug)
return true;
}
-/// Returns if the player is wearing MADO Gear.
-///
-/// checkmadogear() -> <bool>
-///
-BUILDIN(checkmadogear)
-{
- TBL_PC* sd;
-
- sd = script->rid2sd(st);
- if( sd == NULL )
- return true;// no player attached, report source
-
- if( pc_ismadogear(sd) )
- script_pushint(st, 1);
- else
- script_pushint(st, 0);
-
- return true;
-}
-
-/// Sets if the player is riding MADO Gear.
-/// <flag> defaults to 1
-///
-/// setmadogear <flag>;
-/// setmadogear;
-BUILDIN(setmadogear)
-{
- int flag = 1;
- 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);
- pc->setmadogear(sd, flag);
-
- return true;
-}
-
/// Sets the save point of the player.
///
/// save "<map name>",<x>,<y>
@@ -9029,7 +9097,7 @@ BUILDIN(monster)
int class_ = script_getnum(st,6);
int amount = script_getnum(st,7);
const char *event = "";
- unsigned int size = SZ_MEDIUM;
+ unsigned int size = SZ_SMALL;
unsigned int ai = AI_NONE;
int mob_id;
@@ -9138,7 +9206,7 @@ BUILDIN(areamonster) {
int class_ = script_getnum(st,8);
int amount = script_getnum(st,9);
const char *event = "";
- unsigned int size = SZ_MEDIUM;
+ unsigned int size = SZ_SMALL;
unsigned int ai = AI_NONE;
int mob_id;
@@ -9939,22 +10007,62 @@ int buildin_getareausers_sub(struct block_list *bl,va_list ap)
(*users)++;
return 0;
}
+
BUILDIN(getareausers)
{
- const char *str;
- int16 m,x0,y0,x1,y1,users=0; //doubt we can have more then 32k users on
- str=script_getstr(st,2);
- x0=script_getnum(st,3);
- y0=script_getnum(st,4);
- x1=script_getnum(st,5);
- y1=script_getnum(st,6);
- if( (m=map->mapname2mapid(str))< 0) {
- script_pushint(st,-1);
- return true;
+ int16 m = -1, x0, y0, x1, y1;
+ int users = 0;
+ int idx = 2;
+
+ if (script_hasdata(st, 2) && script_isstringtype(st, 2)) {
+ const char *str = script_getstr(st, 2);
+ if ((m = map->mapname2mapid(str)) < 0) {
+ script_pushint(st, -1);
+ return true;
+ }
+ idx = 3;
+ } else {
+ TBL_PC *sd = script->rid2sd(st);
+ if (!sd) {
+ script_pushint(st, -1);
+ return false;
+ }
+ m = sd->bl.m;
+ }
+
+ if (script_hasdata(st, idx + 3)) {
+ x0 = script_getnum(st, idx + 0);
+ y0 = script_getnum(st, idx + 1);
+ x1 = script_getnum(st, idx + 2);
+ y1 = script_getnum(st, idx + 3);
+ } else if (st->oid) {
+ struct npc_data *nd = map->id2nd(st->oid);
+ if (!nd) {
+ script_pushint(st, -1);
+ return true;
+ }
+ if (script_hasdata(st, idx)) {
+ int range = script_getnum(st, idx);
+ x0 = nd->bl.x - range;
+ y0 = nd->bl.y - range;
+ x1 = nd->bl.x + range;
+ y1 = nd->bl.y + range;
+ } else if (nd->u.scr.xs != -1 && nd->u.scr.ys != -1) {
+ x0 = nd->bl.x - nd->u.scr.xs;
+ y0 = nd->bl.y - nd->u.scr.ys;
+ x1 = nd->bl.x + nd->u.scr.xs;
+ y1 = nd->bl.y + nd->u.scr.ys;
+ } else {
+ script_pushint(st, -1);
+ return true;
+ }
+ } else {
+ script_pushint(st, -1);
+ return false;
}
map->foreachinarea(script->buildin_getareausers_sub,
- m,x0,y0,x1,y1,BL_PC,&users);
- script_pushint(st,users);
+ m, x0, y0, x1, y1, BL_PC, &users);
+ script_pushint(st, users);
return true;
}
@@ -10039,117 +10147,74 @@ BUILDIN(hideonnpc)
return true;
}
-/// Starts a status effect on the target unit or on the attached player.
-///
-/// sc_start <effect_id>,<duration>,<val1>{,<unit_id>};
+/* Starts a status effect on the target unit or on the attached player.
+ *
+ * sc_start <effect_id>,<duration>,<val1>{,<rate>,<flag>,{<unit_id>}};
+ * sc_start2 <effect_id>,<duration>,<val1>,<val2>{,<rate,<flag>,{<unit_id>}};
+ * sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<rate,<flag>,{<unit_id>}};
+ * <flag>: @see enum scstart_flag
+ */
BUILDIN(sc_start) {
+ TBL_NPC * nd = map->id2nd(st->oid);
struct block_list* bl;
enum sc_type type;
- int tick;
- int val1;
- int val4 = 0;
+ int tick, val1, val2, val3, val4=0, rate, flag;
+ char start_type;
+ const char* command = script->getfuncname(st);
+
+ if(strstr(command, "4"))
+ start_type = 4;
+ else if(strstr(command, "2"))
+ start_type = 2;
+ else
+ start_type = 1;
type = (sc_type)script_getnum(st,2);
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
- if( script_hasdata(st,5) )
- bl = map->id2bl(script_getnum(st,5));
- else
- bl = map->id2bl(st->rid);
-
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
- // When there isn't a duration specified, try to get it from the skill_db
- tick = skill->get_time(status->sc2skill(type), val1);
- }
- if( script->potion_flag == 1 && script->potion_target ) {
- //skill.c set the flags before running the script, this must be a potion-pitched effect.
- bl = map->id2bl(script->potion_target);
- tick /= 2;// Thrown potions only last half.
- val4 = 1;// Mark that this was a thrown sc_effect
- }
-
- if( bl )
- status->change_start(NULL, bl, type, 10000, val1, 0, 0, val4, tick, 2);
+ //If from NPC we make default flag SCFLAG_NOAVOID to be unavoidable
+ if(nd && nd->bl.id == npc->fake_nd->bl.id)
+ flag = script_hasdata(st,5+start_type) ? script_getnum(st,5+start_type) : SCFLAG_FIXEDTICK;
+ else
+ flag = script_hasdata(st,5+start_type) ? script_getnum(st,5+start_type) : SCFLAG_NOAVOID;
- return true;
-}
+ rate = script_hasdata(st,4+start_type)?min(script_getnum(st,4+start_type),10000):10000;
-/// Starts a status effect on the target unit or on the attached player.
-///
-/// sc_start2 <effect_id>,<duration>,<val1>,<percent chance>{,<unit_id>};
-BUILDIN(sc_start2) {
- struct block_list* bl;
- enum sc_type type;
- int tick;
- int val1;
- int val4 = 0;
- int rate;
-
- type = (sc_type)script_getnum(st,2);
- tick = script_getnum(st,3);
- val1 = script_getnum(st,4);
- rate = script_getnum(st,5);
- if( script_hasdata(st,6) )
- bl = map->id2bl(script_getnum(st,6));
+ if(script_hasdata(st,(6+start_type)))
+ bl = map->id2bl(script_getnum(st,(6+start_type)));
else
bl = map->id2bl(st->rid);
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
- // When there isn't a duration specified, try to get it from the skill_db
+ if(tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0)
+ {// When there isn't a duration specified, try to get it from the skill_db
tick = skill->get_time(status->sc2skill(type), val1);
}
- if( script->potion_flag == 1 && script->potion_target ) {
- //skill.c set the flags before running the script, this must be a potion-pitched effect.
+ if(script->potion_flag == 1 && script->potion_target) { //skill.c set the flags before running the script, this is a potion-pitched effect.
bl = map->id2bl(script->potion_target);
tick /= 2;// Thrown potions only last half.
val4 = 1;// Mark that this was a thrown sc_effect
}
- if( bl )
- status->change_start(NULL, bl, type, rate, val1, 0, 0, val4, tick, 2);
-
- return true;
-}
-
-/// Starts a status effect on the target unit or on the attached player.
-///
-/// sc_start4 <effect_id>,<duration>,<val1>,<val2>,<val3>,<val4>{,<unit_id>};
-BUILDIN(sc_start4) {
- struct block_list* bl;
- enum sc_type type;
- int tick;
- int val1;
- int val2;
- int val3;
- int val4;
-
- type = (sc_type)script_getnum(st,2);
- tick = script_getnum(st,3);
- val1 = script_getnum(st,4);
- val2 = script_getnum(st,5);
- val3 = script_getnum(st,6);
- val4 = script_getnum(st,7);
- if( script_hasdata(st,8) )
- bl = map->id2bl(script_getnum(st,8));
- else
- bl = map->id2bl(st->rid);
-
- if( tick == 0 && val1 > 0 && type > SC_NONE && type < SC_MAX && status->sc2skill(type) != 0 ) {
- // When there isn't a duration specified, try to get it from the skill_db
- tick = skill->get_time(status->sc2skill(type), val1);
- }
+ if(!bl)
+ return true;
- if( script->potion_flag == 1 && script->potion_target ) {
- //skill.c set the flags before running the script, this must be a potion-pitched effect.
- bl = map->id2bl(script->potion_target);
- tick /= 2;// Thrown potions only last half.
+ switch(start_type) {
+ case 1:
+ status->change_start(bl, bl, type, rate, val1, 0, 0, val4, tick, flag);
+ break;
+ case 2:
+ val2 = script_getnum(st,5);
+ status->change_start(bl, bl, type, rate, val1, val2, 0, val4, tick, flag);
+ break;
+ case 4:
+ val2 = script_getnum(st,5);
+ val3 = script_getnum(st,6);
+ val4 = script_getnum(st,7);
+ status->change_start(bl, bl, type, rate, val1, val2, val3, val4, tick, flag);
+ break;
}
-
- if( bl )
- status->change_start(NULL, bl, type, 10000, val1, val2, val3, val4, tick, 2);
-
return true;
}
@@ -10215,7 +10280,7 @@ BUILDIN(getscrate) {
bl = map->id2bl(st->rid);
if (bl)
- rate = status->get_sc_def(bl, bl, (sc_type)type, 10000, 10000, 0);
+ rate = status->get_sc_def(bl, bl, (sc_type)type, 10000, 10000, SCFLAG_NONE);
script_pushint(st,rate);
return true;
@@ -10568,40 +10633,57 @@ BUILDIN(changebase) {
return true;
}
- if(sd->disguise == -1 && vclass != sd->vd.class_) {
- status->set_viewdata(&sd->bl, vclass);
- //Updated client view. Base, Weapon and Cloth Colors.
- clif->changelook(&sd->bl,LOOK_BASE,sd->vd.class_);
- clif->changelook(&sd->bl,LOOK_WEAPON,sd->status.weapon);
- if (sd->vd.cloth_color)
- clif->changelook(&sd->bl,LOOK_CLOTHES_COLOR,sd->vd.cloth_color);
- clif->skillinfoblock(sd);
- }
+ if(sd->disguise == -1 && vclass != sd->vd.class_)
+ pc->changelook(sd,LOOK_BASE,vclass); //Updated client view. Base, Weapon and Cloth Colors.
return true;
}
+static TBL_PC *prepareChangeSex(struct script_state* st)
+{
+ int i;
+ TBL_PC *sd = script->rid2sd(st);
+
+ if (sd == NULL)
+ return NULL;
+
+ pc->resetskill(sd, 4);
+ // to avoid any problem with equipment and invalid sex, equipment is unequiped.
+ for (i=0; i<EQI_MAX; i++)
+ if (sd->equip_index[i] >= 0) pc->unequipitem(sd, sd->equip_index[i], 3);
+ return sd;
+}
+
/*==========================================
* Unequip all item and request for a changesex to char-serv
*------------------------------------------*/
BUILDIN(changesex)
{
- int i;
- TBL_PC *sd = NULL;
- sd = script->rid2sd(st);
-
- if( sd == NULL )
+ TBL_PC *sd = prepareChangeSex(st);
+ if (sd == NULL)
return false;
-
- pc->resetskill(sd,4);
- // to avoid any problem with equipment and invalid sex, equipment is unequiped.
- for( i=0; i<EQI_MAX; i++ )
- if( sd->equip_index[i] >= 0 ) pc->unequipitem(sd, sd->equip_index[i], 3);
chrif->changesex(sd);
return true;
}
/*==========================================
+ * Unequip all items and change character sex [4144]
+ *------------------------------------------*/
+BUILDIN(changecharsex)
+{
+ TBL_PC *sd = prepareChangeSex(st);
+ if (sd == NULL)
+ return false;
+ if (sd->status.sex == 99)
+ sd->status.sex = 0;
+ sd->status.sex = sd->status.sex ? 0 : 1;
+ chrif->save(sd, 0);
+ if (sd->fd)
+ clif->authfail_fd(sd->fd, 15);
+ return true;
+}
+
+/*==========================================
* Works like 'announce' but outputs in the common chat window
*------------------------------------------*/
BUILDIN(globalmes) {
@@ -12315,23 +12397,26 @@ BUILDIN(petloot)
* @inventorylist_card(0..3), @inventorylist_expire
* @inventorylist_count = scalar
*------------------------------------------*/
-BUILDIN(getinventorylist)
-{
+BUILDIN(getinventorylist){
TBL_PC *sd=script->rid2sd(st);
char card_var[NAME_LENGTH];
int i,j=0,k;
if(!sd) return true;
+
for(i=0;i<MAX_INVENTORY;i++) {
if(sd->status.inventory[i].nameid > 0 && sd->status.inventory[i].amount > 0) {
pc->setreg(sd,reference_uid(script->add_str("@inventorylist_id"), j),sd->status.inventory[i].nameid);
pc->setreg(sd,reference_uid(script->add_str("@inventorylist_amount"), j),sd->status.inventory[i].amount);
- pc->setreg(sd,reference_uid(script->add_str("@inventorylist_equip"), j),sd->status.inventory[i].equip);
+ if(sd->status.inventory[i].equip) {
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_equip"), j),pc->equippoint(sd,i));
+ } else {
+ pc->setreg(sd,reference_uid(script->add_str("@inventorylist_equip"), j),0);
+ }
pc->setreg(sd,reference_uid(script->add_str("@inventorylist_refine"), j),sd->status.inventory[i].refine);
pc->setreg(sd,reference_uid(script->add_str("@inventorylist_identify"), j),sd->status.inventory[i].identify);
pc->setreg(sd,reference_uid(script->add_str("@inventorylist_attribute"), j),sd->status.inventory[i].attribute);
- for (k = 0; k < MAX_SLOTS; k++)
- {
+ for (k = 0; k < MAX_SLOTS; k++) {
sprintf(card_var, "@inventorylist_card%d",k+1);
pc->setreg(sd,reference_uid(script->add_str(card_var), j),sd->status.inventory[i].card[k]);
}
@@ -12344,6 +12429,34 @@ BUILDIN(getinventorylist)
return true;
}
+BUILDIN(getcartinventorylist){
+ TBL_PC *sd=script->rid2sd(st);
+ char card_var[NAME_LENGTH];
+
+ int i,j=0,k;
+ if(!sd) return true;
+
+ for(i=0;i<MAX_CART;i++) {
+ if(sd->status.cart[i].nameid > 0 && sd->status.cart[i].amount > 0) {
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_id"), j),sd->status.cart[i].nameid);
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_amount"), j),sd->status.cart[i].amount);
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_equip"), j),sd->status.cart[i].equip);
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_refine"), j),sd->status.cart[i].refine);
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_identify"), j),sd->status.cart[i].identify);
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_attribute"), j),sd->status.cart[i].attribute);
+ for (k = 0; k < MAX_SLOTS; k++) {
+ sprintf(card_var, "@cartinventorylist_card%d",k+1);
+ pc->setreg(sd,reference_uid(script->add_str(card_var), j),sd->status.cart[i].card[k]);
+ }
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_expire"), j),sd->status.cart[i].expire_time);
+ pc->setreg(sd,reference_uid(script->add_str("@cartinventorylist_bound"), j),sd->status.cart[i].bound);
+ j++;
+ }
+ }
+ pc->setreg(sd,script->add_str("@cartinventorylist_count"),j);
+ return true;
+}
+
BUILDIN(getskilllist)
{
TBL_PC *sd=script->rid2sd(st);
@@ -12629,46 +12742,6 @@ BUILDIN(petrecovery)
}
/*==========================================
- * pet healing [Valaris] //Rewritten by [Skotlex]
- *------------------------------------------*/
-BUILDIN(petheal)
-{
- struct pet_data *pd;
- TBL_PC *sd=script->rid2sd(st);
-
- if(sd==NULL || sd->pd==NULL)
- return true;
-
- pd=sd->pd;
- if (pd->s_skill)
- { //Clear previous skill
- if (pd->s_skill->timer != INVALID_TIMER)
- {
- if (pd->s_skill->id)
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
- }
- } else //init memory
- pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
-
- pd->s_skill->id=0; //This id identifies that it IS petheal rather than pet_skillsupport
- //Use the lv as the amount to heal
- pd->s_skill->lv=script_getnum(st,2);
- pd->s_skill->delay=script_getnum(st,3);
- pd->s_skill->hp=script_getnum(st,4);
- pd->s_skill->sp=script_getnum(st,5);
-
- //Use delay as initial offset to avoid skill/heal exploits
- if (battle_config.pet_equip_required && pd->pet.equip == 0)
- pd->s_skill->timer = INVALID_TIMER;
- else
- pd->s_skill->timer = timer->add(timer->gettick()+pd->s_skill->delay*1000,pet->heal_timer,sd->bl.id,0);
-
- return true;
-}
-
-/*==========================================
* pet attack skills [Valaris] //Rewritten by [Skotlex]
*------------------------------------------*/
/// petskillattack <skill id>,<level>,<rate>,<bonusrate>
@@ -12731,17 +12804,15 @@ BUILDIN(petskillsupport) {
return true;
pd=sd->pd;
- if (pd->s_skill)
- { //Clear previous skill
- if (pd->s_skill->timer != INVALID_TIMER)
- {
- if (pd->s_skill->id)
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
+ if (pd->s_skill) {
+ //Clear previous skill
+ if (pd->s_skill->timer != INVALID_TIMER) {
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
}
- } else //init memory
+ } else {
+ //init memory
pd->s_skill = (struct pet_skill_support *) aMalloc(sizeof(struct pet_skill_support));
+ }
pd->s_skill->id=( script_isstringtype(st,2) ? skill->name2id(script_getstr(st,2)) : script_getnum(st,2) );
pd->s_skill->lv=script_getnum(st,3);
@@ -13094,14 +13165,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;
}
@@ -13220,6 +13291,112 @@ BUILDIN(npcstop) {
return true;
}
+// set click npc distance [4144]
+BUILDIN(setnpcdistance) {
+ struct npc_data *nd = (struct npc_data *) map->id2bl (st->oid);
+ if (!nd)
+ return false;
+
+ nd->area_size = script_getnum(st, 2);
+
+ return true;
+}
+
+// return current npc direction [4144]
+BUILDIN(getnpcdir)
+{
+ struct npc_data *nd = 0;
+
+ if (script_hasdata(st, 2))
+ {
+ nd = npc->name2id (script_getstr(st, 2));
+ }
+ if (!nd && !st->oid)
+ {
+ script_pushint(st, -1);
+ return true;
+ }
+
+ if (!nd)
+ nd = (struct npc_data *) map->id2bl (st->oid);
+
+ if (!nd)
+ {
+ script_pushint(st, -1);
+ return true;
+ }
+
+ script_pushint(st, (int)nd->dir);
+
+ return true;
+}
+
+// set npc direction [4144]
+BUILDIN(setnpcdir)
+{
+ int newdir;
+ struct npc_data *nd = 0;
+
+ if (script_hasdata(st, 3))
+ {
+ nd = npc->name2id (script_getstr(st, 2));
+ newdir = script_getnum(st, 3);
+ }
+ else if (script_hasdata(st, 2))
+ {
+ if (!st->oid)
+ return false;
+
+ nd = (struct npc_data *) map->id2bl (st->oid);
+ newdir = script_getnum(st, 2);
+ }
+ if (!nd)
+ return false;
+
+ if (newdir < 0)
+ newdir = 0;
+ else if (newdir > 7)
+ newdir = 7;
+
+ nd->dir = newdir;
+ if (nd->ud)
+ nd->ud->dir = newdir;
+
+ clif->clearunit_area(&nd->bl, CLR_OUTSIGHT);
+ clif->spawn(&nd->bl);
+
+ return true;
+}
+
+// return npc class [4144]
+BUILDIN(getnpcclass)
+{
+ struct npc_data *nd = 0;
+
+ if (script_hasdata(st, 2))
+ {
+ nd = npc->name2id (script_getstr(st, 2));
+ }
+ if (!nd && !st->oid)
+ {
+ script_pushint(st, -1);
+ return false;
+ }
+
+ if (!nd)
+ nd = (struct npc_data *) map->id2bl(st->oid);
+
+ if (!nd)
+ {
+ script_pushint(st, -1);
+ return false;
+ }
+
+ script_pushint(st, (int)nd->class_);
+
+ return true;
+}
+
/*==========================================
* getlook char info. getlook(arg)
@@ -13496,7 +13673,7 @@ BUILDIN(summon)
clif->skill_poseffect(&sd->bl,AM_CALLHOMUN,1,sd->bl.x,sd->bl.y,tick);
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, sd->bl.x, sd->bl.y, str, class_, event, SZ_SMALL, AI_NONE);
if (md) {
md->master_id=sd->bl.id;
md->special_state.ai = AI_ATTACK;
@@ -13791,6 +13968,57 @@ BUILDIN(autoequip)
return true;
}
+/*=======================================================
+ * Equip2
+ * equip2 <item id>,<refine>,<attribute>,<card1>,<card2>,<card3>,<card4>;
+ *-------------------------------------------------------*/
+BUILDIN(equip2)
+{
+ int i,nameid,ref,attr,c0,c1,c2,c3;
+ struct item_data *item_data;
+ TBL_PC *sd;
+
+ sd = script->rid2sd(st);
+
+ if ( sd == NULL ) {
+ script_pushint(st,0);
+ return true;
+ }
+
+ nameid = script_getnum(st,2);
+ if( (item_data = itemdb->exists(nameid)) == NULL )
+ {
+ ShowError("Wrong item ID : equip2(%i)\n",nameid);
+ script_pushint(st,0);
+ return false;
+ }
+
+ ref = script_getnum(st,3);
+ attr = script_getnum(st,4);
+ c0 = (short)script_getnum(st,5);
+ c1 = (short)script_getnum(st,6);
+ c2 = (short)script_getnum(st,7);
+ c3 = (short)script_getnum(st,8);
+
+ ARR_FIND( 0, MAX_INVENTORY, i,( sd->status.inventory[i].equip == 0 &&
+ sd->status.inventory[i].nameid == nameid &&
+ sd->status.inventory[i].refine == ref &&
+ sd->status.inventory[i].attribute == attr &&
+ sd->status.inventory[i].card[0] == c0 &&
+ sd->status.inventory[i].card[1] == c1 &&
+ sd->status.inventory[i].card[2] == c2 &&
+ sd->status.inventory[i].card[3] == c3 ) );
+
+ if( i < MAX_INVENTORY ) {
+ script_pushint(st,1);
+ pc->equipitem(sd,i,item_data->equip);
+ }
+ else
+ script_pushint(st,0);
+
+ return true;
+}
+
BUILDIN(setbattleflag)
{
const char *flag, *value;
@@ -14499,7 +14727,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 +14957,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 +15916,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);
}
@@ -15909,8 +16165,7 @@ BUILDIN(warpportal) {
struct block_list* bl;
bl = map->id2bl(st->oid);
- if( bl == NULL )
- {
+ if( bl == NULL ) {
ShowError("script:warpportal: npc is needed\n");
return false;
}
@@ -15924,6 +16179,9 @@ BUILDIN(warpportal) {
if( map_index == 0 )
return true;// map not found
+ if( bl->type == BL_NPC )
+ unit->bl2ud2(bl); // ensure nd->ud is safe to edit
+
group = skill->unitsetting(bl, AL_WARP, 4, spx, spy, 0);
if( group == NULL )
return true;// failed
@@ -16058,7 +16316,7 @@ BUILDIN(mercenary_sc_start) {
tick = script_getnum(st,3);
val1 = script_getnum(st,4);
- status->change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, 2);
+ status->change_start(NULL, &sd->md->bl, type, 10000, val1, 0, 0, 0, tick, SCFLAG_FIXEDTICK);
return true;
}
@@ -16281,21 +16539,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;
}
@@ -16309,17 +16591,46 @@ BUILDIN(changequest) {
return true;
}
-BUILDIN(checkquest) {
+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 )
+ if (sd == NULL)
return false;
- if( script_hasdata(st, 3) )
+ if (script_hasdata(st, 3))
type = (enum quest_check_type)script_getnum(st, 3);
- script_pushint(st, quest->check(sd, script_getnum(st, 2), type));
+ 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;
}
@@ -16977,6 +17288,63 @@ BUILDIN(instance_check_party) {
}
/*==========================================
+ * instance_check_guild
+ * Values:
+ * guild_id : Guild ID of the invoking character. [Required Parameter]
+ * amount : Amount of needed Guild Members for the Instance. [Optional Parameter]
+ * min : Minimum Level needed to join the Instance. [Optional Parameter]
+ * max : Maxium Level allowed to join the Instance. [Optional Parameter]
+ * Example: instance_check_guild (getcharid(2){,amount}{,min}{,max});
+ * Example 2: instance_check_guild (getcharid(2),1,1,99);
+ *------------------------------------------*/
+BUILDIN(instance_check_guild){
+ struct map_session_data *pl_sd;
+ int amount, min, max, i, guild_id, c = 0;
+ struct guild *g = NULL;
+
+ amount = script_hasdata(st,3) ? script_getnum(st,3) : 1;
+ min = script_hasdata(st,4) ? script_getnum(st,4) : 1;
+ max = script_hasdata(st,5) ? script_getnum(st,5) : MAX_LEVEL;
+
+ if( min < 1 || min > MAX_LEVEL ){
+ ShowError("instance_check_guild: Invalid min level, %d\n", min);
+ return true;
+ } else if( max < 1 || max > MAX_LEVEL ){
+ ShowError("instance_check_guild: Invalid max level, %d\n", max);
+ return true;
+ }
+
+ if( script_hasdata(st,2) )
+ guild_id = script_getnum(st,2);
+ else return true;
+
+ if( !(g = guild->search(guild_id)) ){
+ script_pushint(st,0);
+ return true;
+ }
+
+ for( i = 0; i < MAX_GUILD; i++ )
+ if( (pl_sd = g->member[i].sd) )
+ if( map->id2bl(pl_sd->bl.id) ){
+ if( pl_sd->status.base_level < min ){
+ script_pushint(st,0);
+ return true;
+ } else if( pl_sd->status.base_level > max ){
+ script_pushint(st,0);
+ return true;
+ }
+ c++;
+ }
+
+ if( c < amount )
+ script_pushint(st,0);
+ else
+ script_pushint(st,1);
+
+ return true;
+}
+
+/*==========================================
* Custom Fonts
*------------------------------------------*/
BUILDIN(setfont)
@@ -17215,63 +17583,12 @@ BUILDIN(makerune) {
sd->itemid = script_getnum(st,2);
return true;
}
-/**
- * checkdragon() returns 1 if mounting a dragon or 0 otherwise.
- **/
-BUILDIN(checkdragon) {
- TBL_PC* sd;
- if( (sd = script->rid2sd(st)) == NULL )
- return true;
- if( pc_isridingdragon(sd) )
- script_pushint(st,1);
- else
- script_pushint(st,0);
- return true;
-}
-/**
- * setdragon({optional Color}) returns 1 on success or 0 otherwise
- * - Toggles the dragon on a RK if he can mount;
- * @param Color - when not provided uses the green dragon;
- * - 1 : Green Dragon
- * - 2 : Brown Dragon
- * - 3 : Gray Dragon
- * - 4 : Blue Dragon
- * - 5 : Red Dragon
- **/
-BUILDIN(setdragon) {
- TBL_PC* sd;
- int color = script_hasdata(st,2) ? script_getnum(st,2) : 0;
-
- if( (sd = script->rid2sd(st)) == NULL )
- return true;
- if( !pc->checkskill(sd,RK_DRAGONTRAINING) || (sd->class_&MAPID_THIRDMASK) != MAPID_RUNE_KNIGHT )
- script_pushint(st,0);//Doesn't have the skill or it's not a Rune Knight
- else if ( pc_isridingdragon(sd) ) {//Is mounted; release
- pc->setoption(sd, sd->sc.option&~OPTION_DRAGON);
- script_pushint(st,1);
- } else {//Not mounted; Mount now.
- unsigned int option = OPTION_DRAGON1;
- if( color ) {
- option = ( color == 1 ? OPTION_DRAGON1 :
- color == 2 ? OPTION_DRAGON2 :
- color == 3 ? OPTION_DRAGON3 :
- color == 4 ? OPTION_DRAGON4 :
- color == 5 ? OPTION_DRAGON5 : 0);
- if( !option ) {
- ShowWarning("script_setdragon: Unknown Color %d used; changing to green (1)\n",color);
- option = OPTION_DRAGON1;
- }
- }
- pc->setoption(sd, sd->sc.option|option);
- script_pushint(st,1);
- }
- return true;
-}
/**
- * 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;
@@ -17283,20 +17600,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);
@@ -17304,6 +17623,7 @@ BUILDIN(setmounting) {
}
return true;
}
+
/**
* Retrieves quantity of arguments provided to callfunc/callsub.
* getargcount() -> amount of arguments received in a function
@@ -17786,6 +18106,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;
@@ -17805,12 +18126,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))
@@ -17846,8 +18172,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;
}
@@ -18311,6 +18640,55 @@ BUILDIN(countbound)
return 0;
}
+/*==========================================
+ * checkbound(<item_id>{,<bound_type>{,<refine>{,<attribute>{,<card_1>{,<card_2>{,<card_3>{,<card_4>}}}}}}});
+ * Checks to see if specified item is in inventory.
+ * Returns the bound type of item found.
+ * Type:
+ * 1 - Account Bound
+ * 2 - Guild Bound
+ * 3 - Party Bound
+ * 4 - Character Bound
+ *------------------------------------------*/
+BUILDIN(checkbound){
+ int i, nameid = script_getnum(st,2);
+ int bound_type = 0, ref, attr, c1, c2, c3, c4;
+ TBL_PC *sd;
+
+ sd = script->rid2sd(st);
+ if( sd == NULL )
+ return false;
+
+ if( !(itemdb->exists(nameid)) ){
+ ShowError("script_checkbound: Invalid item ID = %d\n", nameid);
+ return false;
+ }
+
+ if (script_hasdata(st,3))
+ bound_type = script_getnum(st,3);
+
+ if( bound_type <= -1 || bound_type > IBT_MAX ){
+ ShowError("script_checkbound: Not a valid bind type! Type=%d\n", bound_type);
+ }
+
+ ARR_FIND( 0, MAX_INVENTORY, i, (sd->status.inventory[i].nameid == nameid &&
+ ( sd->status.inventory[i].refine == (script_hasdata(st,4)? (ref = script_getnum(st,4)) : sd->status.inventory[i].refine) ) &&
+ ( sd->status.inventory[i].attribute == (script_hasdata(st,5)? (attr = script_getnum(st,5)) : sd->status.inventory[i].attribute) ) &&
+ ( sd->status.inventory[i].card[0] == (script_hasdata(st,6)? (c1 = script_getnum(st,6)) : sd->status.inventory[i].card[0]) ) &&
+ ( sd->status.inventory[i].card[1] == (script_hasdata(st,7)? (c2 = script_getnum(st,7)) : sd->status.inventory[i].card[1]) ) &&
+ ( sd->status.inventory[i].card[2] == (script_hasdata(st,8)? (c3 = script_getnum(st,8)) : sd->status.inventory[i].card[2]) ) &&
+ ( sd->status.inventory[i].card[3] == (script_hasdata(st,9)? (c4 = script_getnum(st,9)) : sd->status.inventory[i].card[3]) ) &&
+ ((sd->status.inventory[i].bound > 0 && !bound_type) || sd->status.inventory[i].bound == bound_type )) );
+
+ if( i < MAX_INVENTORY ){
+ script_pushint(st, sd->status.inventory[i].bound);
+ return true;
+ } else
+ script_pushint(st,0);
+
+ return true;
+}
+
/* bg_match_over( arena_name {, optional canceled } ) */
/* returns 0 when successful, 1 otherwise */
BUILDIN(bg_match_over) {
@@ -18737,7 +19115,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;
@@ -18753,6 +19131,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 ) {
@@ -18765,18 +19144,25 @@ bool script_add_builtin(const struct script_function *buildin, bool override) {
return true;
}
-bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st)) {
+bool script_hp_add(char *name, char *args, bool (*func)(struct script_state *st), bool isDeprecated) {
struct script_function buildin;
buildin.name = name;
buildin.arg = args;
buildin.func = func;
+ buildin.deprecated = isDeprecated;
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,""),
@@ -18801,8 +19187,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"),
@@ -18838,11 +19223,13 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getguildname,"i"),
BUILDIN_DEF(getguildmaster,"i"),
BUILDIN_DEF(getguildmasterid,"i"),
+ BUILDIN_DEF(getguildmember,"i?"),
BUILDIN_DEF(strcharinfo,"i"),
BUILDIN_DEF(strnpcinfo,"i"),
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"),
@@ -18879,12 +19266,10 @@ void script_parse_builtin(void) {
BUILDIN_DEF(checkcart,""),
BUILDIN_DEF(setfalcon,"?"),
BUILDIN_DEF(checkfalcon,""),
- BUILDIN_DEF(setriding,"?"),
- BUILDIN_DEF(checkriding,""),
+ BUILDIN_DEF(setmount,"?"),
+ BUILDIN_DEF(checkmount,""),
BUILDIN_DEF(checkwug,""),
- BUILDIN_DEF(checkmadogear,""),
- BUILDIN_DEF(setmadogear,"?"),
- BUILDIN_DEF2(savepoint,"save","sii"),
+ BUILDIN_DEF2_DEPRECATED(savepoint,"save","sii"), // Deprecated 2014-11-02 [Haru]
BUILDIN_DEF(savepoint,"sii"),
BUILDIN_DEF(gettimetick,"i"),
BUILDIN_DEF(gettime,"i"),
@@ -18902,7 +19287,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"),
@@ -18920,15 +19305,15 @@ void script_parse_builtin(void) {
BUILDIN_DEF(getusers,"i"),
BUILDIN_DEF(getmapguildusers,"si"),
BUILDIN_DEF(getmapusers,"s"),
- BUILDIN_DEF(getareausers,"siiii"),
+ BUILDIN_DEF(getareausers,"*"),
BUILDIN_DEF(getareadropitem,"siiiiv"),
BUILDIN_DEF(enablenpc,"s"),
BUILDIN_DEF(disablenpc,"s"),
BUILDIN_DEF(hideoffnpc,"s"),
BUILDIN_DEF(hideonnpc,"s"),
- BUILDIN_DEF(sc_start,"iii?"),
- BUILDIN_DEF(sc_start2,"iiii?"),
- BUILDIN_DEF(sc_start4,"iiiiii?"),
+ BUILDIN_DEF(sc_start,"iii???"),
+ BUILDIN_DEF2(sc_start,"sc_start2","iiii???"),
+ BUILDIN_DEF2(sc_start,"sc_start4","iiiiii???"),
BUILDIN_DEF(sc_end,"i?"),
BUILDIN_DEF(getstatus, "i?"),
BUILDIN_DEF(getscrate,"ii?"),
@@ -18941,13 +19326,14 @@ void script_parse_builtin(void) {
BUILDIN_DEF(skillpointcount,""),
BUILDIN_DEF(changebase,"i?"),
BUILDIN_DEF(changesex,""),
+ BUILDIN_DEF(changecharsex,""), // [4144]
BUILDIN_DEF(waitingroom,"si?????"),
BUILDIN_DEF(delwaitingroom,"?"),
BUILDIN_DEF2(waitingroomkickall,"kickwaitingroomall","?"),
BUILDIN_DEF(enablewaitingroomevent,"?"),
BUILDIN_DEF(disablewaitingroomevent,"?"),
- BUILDIN_DEF2(enablewaitingroomevent,"enablearena",""), // Added by RoVeRT
- BUILDIN_DEF2(disablewaitingroomevent,"disablearena",""), // Added by RoVeRT
+ BUILDIN_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"),
@@ -18988,6 +19374,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(makepet,"i"),
BUILDIN_DEF(getexp,"ii"),
BUILDIN_DEF(getinventorylist,""),
+ BUILDIN_DEF(getcartinventorylist,""),
BUILDIN_DEF(getskilllist,""),
BUILDIN_DEF(clearitem,""),
BUILDIN_DEF(classchange,"ii"),
@@ -19002,7 +19389,6 @@ 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(petskillattack,"viii"), // [Skotlex]
BUILDIN_DEF(petskillattack2,"viiii"), // [Valaris]
BUILDIN_DEF(petskillsupport,"viiii"), // [Skotlex]
@@ -19023,6 +19409,10 @@ void script_parse_builtin(void) {
BUILDIN_DEF(npcspeed,"i"), // [Valaris]
BUILDIN_DEF(npcwalkto,"ii"), // [Valaris]
BUILDIN_DEF(npcstop,""), // [Valaris]
+ BUILDIN_DEF(setnpcdistance,"i"), // [4144]
+ BUILDIN_DEF(getnpcdir,"?"), // [4144]
+ BUILDIN_DEF(setnpcdir,"*"), // [4144]
+ BUILDIN_DEF(getnpcclass,"?"), // [4144]
BUILDIN_DEF(getmapxy,"rrri?"), //by Lorky [Lupus]
BUILDIN_DEF(checkoption1,"i"),
BUILDIN_DEF(checkoption2,"i"),
@@ -19052,7 +19442,6 @@ 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_DEF(globalmes,"s?"), //end jA addition
BUILDIN_DEF(unequip,"i"), // unequip command [Spectre]
BUILDIN_DEF(getstrlen,"s"), //strlen [Valaris]
@@ -19083,6 +19472,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"),
@@ -19096,6 +19487,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(npcshopattach,"s?"),
BUILDIN_DEF(equip,"i"),
BUILDIN_DEF(autoequip,"ii"),
+ BUILDIN_DEF(equip2,"iiiiiii"),
BUILDIN_DEF(setbattleflag,"si"),
BUILDIN_DEF(getbattleflag,"s"),
BUILDIN_DEF(setitemscript,"is?"), //Set NEW item bonus script. Lupus
@@ -19196,6 +19588,7 @@ void script_parse_builtin(void) {
BUILDIN_DEF(has_instance,"s?"),
BUILDIN_DEF(instance_warpall,"sii?"),
BUILDIN_DEF(instance_check_party,"i???"),
+ BUILDIN_DEF(instance_check_guild,"i???"),
BUILDIN_DEF(instance_mapname,"s?"),
BUILDIN_DEF(instance_set_respawn,"sii?"),
BUILDIN_DEF2(has_instance,"has_instance2","s"),
@@ -19204,10 +19597,8 @@ 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(hascashmount,""),//[Ind]
+ BUILDIN_DEF(setcashmount,""),//[Ind]
BUILDIN_DEF(checkre,"i"),
/**
* rAthena and beyond!
@@ -19236,13 +19627,15 @@ void script_parse_builtin(void) {
BUILDIN_DEF2(getitem,"getitembound","vii?"),
BUILDIN_DEF2(getitem2,"getitembound2","viiiiiiiii?"),
BUILDIN_DEF(countbound, "?"),
+ BUILDIN_DEF(checkbound, "i???????"),
//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(questprogress, "i?"),
+ BUILDIN_DEF(questactive, "i"),
BUILDIN_DEF(changequest, "ii"),
BUILDIN_DEF(showevent, "i?"),
@@ -19266,7 +19659,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"),
@@ -19320,6 +19713,7 @@ void script_hardcoded_constants(void) {
script->set_constant("MAX_ZENY",MAX_ZENY,false);
script->set_constant("MAX_BG_MEMBERS",MAX_BG_MEMBERS,false);
script->set_constant("MAX_CHAT_USERS",MAX_CHAT_USERS,false);
+ script->set_constant("MAX_REFINE",MAX_REFINE,false);
/* status options */
script->set_constant("Option_Nothing",OPTION_NOTHING,false);
@@ -19609,8 +20003,9 @@ void script_defaults(void) {
script->config.loadmap_event_name = "OnPCLoadMapEvent";
script->config.baselvup_event_name = "OnPCBaseLvUpEvent";
script->config.joblvup_event_name = "OnPCJobLvUpEvent";
- script->config.ontouch_name = "OnTouch_";//ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves)
- script->config.ontouch2_name = "OnTouch";//ontouch2_name (run whenever a char walks into the OnTouch area)
+ script->config.ontouch_name = "OnTouch_"; //ontouch_name (runs on first visible char to enter area, picks another char if the first char leaves)
+ script->config.ontouch2_name = "OnTouch"; //ontouch2_name (run whenever a char walks into the OnTouch area)
+ script->config.onuntouch_name = "OnUnTouch"; //onuntouch_name (run whenever a char walks from the OnTouch area)
// for ENABLE_CASE_CHECK
script->calc_hash_ci = calc_hash_ci;
diff --git a/src/map/script.h b/src/map/script.h
index 48abf1487..548c0f261 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
@@ -187,7 +187,7 @@ typedef enum c_op {
C_USERFUNC, // internal script function
C_USERFUNC_POS, // internal script function label
C_REF, // the next call to c_op2 should push back a ref to the left operand
-
+
// operators
C_OP3, // a ? b : c
C_LOR, // a || b
@@ -265,7 +265,7 @@ enum e_arglist {
*------------------------------------------*/
enum {
- MF_NOMEMO, //0
+ MF_NOMEMO, //0
MF_NOTELEPORT,
MF_NOSAVE,
MF_NOBRANCH,
@@ -275,7 +275,7 @@ enum {
MF_PVP_NOPARTY,
MF_PVP_NOGUILD,
MF_GVG,
- MF_GVG_NOPARTY, //10
+ MF_GVG_NOPARTY, //10
MF_NOTRADE,
MF_NOSKILL,
MF_NOWARP,
@@ -293,7 +293,7 @@ enum {
MF_GVG_DUNGEON,
MF_NIGHTENABLED,
MF_NOBASEEXP,
- MF_NOJOBEXP, //30
+ MF_NOJOBEXP, //30
MF_NOMOBLOOT,
MF_NOMVPLOOT,
MF_NORETURN,
@@ -303,7 +303,7 @@ enum {
MF_NOCOMMAND,
MF_NODROP,
MF_JEXP,
- MF_BEXP, //40
+ MF_BEXP, //40
MF_NOVENDING,
MF_LOADEVENT,
MF_NOCHAT,
@@ -313,7 +313,7 @@ enum {
MF_AUTOTRADE,
MF_ALLOWKS,
MF_MONSTER_NOTELEPORT,
- MF_PVP_NOCALCRANK, //50
+ MF_PVP_NOCALCRANK, //50
MF_BATTLEGROUND,
MF_RESET,
MF_NOTOMB,
@@ -343,6 +343,7 @@ struct Script_Config {
const char* ontouch_name;
const char* ontouch2_name;
+ const char* onuntouch_name;
};
/**
@@ -433,6 +434,7 @@ struct script_function {
bool (*func)(struct script_state *st);
char *name;
char *arg;
+ bool deprecated;
};
// String buffer structures.
@@ -445,6 +447,7 @@ struct str_data_struct {
bool (*func)(struct script_state *st);
int val;
int next;
+ uint8 deprecated : 1;
};
struct script_label_entry {
@@ -458,9 +461,9 @@ struct script_syntax_data {
int count;
int flag;
struct linkdb_node *case_label;
- } curly[256]; // Information right parenthesis
- int curly_count; // The number of right brackets
- int index; // Number of the syntax used in the script
+ } curly[256]; // Information right parenthesis
+ int curly_count; // The number of right brackets
+ int index; // Number of the syntax used in the script
};
struct casecheck_data {
@@ -574,7 +577,7 @@ struct script_interface {
void (*error) (const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos);
void (*warning) (const char* src, const char* file, int start_line, const char* error_msg, const char* error_pos);
/* */
- bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st));
+ bool (*addScript) (char *name, char *args, bool (*func)(struct script_state *st), bool isDeprecated);
int (*conv_num) (struct script_state *st,struct script_data *data);
const char* (*conv_str) (struct script_state *st,struct script_data *data);
TBL_PC *(*rid2sd) (struct script_state *st);
diff --git a/src/map/searchstore.c b/src/map/searchstore.c
index 72b28aacd..782c14987 100644
--- a/src/map/searchstore.c
+++ b/src/map/searchstore.c
@@ -333,7 +333,7 @@ bool searchstore_result(struct map_session_data* sd, unsigned int store_id, int
void searchstore_defaults (void) {
searchstore = &searchstore_s;
-
+
searchstore->open = searchstore_open;
searchstore->query = searchstore_query;
searchstore->querynext = searchstore_querynext;
@@ -344,5 +344,5 @@ void searchstore_defaults (void) {
searchstore->queryremote = searchstore_queryremote;
searchstore->clearremote = searchstore_clearremote;
searchstore->result = searchstore_result;
-
+
}
diff --git a/src/map/skill.c b/src/map/skill.c
index b82c47a69..5eb319c02 100644
--- a/src/map/skill.c
+++ b/src/map/skill.c
@@ -45,7 +45,7 @@
#include "../common/timer.h"
#include "../common/utils.h"
-#define SKILLUNITTIMER_INTERVAL 100
+#define SKILLUNITTIMER_INTERVAL 100
// ranges reserved for mapping skill ids to skilldb offsets
#define HM_SKILLRANGEMIN 750
@@ -145,49 +145,49 @@ void skill_chk(uint16* skill_id) {
} while(0)
#define skill_glv(lv) min((lv),MAX_SKILL_LEVEL-1)
// Skill DB
-int skill_get_hit( uint16 skill_id ) { skill_get (skill->db[skill_id].hit, skill_id); }
-int skill_get_inf( uint16 skill_id ) { skill_get (skill->db[skill_id].inf, skill_id); }
-int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get (skill->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); }
-int skill_get_nk( uint16 skill_id ) { skill_get (skill->db[skill_id].nk, skill_id); }
-int skill_get_max( uint16 skill_id ) { skill_get (skill->db[skill_id].max, skill_id); }
-int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); }
-int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_state(uint16 skill_id) { skill_get (skill->db[skill_id].state, skill_id); }
-int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get2 (skill->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].itemid[idx], skill_id); }
-int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].amount[idx], skill_id); }
-int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_castdef( uint16 skill_id ) { skill_get (skill->db[skill_id].cast_def_rate, skill_id); }
-int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->db[skill_id].weapon, skill_id); }
-int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->db[skill_id].ammo, skill_id); }
-int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_inf2( uint16 skill_id ) { skill_get (skill->db[skill_id].inf2, skill_id); }
-int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->db[skill_id].castcancel, skill_id); }
-int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_type( uint16 skill_id ) { skill_get (skill->db[skill_id].skill_type, skill_id); }
-int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->db[skill_id].unit_id[flag], skill_id); }
-int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_interval, skill_id); }
-int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BCT_ALL, skill_id); }
-int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BL_ALL, skill_id); }
-int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_flag, skill_id); }
-int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); }
-int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) {
+int skill_get_hit( uint16 skill_id ) { skill_get (skill->db[skill_id].hit, skill_id); }
+int skill_get_inf( uint16 skill_id ) { skill_get (skill->db[skill_id].inf, skill_id); }
+int skill_get_ele( uint16 skill_id , uint16 skill_lv ) { skill_get (skill->db[skill_id].element[skill_glv(skill_lv-1)], skill_id); }
+int skill_get_nk( uint16 skill_id ) { skill_get (skill->db[skill_id].nk, skill_id); }
+int skill_get_max( uint16 skill_id ) { skill_get (skill->db[skill_id].max, skill_id); }
+int skill_get_range( uint16 skill_id , uint16 skill_lv ) { skill_get2 (skill->db[skill_id].range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_splash( uint16 skill_id , uint16 skill_lv ) { skill_get2 ( (skill->db[skill_id].splash[skill_glv(skill_lv-1)]>=0?skill->db[skill_id].splash[skill_glv(skill_lv-1)]:AREA_SIZE), skill_id, skill_lv); }
+int skill_get_hp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_sp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_hp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].hp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_sp_rate(uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].sp_rate[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_state(uint16 skill_id) { skill_get (skill->db[skill_id].state, skill_id); }
+int skill_get_spiritball(uint16 skill_id, uint16 skill_lv) { skill_get2 (skill->db[skill_id].spiritball[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_itemid(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].itemid[idx], skill_id); }
+int skill_get_itemqty(uint16 skill_id, int idx) { skill_get (skill->db[skill_id].amount[idx], skill_id); }
+int skill_get_zeny( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].zeny[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_num( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].num[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_cast( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cast[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_delay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].delay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_walkdelay( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].walkdelay[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_time( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_time2( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].upkeep_time2[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_castdef( uint16 skill_id ) { skill_get (skill->db[skill_id].cast_def_rate, skill_id); }
+int skill_get_weapontype( uint16 skill_id ) { skill_get (skill->db[skill_id].weapon, skill_id); }
+int skill_get_ammotype( uint16 skill_id ) { skill_get (skill->db[skill_id].ammo, skill_id); }
+int skill_get_ammo_qty( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].ammo_qty[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_inf2( uint16 skill_id ) { skill_get (skill->db[skill_id].inf2, skill_id); }
+int skill_get_castcancel( uint16 skill_id ) { skill_get (skill->db[skill_id].castcancel, skill_id); }
+int skill_get_maxcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].maxcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_blewcount( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].blewcount[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_mhp( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].mhp[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_castnodex( uint16 skill_id ,uint16 skill_lv ) { skill_get2 (skill->db[skill_id].castnodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_delaynodex( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].delaynodex[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_type( uint16 skill_id ) { skill_get (skill->db[skill_id].skill_type, skill_id); }
+int skill_get_unit_id ( uint16 skill_id, int flag ){ skill_get (skill->db[skill_id].unit_id[flag], skill_id); }
+int skill_get_unit_interval( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_interval, skill_id); }
+int skill_get_unit_range( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].unit_range[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_unit_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BCT_ALL, skill_id); }
+int skill_get_unit_bl_target( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_target&BL_ALL, skill_id); }
+int skill_get_unit_flag( uint16 skill_id ) { skill_get (skill->db[skill_id].unit_flag, skill_id); }
+int skill_get_unit_layout_type( uint16 skill_id ,uint16 skill_lv ){ skill_get2 (skill->db[skill_id].unit_layout_type[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_cooldown( uint16 skill_id, uint16 skill_lv ) { skill_get2 (skill->db[skill_id].cooldown[skill_glv(skill_lv-1)], skill_id, skill_lv); }
+int skill_get_fixed_cast( uint16 skill_id ,uint16 skill_lv ) {
#ifdef RENEWAL_CAST
skill_get2 (skill->db[skill_id].fixed_cast[skill_glv(skill_lv-1)], skill_id, skill_lv);
#else
@@ -254,8 +254,10 @@ int skill_get_range2 (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
//TODO: Find a way better than hardcoding the list of skills affected by AC_VULTURE
switch( skill_id ) {
- case AC_SHOWER: case MA_SHOWER:
- case AC_DOUBLE: case MA_DOUBLE:
+ case AC_SHOWER:
+ case MA_SHOWER:
+ case AC_DOUBLE:
+ case MA_DOUBLE:
case HT_BLITZBEAT:
case AC_CHARGEARROW:
case MA_CHARGEARROW:
@@ -433,16 +435,12 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b
return 0;
// Couldn't preserve 3rd Class skills except only when using Reproduce skill. [Jobbie]
- if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= SR_RIDEINLIGHTNING) || (skill_id >= KO_YAMIKUMO && skill_id <= OB_AKAITSUKI)))
+ if( !(sd->sc.data[SC__REPRODUCE]) && ((skill_id >= RK_ENCHANTBLADE && skill_id <= LG_OVERBRAND_PLUSATK) || (skill_id >= RL_GLITTERING_GREED && skill_id <= OB_AKAITSUKI) || (skill_id >= GC_DARKCROW && skill_id <= NC_MAGMA_ERUPTION_DOTDAMAGE)))
return 0;
// Reproduce will only copy skills according on the list. [Jobbie]
else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] )
return 0;
- //Never copy new 3rd class skills By OmegaRed
- if(skill_id >= GC_DARKCROW && skill_id <= ALL_FULL_THROTTLE)
- return 0;
-
return 1;
}
@@ -457,6 +455,9 @@ int skillnotok (uint16 skill_id, struct map_session_data *sd)
if (idx == 0)
return 1; // invalid skill id
+ if( pc_has_permission(sd, PC_PERM_DISABLE_SKILL_USAGE) )
+ return 1;
+
if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL))
return 0; // can do any damn thing they want
@@ -646,7 +647,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
nullpo_ret(src);
nullpo_ret(bl);
- if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! - celest
+ if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! - celest
if( dmg_lv < ATK_BLOCK ) // Don't apply effect if miss.
return 0;
@@ -695,10 +696,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
temp = skill->get_time2(status->sc2skill(type),7);
if (sd->addeff[i].flag&ATF_TARGET)
- status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0);
+ status->change_start(src,bl,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE);
if (sd->addeff[i].flag&ATF_SELF)
- status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,0);
+ status->change_start(src,src,type,rate,7,0,(type == SC_BURNING)?src->id:0,0,temp,SCFLAG_NONE);
}
}
@@ -713,9 +714,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
temp = skill->get_time2(status->sc2skill(type),7);
if( sd->addeff3[i].target&ATF_TARGET )
- status->change_start(src,bl,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
+ status->change_start(src,bl,type,sd->addeff3[i].rate,7,0,0,0,temp,SCFLAG_NONE);
if( sd->addeff3[i].target&ATF_SELF )
- status->change_start(src,src,type,sd->addeff3[i].rate,7,0,0,0,temp,0);
+ status->change_start(src,src,type,sd->addeff3[i].rate,7,0,0,0,temp,SCFLAG_NONE);
}
}
}
@@ -782,7 +783,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
// Enchant Poison gives a chance to poison attacked enemies
if((sce=sc->data[SC_ENCHANTPOISON])) //Don't use sc_start since chance comes in 1/10000 rate.
status->change_start(src,bl,SC_POISON,sce->val2, sce->val1,src->id,0,0,
- skill->get_time2(AS_ENCHANTPOISON,sce->val1),0);
+ skill->get_time2(AS_ENCHANTPOISON,sce->val1),SCFLAG_NONE);
// Enchant Deadly Poison gives a chance to deadly poison attacked enemies
if((sce=sc->data[SC_EDP]))
sc_start4(src,bl,SC_DPOISON,sce->val2, sce->val1,src->id,0,0,
@@ -794,7 +795,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case SM_BASH:
if( sd && skill_lv > 5 && pc->checkskill(sd,SM_FATALBLOW)>0 )
status->change_start(src,bl,SC_STUN,500*(skill_lv-5)*sd->status.base_level/50,
- skill_lv,0,0,0,skill->get_time2(SM_FATALBLOW,skill_lv),0);
+ skill_lv,0,0,0,skill->get_time2(SM_FATALBLOW,skill_lv),SCFLAG_NONE);
break;
case MER_CRASH:
@@ -806,8 +807,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
skill_lv = pc->checkskill(sd, TF_POISON);
case TF_POISON:
case AS_SPLASHER:
- if(!sc_start2(src,bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv))
- && sd && skill_id==TF_POISON
+ if (!sc_start2(src,bl,SC_POISON,(4*skill_lv+10),skill_lv,src->id,skill->get_time2(skill_id,skill_lv))
+ && sd && skill_id==TF_POISON
)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
@@ -824,8 +825,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
#ifndef RENEWAL
case WZ_FROSTNOVA:
#endif
- if( !sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv))
- && sd && skill_id == MG_FROSTDIVER )
+ if (!sc_start(src,bl,SC_FREEZE,skill_lv*3+35,skill_lv,skill->get_time2(skill_id,skill_lv))
+ && sd && skill_id == MG_FROSTDIVER
+ )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
@@ -842,9 +844,9 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
#ifdef RENEWAL
sc_start(src,bl,SC_FREEZE,65-(5*skill_lv),skill_lv,skill->get_time2(skill_id,skill_lv));
#else
- // [Tharis] pointed out that this is normal freeze chance with a base of 300%
+ //On third hit, there is a 150% to freeze the target
if(tsc->sg_counter >= 3 &&
- sc_start(src,bl,SC_FREEZE,300,skill_lv,skill->get_time2(skill_id,skill_lv)))
+ sc_start(src,bl,SC_FREEZE,150,skill_lv,skill->get_time2(skill_id,skill_lv)))
tsc->sg_counter = 0;
/**
* being it only resets on success it'd keep stacking and eventually overflowing on mvps, so we reset at a high value
@@ -984,7 +986,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case NPC_MENTALBREAKER:
{
//Based on observations by [Tharis], Mental Breaker should do SP damage
- //equal to Matk*skLevel.
+ //equal to Matk*skLevel.
rate = status->get_matk(src, 2);
rate*=skill_lv;
status_zap(bl, 0, rate);
@@ -1010,7 +1012,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
case LK_SPIRALPIERCE:
case ML_SPIRALPIERCE:
- sc_start(src,bl,SC_ANKLESNARE,100,0,skill->get_time2(skill_id,skill_lv));
+ if( dstsd || ( dstmd && !is_boss(bl) ) ) //Does not work on bosses
+ sc_start(src,bl,SC_STOP,100,0,skill->get_time2(skill_id,skill_lv));
break;
case ST_REJECTSWORD:
@@ -1045,14 +1048,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
default:
sc_start2(src,bl,SC_BLOODING,(5+skill_lv*5),skill_lv,src->id,skill->get_time2(skill_id,3));
- }
+ }
break;
case HW_NAPALMVULCAN:
sc_start(src,bl,SC_CURSE,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case WS_CARTTERMINATION: // Cart termination
+ case WS_CARTTERMINATION:
sc_start(src,bl,SC_STUN,5*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
@@ -1082,7 +1085,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
case GS_BULLSEYE: //0.1% coma rate.
if(tstatus->race == RC_BRUTE || tstatus->race == RC_DEMIHUMAN)
- status->change_start(src,bl,SC_COMA,10,skill_lv,0,src->id,0,0,0);
+ status->change_start(src,bl,SC_COMA,10,skill_lv,0,src->id,0,0,SCFLAG_NONE);
break;
case GS_PIERCINGSHOT:
sc_start2(src,bl,SC_BLOODING,(skill_lv*3),skill_lv,src->id,skill->get_time2(skill_id,skill_lv));
@@ -1192,7 +1195,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
case NC_POWERSWING:
// Use flag=2, the stun duration is not vit-reduced.
- status->change_start(src, bl, SC_STUN, 5*skill_lv*100, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 2);
+ status->change_start(src, bl, SC_STUN, 5*skill_lv*100, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), SCFLAG_FIXEDTICK);
if( rnd()%100 < 5*skill_lv )
skill->castend_damage_id(src, bl, NC_AXEBOOMERANG, pc->checkskill(sd, NC_AXEBOOMERANG), tick, 1);
break;
@@ -1210,6 +1213,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
rate = 30 + 8 * skill_lv + sstatus->dex / 10 + (sd? sd->status.job_level:0) / 4;
sc_start(src, bl, SC_STUN, rate, skill_lv, skill->get_time(skill_id,skill_lv));
break;
+ case LG_HESPERUSLIT:
+ if ( sc && sc->data[SC_BANDING] ) {
+ if ( sc->data[SC_BANDING]->val2 == 4 ) // 4 banding RGs: Targets will be stunned at 100% chance for 4 ~ 8 seconds, irreducible by STAT.
+ status->change_start(src, bl, SC_STUN, 10000, skill_lv, 0, 0, 0, 1000*(4+rand()%4), SCFLAG_FIXEDTICK);
+ else if ( sc->data[SC_BANDING]->val2 == 6 ) // 6 banding RGs: activate Pinpoint Attack Lv1-5
+ skill->castend_damage_id(src,bl,LG_PINPOINTATTACK,1+rand()%5,tick,0);
+ }
+ break;
case LG_PINPOINTATTACK:
rate = 30 + 5 * (sd ? pc->checkskill(sd,LG_PINPOINTATTACK) : 1) + (sstatus->agi + status->get_lv(src)) / 10;
switch( skill_lv ) {
@@ -1237,7 +1248,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
else if( dstmd && !is_boss(bl) )
sc_start(src, bl,SC_STOP,100,skill_lv,skill->get_time(skill_id,skill_lv));
break;
- case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters.
+ case LG_RAYOFGENESIS: // 50% chance to cause Blind on Undead and Demon monsters.
if ( battle->check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON )
sc_start(src, bl, SC_BLIND,50, skill_lv, skill->get_time(skill_id,skill_lv));
break;
@@ -1267,7 +1278,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
sc_start(src, bl, SC_FEAR, 5 + 5 * skill_lv, skill_lv, skill->get_time(skill_id, skill_lv));
break;
case SO_EARTHGRAVE:
- sc_start2(src, bl, SC_BLOODING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine]
+ sc_start2(src, bl, SC_BLOODING, 5 * skill_lv, skill_lv, src->id, skill->get_time2(skill_id, skill_lv)); // Need official rate. [LimitLine]
break;
case SO_DIAMONDDUST:
rate = 5 + 5 * skill_lv;
@@ -1280,7 +1291,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
break;
case GN_SLINGITEM_RANGEMELEEATK:
if( sd ) {
- switch( sd->itemid ) { // Starting SCs here instead of do it in skill->additional_effect to simplify the code.
+ switch( sd->itemid ) {
+ // Starting SCs here instead of do it in skill->additional_effect to simplify the code.
case ITEMID_COCONUT_BOMB:
sc_start(src, bl, SC_STUN, 100, skill_lv, 5000); // 5 seconds until I get official
sc_start(src, bl, SC_BLOODING, 100, skill_lv, 10000);
@@ -1300,7 +1312,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
sc_start(src, bl, SC_STUN, 20 + 10 * skill_lv, skill_lv, skill->get_time2(skill_id, skill_lv));
sc_start2(src, bl, SC_BLOODING, 5 + 5 * skill_lv, skill_lv, src->id,skill->get_time2(skill_id, skill_lv));
break;
- case EL_WIND_SLASH: // Non confirmed rate.
+ case EL_WIND_SLASH: // Non confirmed rate.
sc_start2(src, bl, SC_BLOODING, 25, skill_lv, src->id, skill->get_time(skill_id,skill_lv));
break;
case EL_STONE_HAMMER:
@@ -1351,10 +1363,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
rate += sd->weapon_coma_race[tstatus->race];
rate += sd->weapon_coma_race[tstatus->mode&MD_BOSS?RC_BOSS:RC_NONBOSS];
if (rate)
- status->change_start(src, bl, SC_COMA, rate, 0, 0, src->id, 0, 0, 0);
+ status->change_start(src, bl, SC_COMA, rate, 0, 0, src->id, 0, 0, SCFLAG_NONE);
}
- if( sd && battle_config.equip_self_break_rate )
- { // Self weapon breaking
+ if (sd && battle_config.equip_self_break_rate) {
+ // Self weapon breaking
rate = battle_config.equip_natural_break_rate;
if( sc )
{
@@ -1368,8 +1380,8 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if( rate )
skill->break_equip(src, EQP_WEAPON, rate, BCT_SELF);
}
- if( battle_config.equip_skill_break_rate && skill_id != WS_CARTTERMINATION && skill_id != ITM_TOMAHAWK )
- { // Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity.
+ if (battle_config.equip_skill_break_rate && skill_id != WS_CARTTERMINATION && skill_id != ITM_TOMAHAWK) {
+ // Cart Termination/Tomahawk won't trigger breaking data. Why? No idea, go ask Gravity.
// Target weapon breaking
rate = 0;
if( sd )
@@ -1391,10 +1403,10 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
if (sd && !skill_id && bl->type == BL_PC) { // This effect does not work with skills.
if (sd->def_set_race[tstatus->race].rate)
status->change_start(src,bl, SC_DEFSET, sd->def_set_race[tstatus->race].rate, sd->def_set_race[tstatus->race].value,
- 0, 0, 0, sd->def_set_race[tstatus->race].tick, 2);
+ 0, 0, 0, sd->def_set_race[tstatus->race].tick, SCFLAG_FIXEDTICK);
if (sd->def_set_race[tstatus->race].rate)
status->change_start(src,bl, SC_MDEFSET, sd->mdef_set_race[tstatus->race].rate, sd->mdef_set_race[tstatus->race].value,
- 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2);
+ 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, SCFLAG_FIXEDTICK);
}
}
@@ -1557,7 +1569,7 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1
monster = mob->db(class_);
} while (
(monster->status.mode&(MD_BOSS|MD_PLANT) || monster->summonper[0] <= rate) &&
- (temp++) < 2000);
+ (temp++) < 2000);
if (temp < 2000)
mob->class_change(dstmd,class_);
}
@@ -1667,14 +1679,16 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
int rate;
struct map_session_data *sd=NULL;
struct map_session_data *dstsd=NULL;
+ struct status_change *sc;
nullpo_ret(src);
nullpo_ret(bl);
- if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! [celest]
+ if(skill_id > 0 && !skill_lv) return 0; // don't forget auto attacks! [celest]
sd = BL_CAST(BL_PC, src);
dstsd = BL_CAST(BL_PC, bl);
+ sc = status->get_sc(src);
if(dstsd && attack_type&BF_WEAPON) {
//Counter effects.
@@ -1696,10 +1710,10 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
time = skill->get_time2(status->sc2skill(type),7);
if (dstsd->addeff2[i].flag&ATF_TARGET)
- status->change_start(bl,src,type,rate,7,0,0,0,time,0);
+ status->change_start(bl,src,type,rate,7,0,0,0,time,SCFLAG_NONE);
if (dstsd->addeff2[i].flag&ATF_SELF && !status->isdead(bl))
- status->change_start(bl,bl,type,rate,7,0,0,0,time,0);
+ status->change_start(bl,bl,type,rate,7,0,0,0,time,SCFLAG_NONE);
}
}
@@ -1710,7 +1724,7 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
case GS_FULLBUSTER:
sc_start(src,src,SC_BLIND,2*skill_lv,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case HFLI_SBR44: // [orn]
+ case HFLI_SBR44: // [orn]
case HVAN_EXPLOSION:
if(src->type == BL_HOM){
TBL_HOM *hd = (TBL_HOM*)src;
@@ -1723,6 +1737,13 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
case NPC_GRANDDARKNESS:
attack_type |= BF_WEAPON;
break;
+ case LG_HESPERUSLIT:
+ if ( sc && sc->data[SC_FORCEOFVANGUARD] && sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 6 ) {
+ char i;
+ for( i = 0; i < sc->data[SC_FORCEOFVANGUARD]->val3 && sc->fv_counter <= sc->data[SC_FORCEOFVANGUARD]->val3 ; i++)
+ clif->millenniumshield(bl, sc->fv_counter++);
+ }
+ break;
}
if( sd && (sd->class_&MAPID_UPPERMASK) == MAPID_STAR_GLADIATOR
@@ -1755,14 +1776,11 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
sp += sd->bonus.magic_sp_gain_value;
hp += sd->bonus.magic_hp_gain_value;
if( skill_id == WZ_WATERBALL ) {// (bugreport:5303)
- struct status_change *sc = NULL;
- if( ( sc = status->get_sc(src) ) ) {
- if( sc->data[SC_SOULLINK]
- && sc->data[SC_SOULLINK]->val2 == SL_WIZARD
- && sc->data[SC_SOULLINK]->val3 == WZ_WATERBALL
- )
- sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
- }
+ if( sc->data[SC_SOULLINK]
+ && sc->data[SC_SOULLINK]->val2 == SL_WIZARD
+ && sc->data[SC_SOULLINK]->val3 == WZ_WATERBALL
+ )
+ sc->data[SC_SOULLINK]->val3 = 0; //Clear bounced spell check.
}
}
if( hp || sp ) {
@@ -1881,11 +1899,11 @@ int skill_counter_additional_effect(struct block_list* src, struct block_list *b
return 0;
}
/*=========================================================================
- Breaks equipment. On-non players causes the corresponding strip effect.
- - rate goes from 0 to 10000 (100.00%)
- - flag is a BCT_ flag to indicate which type of adjustment should be used
- (BCT_ENEMY/BCT_PARTY/BCT_SELF) are the valid values.
---------------------------------------------------------------------------*/
+ * Breaks equipment. On-non players causes the corresponding strip effect.
+ * - rate goes from 0 to 10000 (100.00%)
+ * - flag is a BCT_ flag to indicate which type of adjustment should be used
+ * (BCT_ENEMY/BCT_PARTY/BCT_SELF) are the valid values.
+ *------------------------------------------------------------------------*/
int skill_break_equip (struct block_list *bl, unsigned short where, int rate, int flag) {
const int where_list[4] = {EQP_WEAPON, EQP_ARMOR, EQP_SHIELD, EQP_HELM};
const enum sc_type scatk[4] = {SC_NOEQUIPWEAPON, SC_NOEQUIPARMOR, SC_NOEQUIPSHIELD, SC_NOEQUIPHELM};
@@ -1904,7 +1922,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in
rate -= rate*sd->bonus.unbreakable/100;
if (where&EQP_WEAPON) {
switch (sd->status.weapon) {
- case W_FIST: //Bare fists should not break :P
+ case W_FIST: //Bare fists should not break :P
case W_1HAXE:
case W_2HAXE:
case W_MACE: // Axes and Maces can't be broken [DracoRPG]
@@ -2047,13 +2065,13 @@ int skill_blown(struct block_list* src, struct block_list* target, int count, in
if (dir == -1) // <optimized>: do the computation here instead of outside
dir = map->calc_dir(target, src->x, src->y); // direction from src to target, reversed
- if (dir >= 0 && dir < 8)
- { // take the reversed 'direction' and reverse it
+ if (dir >= 0 && dir < 8) {
+ // take the reversed 'direction' and reverse it
dx = -dirx[dir];
dy = -diry[dir];
}
- return unit->blown(target, dx, dy, count, flag); // send over the proper flag
+ return unit->blown(target, dx, dy, count, flag); // send over the proper flag
}
@@ -2109,6 +2127,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;
@@ -2122,7 +2141,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
if(skill_id > 0 && !skill_lv) return 0;
- nullpo_ret(src); // Source is the master behind the attack (player/mob/pet)
+ nullpo_ret(src); // Source is the master behind the attack (player/mob/pet)
nullpo_ret(dsrc); // dsrc is the actual originator of the damage, can be the same as src, or a skill casted by src.
nullpo_ret(bl); //Target to be attacked.
@@ -2339,14 +2358,14 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
case AC_DOUBLE:
// AC_DOUBLE can start the combo with other monster types, but the
// monster that's going to be hit by HT_POWER should be RC_BRUTE or RC_INSECT [Panikon]
- if( pc->checkskill(sd, HT_POWER) )
- {
+ if (pc->checkskill(sd, HT_POWER)) {
sc_start4(NULL,src,SC_COMBOATTACK,100,HT_POWER,0,1,0,2000);
clif->combo_delay(src,2000);
}
break;
case TK_COUNTER:
- { //bonus from SG_FRIEND [Komurka]
+ {
+ //bonus from SG_FRIEND [Komurka]
int level;
if(sd->status.party_id>0 && (level = pc->checkskill(sd,SG_FRIEND)))
party->skill_check(sd, sd->status.party_id, TK_COUNTER,level);
@@ -2373,7 +2392,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
if( pc->checkskill(sd, SR_TIGERCANNON) > 0 || pc->checkskill(sd, SR_GATEOFHELL) > 0 )
combo = 1;
break;
- } //Switch End
+ } //Switch End
if (combo) { //Possible to chain
if ( (combo = DIFF_TICK32(sd->ud.canact_tick, tick)) < 50 ) combo = 50;/* less is a waste. */
sc_start2(NULL,src,SC_COMBOATTACK,100,skill_id,bl->id,combo);
@@ -2445,6 +2464,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);
@@ -2455,9 +2475,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;
@@ -2507,11 +2524,12 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
map->freeblock_lock();
- if(damage > 0 && dmg.flag&BF_SKILL && tsd
- && pc->checkskill(tsd,RG_PLAGIARISM)
- && (!sc || !sc->data[SC_PRESERVE])
- && damage < tsd->battle_status.hp)
- { //Updated to not be able to copy skills if the blow will kill you. [Skotlex]
+ if (damage > 0 && dmg.flag&BF_SKILL && tsd
+ && pc->checkskill(tsd,RG_PLAGIARISM)
+ && (!sc || !sc->data[SC_PRESERVE])
+ && damage < tsd->battle_status.hp
+ ) {
+ //Updated to not be able to copy skills if the blow will kill you. [Skotlex]
int copy_skill = skill_id, cidx = 0;
/**
* Copy Referral: dummy skills should point to their source upon copying
@@ -2530,7 +2548,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;
@@ -2547,7 +2565,7 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
}
cidx = skill->get_index(copy_skill);
if ((tsd->status.skill[cidx].id == 0 || tsd->status.skill[cidx].flag == SKILL_FLAG_PLAGIARIZED) &&
- can_copy(tsd,copy_skill,bl)) // Split all the check into their own function [Aru]
+ can_copy(tsd,copy_skill,bl)) // Split all the check into their own function [Aru]
{
int lv, idx = 0;
if( sc && sc->data[SC__REPRODUCE] && (lv = sc->data[SC__REPRODUCE]->val1) ) {
@@ -2640,7 +2658,8 @@ int skill_attack(int attack_type, struct block_list* src, struct block_list *dsr
break;
// This ensures the storm randomly pushes instead of exactly a cell backwards per official mechanics.
case WZ_STORMGUST:
- dir = rnd()%8;
+ if(!battle_config.stormgust_knockback)
+ dir = rand()%8;
break;
case WL_CRIMSONROCK:
dir = map->calc_dir(bl,skill->area_temp[4],skill->area_temp[5]);
@@ -2782,6 +2801,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);
}
@@ -2835,9 +2857,11 @@ int skill_check_unit_range_sub (struct block_list *bl, va_list ap) {
g_skill_id = su->group->skill_id;
switch (skill_id) {
- case MH_STEINWAND:
- case MG_SAFETYWALL:
case AL_PNEUMA:
+ if(g_skill_id == SA_LANDPROTECTOR)
+ break;
+ case MG_SAFETYWALL:
+ case MH_STEINWAND:
case SC_MAELSTROM:
case SO_ELEMENTAL_SHIELD:
if(g_skill_id != MH_STEINWAND && g_skill_id != MG_SAFETYWALL && g_skill_id != AL_PNEUMA && g_skill_id != SC_MAELSTROM && g_skill_id != SO_ELEMENTAL_SHIELD)
@@ -2919,7 +2943,8 @@ int skill_check_unit_range2_sub (struct block_list *bl, va_list ap) {
int skill_check_unit_range2 (struct block_list *bl, int x, int y, uint16 skill_id, uint16 skill_lv) {
int range, type;
- switch (skill_id) { // to be expanded later
+ switch (skill_id) {
+ // to be expanded later
case WZ_ICEWALL:
range = 2;
break;
@@ -3281,12 +3306,18 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) {
int x = skl->type>>16, y = skl->type&0xFFFF;
if( path->search_long(NULL, src->m, src->x, src->y, x, y, CELL_CHKWALL) )
skill->unitsetting(src,skl->skill_id,skl->skill_lv,x,y,skl->flag);
- if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
+ if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL)
+ && !map->getcell(src->m, skl->x, skl->y, CELL_CHKLANDPROTECTOR) )
clif->skill_poseffect(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,tick);
}
else if( path->search_long(NULL, src->m, src->x, src->y, skl->x, skl->y, CELL_CHKWALL) )
skill->unitsetting(src,skl->skill_id,skl->skill_lv,skl->x,skl->y,skl->flag);
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);
@@ -3296,14 +3327,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);
@@ -3390,7 +3413,7 @@ int skill_activate_reverberation(struct block_list *bl, va_list ap) {
int skill_reveal_trap (struct block_list *bl, va_list ap) {
TBL_SKILL *su = (TBL_SKILL*)bl;
- if (su->alive && su->group && skill->get_inf2(su->group->skill_id)&INF2_TRAP) { //Reveal trap.
+ if (su->alive && su->group && skill->get_inf2(su->group->skill_id)&INF2_TRAP) { //Reveal trap.
//Change look is not good enough, the client ignores it as an actual trap still. [Skotlex]
//clif->changetraplook(bl, su->group->unit_id);
clif->getareachar_skillunit(&su->bl,su,AREA);
@@ -3503,9 +3526,9 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case MO_TRIPLEATTACK:
case CH_CHAINCRUSH:
case CH_TIGERFIST:
- case PA_SHIELDCHAIN: // Shield Chain
+ case PA_SHIELDCHAIN:
case PA_SACRIFICE:
- case WS_CARTTERMINATION: // Cart Termination
+ case WS_CARTTERMINATION:
case AS_VENOMKNIFE:
case HT_PHANTASMIC:
case TK_DOWNKICK:
@@ -3517,15 +3540,15 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case GS_PIERCINGSHOT:
case GS_RAPIDSHOWER:
case GS_DUST:
- case GS_DISARM: // Added disarm. [Reddozen]
+ case GS_DISARM:
case GS_FULLBUSTER:
case NJ_SYURIKEN:
case NJ_KUNAI:
#ifndef RENEWAL
case ASC_BREAKER:
#endif
- case HFLI_MOON: //[orn]
- case HFLI_SBR44: //[orn]
+ case HFLI_MOON: //[orn]
+ case HFLI_SBR44: //[orn]
case NPC_BLEEDING:
case NPC_CRITICALWOUND:
case NPC_HELLPOWER:
@@ -3550,9 +3573,7 @@ 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:
case GC_DARKCROW:
case LG_OVERBRAND_BRANDISH:
@@ -3740,8 +3761,6 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case NPC_SPLASHATTACK:
flag |= SD_PREAMBLE; // a fake packet will be sent for the first target to be hit
case AS_SPLASHER:
- case SM_MAGNUM:
- case MS_MAGNUM:
case HT_BLITZBEAT:
case AC_SHOWER:
case MA_SHOWER:
@@ -3794,11 +3813,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);
@@ -3847,6 +3870,14 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
}
break;
+ case SM_MAGNUM:
+ case MS_MAGNUM:
+ if( flag&1 ) {
+ //Damage depends on distance, so add it to flag if it is > 1
+ skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag|distance_bl(src, bl));
+ }
+ break;
+
case KN_BRANDISHSPEAR:
case ML_BRANDISH:
//Coded apart for it needs the flag passed to the damage calculation.
@@ -3912,7 +3943,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
// If target cell is a wall then break
if(map->getcell(bl->m,tx,ty,CELL_CHKWALL))
break;
- skill_blown(src,bl,1,dir,0);
+ skill->blown(src,bl,1,dir,0);
// Splash around target cell, but only cells inside area; we first have to check the area is not negative
if((max(min_x,tx-1) <= min(max_x,tx+1)) &&
(max(min_y,ty-1) <= min(max_y,ty+1)) &&
@@ -3964,8 +3995,8 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
skill->castend_nodamage_id);
}
break;
- case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex]
- // clif->skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/
+ case CH_PALMSTRIKE: // Palm Strike takes effect 1sec after casting. [Skotlex]
+ //clif->skill_nodamage(src,bl,skill_id,skill_lv,0); //Can't make this one display the correct attack animation delay :/
clif->damage(src,bl,status_get_amotion(src),0,-1,1,4,0); //Display an absorbed damage attack.
skill->addtimerskill(src, tick + (1000+status_get_amotion(src)), bl->id, 0, 0, skill_id, skill_lv, BF_WEAPON, flag);
break;
@@ -4068,7 +4099,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
case SL_STIN:
case SL_STUN:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,10);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -4184,27 +4215,27 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
}
break;
+ case KO_JYUMONJIKIRI:
case GC_DARKILLUSION:
{
short x, y;
- short dir = map->calc_dir(src,bl->x,bl->y);
+ short dir = map->calc_dir(bl, src->x, src->y);
- if( dir > 0 && dir < 4) x = 2;
- else if( dir > 4 ) x = -2;
- else x = 0;
- if( dir > 2 && dir < 6 ) y = 2;
- else if( dir == 7 || dir < 2 ) y = -2;
- else y = 0;
+ if ( dir < 4 ) {
+ x = bl->x + 2 * (dir > 0) - 3 * (dir > 0);
+ y = bl->y + 1 - (dir / 2) - (dir > 2);
+ } else {
+ x = bl->x + 2 * (dir > 4) - 1 * (dir > 4);
+ y = bl->y + (dir / 6) - 1 + (dir > 6);
+ }
- if( unit->movepos(src, bl->x+x, bl->y+y, 1, 1) )
- {
- clif->slide(src,bl->x+x,bl->y+y);
+ if ( unit->movepos(src, x, y, 1, 1) ) {
+ clif->slide(src, x, y);
clif->fixpos(src); // the official server send these two packets.
- skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,flag);
- if( rnd()%100 < 4 * skill_lv )
- skill->castend_damage_id(src,bl,GC_CROSSIMPACT,skill_lv,tick,flag);
+ skill->attack(BF_WEAPON, src, src, bl, skill_id, skill_lv, tick, flag);
+ if ( rnd() % 100 < 4 * skill_lv && skill_id == GC_DARKILLUSION )
+ skill->castend_damage_id(src, bl, GC_CROSSIMPACT, skill_lv, tick, flag);
}
-
}
break;
case GC_WEAPONCRUSH:
@@ -4507,7 +4538,7 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1
tsc->data[SC_MELODYOFSINK] || tsc->data[SC_BEYOND_OF_WARCRY] || tsc->data[SC_UNLIMITED_HUMMING_VOICE] ) &&
rnd()%100 < 4 * skill_lv + 2 * (sd ? pc->checkskill(sd,WM_LESSON) : 10) + 10 * battle->calc_chorusbonus(sd)) {
skill->attack(BF_MISC,src,src,bl,skill_id,skill_lv,tick,flag);
- status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),8);
+ status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDRATE);
status_change_end(bl, SC_SWING, INVALID_TIMER);
status_change_end(bl, SC_SYMPHONY_LOVE, INVALID_TIMER);
status_change_end(bl, SC_MOONLIT_SERENADE, INVALID_TIMER);
@@ -4844,7 +4875,7 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
break;
} else if( ud->skill_id == RK_PHANTOMTHRUST && target->type != BL_MOB ) {
if( !map_flag_vs(src->m) && battle->check_target(src,target,BCT_PARTY) <= 0 )
- break; // You can use Phantom Thurst on party members in normal maps too. [pakpil]
+ break; // You can use Phantom Thurst on party members in normal maps too. [pakpil]
}
if( inf&BCT_ENEMY
@@ -4893,8 +4924,8 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
break;
if (ud->state.running && ud->skill_id == TK_JUMPKICK) {
- ud->state.running = 0;
- status_change_end(src, SC_RUN, INVALID_TIMER);
+ ud->state.running = 0;
+ status_change_end(src, SC_RUN, INVALID_TIMER);
flag = 1;
}
@@ -4988,8 +5019,8 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
skill->consume_requirement(sd,ud->skill_id, ud->skill_lv,1);
status->set_sp(src, 0, 0);
sc = &sd->sc;
- if (sc->count)
- { //End states
+ if (sc->count) {
+ //End states
status_change_end(src, SC_EXPLOSIONSPIRITS, INVALID_TIMER);
status_change_end(src, SC_BLADESTOP, INVALID_TIMER);
#ifdef RENEWAL
@@ -5006,8 +5037,8 @@ int skill_castend_id(int tid, int64 tick, int id, intptr_t data) {
if( dir > 2 && dir < 6 ) y = -2;
else if( dir == 7 || dir < 2 ) y = 2;
else y = 0;
- if (unit->movepos(src, src->x+x, src->y+y, 1, 1))
- { //Display movement + animation.
+ if (unit->movepos(src, src->x+x, src->y+y, 1, 1)) {
+ //Display movement + animation.
clif->slide(src,src->x,src->y);
clif->spiritball(src);
}
@@ -5043,7 +5074,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int element = 0;
enum sc_type type;
- if(skill_id > 0 && !skill_lv) return 0; // [Celest]
+ if(skill_id > 0 && !skill_lv) return 0; // [Celest]
nullpo_retr(1, src);
nullpo_retr(1, bl);
@@ -5099,12 +5130,12 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
//Check for undead skills that convert a no-damage skill into a damage one. [Skotlex]
switch (skill_id) {
- case HLIF_HEAL: // [orn]
+ case HLIF_HEAL: // [orn]
if (bl->type != BL_HOM) {
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0) ;
break ;
}
- case AL_HEAL:
+ case AL_HEAL:
/**
* Arch Bishop
@@ -5117,7 +5148,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
//Apparently only player casted skills can be offensive like this.
if (sd && battle->check_undead(tstatus->race,tstatus->def_ele) && skill_id != AL_INCAGI) {
if (battle->check_target(src, bl, BCT_ENEMY) < 1) {
- //Offensive heal does not works on non-enemies. [Skotlex]
+ //Offensive heal does not works on non-enemies. [Skotlex]
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -5135,7 +5166,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if((p = party->search(sd->status.party_id)) == NULL)
break;
- range = skill_get_splash(skill_id,skill_lv);
+ range = skill->get_splash(skill_id,skill_lv);
x0 = sd->bl.x - range;
y0 = sd->bl.y - range;
x1 = sd->bl.x + range;
@@ -5184,7 +5215,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case RK_FIGHTINGSPIRIT:
case RK_ABUNDANCE:
if( sd && !pc->checkskill(sd, RK_RUNEMASTERY) ){
- if( status->change_start(src,&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),8) ){
+ if( status->change_start(src,&sd->bl, (sc_type)(rnd()%SC_CONFUSION), 1000, 1, 0, 0, 0, skill->get_time2(skill_id,skill_lv),SCFLAG_FIXEDRATE) ){
skill->consume_requirement(sd,skill_id,skill_lv,2);
map->freeblock_unlock();
return 0;
@@ -5209,7 +5240,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
map->freeblock_lock();
switch(skill_id) {
- case HLIF_HEAL: // [orn]
+ case HLIF_HEAL: // [orn]
case AL_HEAL:
/**
* Arch Bishop
@@ -5398,7 +5429,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
bl = (struct block_list*)((TBL_PET*)src)->msd;
if (!bl) bl = src;
unit->skilluse_id(src, bl->id, abra_skill_id, abra_skill_lv);
- } else { //Assume offensive skills
+ } else { //Assume offensive skills
int target_id = 0;
if (ud->target)
target_id = ud->target;
@@ -5445,7 +5476,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case SA_SUMMONMONSTER:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
- if (sd) mob->once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_MEDIUM, AI_NONE);
+ if (sd) mob->once_spawn(sd, src->m, src->x, src->y," --ja--", -1, 1, "", SZ_SMALL, AI_NONE);
break;
case SA_LEVELUP:
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
@@ -5558,14 +5589,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start4(src,bl,type,100,skill_lv,src->id,0,0,skill->get_time(skill_id,skill_lv)));
break;
- case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
+ case SA_FLAMELAUNCHER: // added failure chance and chance to break weapon if turned on [Valaris]
case SA_FROSTWEAPON:
case SA_LIGHTNINGLOADER:
case SA_SEISMICWEAPON:
if (dstsd) {
if(dstsd->status.weapon == W_FIST ||
(dstsd->sc.count && !dstsd->sc.data[type] &&
- ( //Allow re-enchanting to lengthen time. [Skotlex]
+ ( //Allow re-enchanting to lengthen time. [Skotlex]
dstsd->sc.data[SC_PROPERTYFIRE] ||
dstsd->sc.data[SC_PROPERTYWATER] ||
dstsd->sc.data[SC_PROPERTYWIND] ||
@@ -5623,8 +5654,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case PR_KYRIE:
case MER_KYRIE:
- clif->skill_nodamage(bl,bl,skill_id,skill_lv,
- sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
+ clif->skill_nodamage(bl, bl, skill_id, -1,
+ sc_start(src, bl, type, 100, skill_lv, skill->get_time(skill_id, skill_lv)));
break;
//Passive Magnum, should had been casted on yourself.
case SM_MAGNUM:
@@ -5830,7 +5861,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
dstsd->sc.data[SC_PROPERTYGROUND] ||
dstsd->sc.data[SC_PROPERTYDARK] ||
dstsd->sc.data[SC_PROPERTYTELEKINESIS]
- // dstsd->sc.data[SC_ENCHANTPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex]
+ //dstsd->sc.data[SC_ENCHANTPOISON] //People say you should be able to recast to lengthen the timer. [Skotlex]
) {
clif->skill_nodamage(src,bl,skill_id,skill_lv,0);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -6009,15 +6040,23 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case MO_ABSORBSPIRITS:
{
int sp = 0;
- if (dstsd && dstsd->spiritball && (sd == dstsd || map_flag_vs(src->m) || (sd->duel_group && sd->duel_group == dstsd->duel_group)) && ((dstsd->class_&MAPID_BASEMASK)!=MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK)!=MAPID_REBELLION))
- { // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen]
+ if ( dstsd && dstsd->spiritball
+ && (sd == dstsd || map_flag_vs(src->m) || (sd->duel_group && sd->duel_group == dstsd->duel_group))
+ && ((dstsd->class_&MAPID_BASEMASK) != MAPID_GUNSLINGER || (dstsd->class_&MAPID_UPPERMASK) != MAPID_REBELLION)
+ ) {
+ // split the if for readability, and included gunslingers in the check so that their coins cannot be removed [Reddozen]
sp = dstsd->spiritball * 7;
- pc->delspiritball(dstsd,dstsd->spiritball,0);
- } else if (dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20)
- { // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen]
+ pc->delspiritball(dstsd, dstsd->spiritball, 0);
+ } else if ( dstmd && !(tstatus->mode&MD_BOSS) && rnd() % 100 < 20 ) {
+ // check if target is a monster and not a Boss, for the 20% chance to absorb 2 SP per monster's level [Reddozen]
sp = 2 * dstmd->level;
mob->target(dstmd,src,0);
}
+ if ( dstsd ) {
+ int i;
+ for ( i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++ )
+ pc->del_charm(dstsd, dstsd->spiritcharm[i], i);
+ }
if (sp) status->heal(src, 0, sp, 3);
clif->skill_nodamage(src,bl,skill_id,skill_lv,sp?1:0);
}
@@ -6121,7 +6160,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
BF_MAGIC, src, src, skill_id, skill_lv, tick, flag, BCT_ENEMY);
break;
- case HVAN_EXPLOSION: // [orn]
+ case HVAN_EXPLOSION: // [orn]
case NPC_SELFDESTRUCTION:
{
//Self Destruction hits everyone in range (allies+enemies)
@@ -6213,7 +6252,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
|| dstsd->status.char_id == sd->status.child
)
) {
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,8);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDRATE);
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
@@ -6261,25 +6300,24 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case GC_CLOAKINGEXCEED:
case LG_FORCEOFVANGUARD:
case SC_REPRODUCE:
+ case RA_CAMOUFLAGE:
if (tsce) {
int failure = status_change_end(bl, type, INVALID_TIMER);
if( failure )
clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
else if( sd )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- if ( skill_id == LG_FORCEOFVANGUARD )
+ if ( skill_id == LG_FORCEOFVANGUARD || skill_id == RA_CAMOUFLAGE )
break;
map->freeblock_unlock();
return 0;
+ } else {
+ int failure = sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
+ if( failure )
+ clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
+ else if( sd )
+ clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
}
- case RA_CAMOUFLAGE:
- {
- int failure = sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
- if( failure )
- clif->skill_nodamage(src,bl,skill_id,( skill_id == LG_FORCEOFVANGUARD ) ? skill_lv : -1,failure);
- else if( sd )
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- }
break;
case BD_ADAPTATION:
@@ -6360,7 +6398,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (tsc->data[SC_STONE]) {
status_change_end(bl, SC_STONE, INVALID_TIMER);
- if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
}
if (sc_start4(src,bl,SC_STONE,(skill_lv*4+20)+brate,
@@ -6417,7 +6455,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( battle->check_undead(tstatus->race,tstatus->def_ele) ) {
status->change_start(src, bl, SC_BLIND,
100*(100-(tstatus->int_/2+tstatus->vit/3+tstatus->luk/10)), 1,0,0,0,
- skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,0);
+ skill->get_time2(skill_id, skill_lv) * (100-(tstatus->int_+tstatus->vit)/2)/100,SCFLAG_NONE);
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
if(dstmd)
@@ -6507,8 +6545,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case MC_VENDING:
- if(sd)
- { //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex]
+ if (sd) {
+ //Prevent vending of GMs with unnecessary Level to trade/drop. [Skotlex]
if ( !pc_can_give_items(sd) )
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
else {
@@ -6613,9 +6651,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;
@@ -6732,7 +6770,14 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sp += sp * i / 100;
}
} else {
- hp = (1 + rnd()%400) * (100 + skill_lv*10) / 100;
+ //Maybe replace with potion_hp, but I'm unsure how that works [Playtester]
+ switch (skill_lv) {
+ case 1: hp = 45; break;
+ case 2: hp = 105; break;
+ case 3: hp = 175; break;
+ default: hp = 325; break;
+ }
+ hp = (hp + rnd()%(skill_lv*20+1)) * (150 + skill_lv*10) / 100;
hp = hp * (100 + (tstatus->vit<<1)) / 100;
if( dstsd )
hp = hp * (100 + pc->checkskill(dstsd,SM_RECOVERY)*10) / 100;
@@ -6778,7 +6823,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
case AM_CP_SHIELD: {
int i;
- if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] &&
+ if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] &&
dstsd->inventory_data[i]->type==IT_ARMOR)
clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
@@ -6929,7 +6974,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);
}
@@ -6968,8 +7013,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break; //Nothing to cancel.
bl_skill_id = ud->skill_id;
bl_skill_lv = ud->skill_lv;
- if (tstatus->mode & MD_BOSS)
- { //Only 10% success chance against bosses. [Skotlex]
+ if (tstatus->mode & MD_BOSS) {
+ //Only 10% success chance against bosses. [Skotlex]
if (rnd()%100 < 90)
{
if (sd) clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -6984,7 +7029,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
status_zap(bl, hp, sp);
if (hp && skill_lv >= 5)
- hp>>=1; //Recover half damaged HP at level 5 [Skotlex]
+ hp>>=1; //Recover half damaged HP at level 5 [Skotlex]
else
hp = 0;
@@ -7010,9 +7055,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
static const int spellarray[3] = { MG_COLDBOLT,MG_FIREBOLT,MG_LIGHTNINGBOLT };
if(skill_lv >= 10) {
spellid = MG_FROSTDIVER;
- // if (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SA_SAGE)
- // maxlv = 10;
- // else
+#if 0
+ if (tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SA_SAGE)
+ maxlv = 10;
+ else
+#endif // 0
maxlv = skill_lv - 9;
}
else if(skill_lv >=8) {
@@ -7088,7 +7135,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
struct unit_data *ud = unit->bl2ud(bl);
if (clif->skill_nodamage(src,bl,skill_id,skill_lv,
sc_start(src,bl,type,100,skill_lv,skill_time))
- && ud) { //Disable attacking/acting/moving for skill's duration.
+ && ud) {
+ //Disable attacking/acting/moving for skill's duration.
ud->attackabletime =
ud->canact_tick =
ud->canmove_tick = tick + skill_time;
@@ -7265,7 +7313,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
return 0;
}
else
- status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),8);
+ status->change_start(src,bl,SC_STUN,10000,skill_lv,0,0,0,skill->get_time2(skill_id,skill_lv),SCFLAG_FIXEDRATE);
}
break;
@@ -7337,7 +7385,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
struct skill_unit *su=NULL;
if((bl->type==BL_SKILL) && (su=(struct skill_unit *)bl) && (su->group) ){
switch(su->group->unit_id){
- case UNT_ANKLESNARE: // ankle snare
+ case UNT_ANKLESNARE:
if (su->group->val2 != 0)
// if it is already trapping something don't spring it,
// remove trap should be used instead
@@ -7492,7 +7540,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if(dstsd && dstsd->inventory_data[dstsd->equip_index[EQI_HAND_R]]) {
iused=true;
clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTWEAPON,100,skill_lv,skill->get_time(skill_id,skill_lv)));
- } if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] &&
+ } if(dstsd && (i=dstsd->equip_index[EQI_HAND_L])>=0 && dstsd->inventory_data[i] &&
dstsd->inventory_data[i]->type==IT_ARMOR) {
iused=true;
clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,SC_PROTECTSHIELD,100,skill_lv,skill->get_time(skill_id,skill_lv)));
@@ -7511,7 +7559,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
break;
- case RG_CLEANER: //AppleGirl
+ case RG_CLEANER: //AppleGirl
clif->skill_nodamage(src,bl,skill_id,skill_lv,1);
break;
@@ -7549,16 +7597,16 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->specialeffect(bl, 523 + eff, AREA);
switch (eff)
{
- case 0: // heals SP to 0
+ case 0: // heals SP to 0
status_percent_damage(src, bl, 0, 100, false);
break;
- case 1: // matk halved
+ case 1: // matk halved
sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
break;
- case 2: // all buffs removed
+ case 2: // all buffs removed
status->change_clear_buffs(bl,1);
break;
- case 3: // 1000 damage, random armor destroyed
+ case 3: // 1000 damage, random armor destroyed
{
status_fix_damage(src, bl, 1000, 0);
clif->damage(src,bl,0,0,1000,0,0,0);
@@ -7568,49 +7616,49 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
}
break;
- case 4: // atk halved
+ case 4: // atk halved
sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
break;
- case 5: // 2000HP heal, random teleported
+ case 5: // 2000HP heal, random teleported
status->heal(src, 2000, 0, 0);
if( !map_flag_vs(bl->m) )
unit->warp(bl, -1,-1,-1, CLR_TELEPORT);
break;
- case 6: // random 2 other effects
+ case 6: // random 2 other effects
if (count == -1)
count = 3;
else
count++; //Should not re-trigger this one.
break;
- case 7: // stop freeze or stoned
+ case 7: // stop freeze or stoned
{
enum sc_type sc[] = { SC_STOP, SC_FREEZE, SC_STONE };
sc_start(src,bl,sc[rnd()%3],100,skill_lv,skill->get_time2(skill_id,skill_lv));
}
break;
- case 8: // curse coma and poison
+ case 8: // curse coma and poison
sc_start(src,bl,SC_COMA,100,skill_lv,skill->get_time2(skill_id,skill_lv));
sc_start(src,bl,SC_CURSE,100,skill_lv,skill->get_time2(skill_id,skill_lv));
sc_start(src,bl,SC_POISON,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case 9: // confusion
+ case 9: // confusion
sc_start(src,bl,SC_CONFUSION,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case 10: // 6666 damage, atk matk halved, cursed
+ case 10: // 6666 damage, atk matk halved, cursed
status_fix_damage(src, bl, 6666, 0);
clif->damage(src,bl,0,0,6666,0,0,0);
sc_start(src,bl,SC_INCATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
sc_start(src,bl,SC_INCMATKRATE,100,-50,skill->get_time2(skill_id,skill_lv));
sc_start(src,bl,SC_CURSE,skill_lv,100,skill->get_time2(skill_id,skill_lv));
break;
- case 11: // 4444 damage
+ case 11: // 4444 damage
status_fix_damage(src, bl, 4444, 0);
clif->damage(src,bl,0,0,4444,0,0,0);
break;
- case 12: // stun
+ case 12: // stun
sc_start(src,bl,SC_STUN,100,skill_lv,5000);
break;
- case 13: // atk,matk,hit,flee,def reduced
+ case 13: // atk,matk,hit,flee,def reduced
sc_start(src,bl,SC_INCATKRATE,100,-20,skill->get_time2(skill_id,skill_lv));
sc_start(src,bl,SC_INCMATKRATE,100,-20,skill->get_time2(skill_id,skill_lv));
sc_start(src,bl,SC_INCHITRATE,100,-20,skill->get_time2(skill_id,skill_lv));
@@ -7646,8 +7694,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
}
- if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100))
- { //Erase death count 1% of the casts
+ if (skill_id == SL_SUPERNOVICE && dstsd && dstsd->die_counter && !(rnd()%100)) {
+ //Erase death count 1% of the casts
dstsd->die_counter = 0;
pc_setglobalreg(dstsd,script->add_str("PC_DIE_COUNTER"), 0);
clif->specialeffect(bl, 0x152, AREA);
@@ -7671,7 +7719,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (tsce) {
if(sd)
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,8);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,10000,SCFLAG_FIXEDRATE);
status_change_end(bl, SC_SWOO, INVALID_TIMER);
break;
}
@@ -7679,7 +7727,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SL_SKE:
if (sd && !battle_config.allow_es_magic_pc && bl->type != BL_MOB) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
- status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,10);
+ status->change_start(src,src,SC_STUN,10000,skill_lv,0,0,0,500,SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
}
clif->skill_nodamage(src,bl,skill_id,skill_lv,sc_start(src,bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv)));
@@ -7795,7 +7843,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
break;
- case AM_CALLHOMUN: // [orn]
+ case AM_CALLHOMUN: // [orn]
if( sd ) {
if (homun->call(sd))
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
@@ -7813,7 +7861,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
}
break;
- case HAMI_CASTLE: // [orn]
+ case HAMI_CASTLE: // [orn]
if(rnd()%100 < 20*skill_lv && src != bl)
{
int x,y;
@@ -7842,7 +7890,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
else if (sd)
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
- case HVAN_CHAOTIC: // [orn]
+ case HVAN_CHAOTIC: // [orn]
{
static const int per[5][2]={{20,50},{50,60},{25,75},{60,64},{34,67}};
int r = rnd()%100;
@@ -8233,7 +8281,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( sd == NULL || sd->status.party_id == 0 || flag&1 ) {
if( sd && tstatus && !battle->check_undead(tstatus->race, tstatus->def_ele) && !tsc->data[SC_BERSERK] ) {
int lv = pc->checkskill(sd, AL_HEAL);
- int heal = skill_calc_heal(src, bl, AL_HEAL, lv, true);
+ int heal = skill->calc_heal(src, bl, AL_HEAL, lv, true);
if( sd->status.party_id ) {
int partycount = party->foreachsamemap(party->sub_count, sd, 0);
@@ -8306,7 +8354,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);
@@ -8410,7 +8458,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if( tsc && tsc->data[SC_STONE] )
status_change_end(bl,SC_STONE,INVALID_TIMER);
else
- status->change_start(src,bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),2);
+ status->change_start(src,bl,SC_STONE,10000,skill_lv,0,0,500,skill->get_time(skill_id, skill_lv),SCFLAG_FIXEDTICK);
} else {
int rate = 45 + 5 * skill_lv;
if( rnd()%100 < rate ){
@@ -8518,9 +8566,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);
@@ -8646,13 +8694,13 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
//If the target was successfully inflected with the Unlucky status, give 1 of 3 random status's.
switch(rnd()%3) {//Targets in the Unlucky status will be affected by one of the 3 random status's regardless of resistance.
case 0:
- status->change_start(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ status->change_start(src,bl,SC_POISON,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
case 1:
- status->change_start(src,bl,SC_SILENCE,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ status->change_start(src,bl,SC_SILENCE,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
case 2:
- status->change_start(src,bl,SC_BLIND,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),10);
+ status->change_start(src,bl,SC_BLIND,10000,skill_lv,0,0,0,skill->get_time(skill_id,skill_lv),SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
}
}
} else if( sd )
@@ -8679,8 +8727,8 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
sc_start(src,bl,SC_SILENCE,100,skill_lv,sd->bonus.shieldmdef * 30000);
} else {
int opt = 0, val = 0, splashrange = 0;
- struct item_data *shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]];
- if( !shield_data || shield_data->type != IT_ARMOR ) {
+ struct item_data *shield_data = NULL;
+ if( sd->equip_index[EQI_HAND_L] < 0 || !( shield_data = sd->inventory_data[sd->equip_index[EQI_HAND_L]] ) || shield_data->type != IT_ARMOR ) {
//Skill will first check if a shield is equipped. If none is found on the caster the skill will fail.
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
@@ -8792,15 +8840,24 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (!tsc->data[i])
continue;
switch(i){
- case SC_POISON: case SC_BLIND:
- case SC_FREEZE: case SC_STONE:
- case SC_STUN: case SC_SLEEP:
- case SC_BLOODING: case SC_CURSE:
- case SC_CONFUSION: case SC_ILLUSION:
- case SC_SILENCE: case SC_BURNING:
- case SC_COLD: case SC_FROSTMISTY:
- case SC_DEEP_SLEEP: case SC_FEAR:
- case SC_MANDRAGORA: case SC__CHAOS:
+ case SC_POISON:
+ case SC_BLIND:
+ case SC_FREEZE:
+ case SC_STONE:
+ case SC_STUN:
+ case SC_SLEEP:
+ case SC_BLOODING:
+ case SC_CURSE:
+ case SC_CONFUSION:
+ case SC_ILLUSION:
+ case SC_SILENCE:
+ case SC_BURNING:
+ case SC_COLD:
+ case SC_FROSTMISTY:
+ case SC_DEEP_SLEEP:
+ case SC_FEAR:
+ case SC_MANDRAGORA:
+ case SC__CHAOS:
status_change_end(bl, (sc_type)i, INVALID_TIMER);
}
}
@@ -8864,6 +8921,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
pc->delspiritball(dstsd, dstsd->spiritball, 0);
status_percent_heal(src, 0, sp);
}
+ if ( dstsd ) {
+ int i;
+ for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++)
+ pc->del_charm(dstsd, dstsd->spiritcharm[i], i);
+ }
clif->skill_nodamage(src, bl, skill_id, skill_lv, sp ? 1:0);
} else {
clif->skill_damage(src,bl,tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
@@ -8912,10 +8974,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[] = {
@@ -8929,7 +8994,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
for( i = 0; i < ARRAYLENGTH(combo); i++ )
skill->addtimerskill(src, tick + 400 * i, bl->id, 0, 0, combo[i], skill_lv, BF_WEAPON, flag|SD_LEVEL);
- break;
+ break;
}
case WA_SWING_DANCE:
case WA_SYMPHONY_OF_LOVER:
@@ -9173,9 +9238,9 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
case SO_EL_CONTROL:
if( sd ) {
- int mode = EL_MODE_PASSIVE; // Standard mode.
+ int mode = EL_MODE_PASSIVE; // Standard mode.
- if( !sd->ed ) break;
+ if( !sd->ed ) break;
if( skill_lv == 4 ) {// At level 4 delete elementals.
elemental->delete(sd->ed, 0);
@@ -9224,7 +9289,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int s_hp = sd->battle_status.hp * 10 / 100, s_sp = sd->battle_status.sp * 10 / 100;
int e_hp, e_sp;
- if( !ed ) break;
+ if( !ed ) break;
if( !status->charge(&sd->bl,s_hp,s_sp) ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
break;
@@ -9353,7 +9418,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
} else {
clif->skill_nodamage(src,src,skill_id,skill_lv,1);
clif->skill_damage(src, ( skill_id == EL_GUST || skill_id == EL_BLAST || skill_id == EL_WILD_STORM )?src:bl, tick, status_get_amotion(src), 0, -30000, 1, skill_id, skill_lv, 6);
- if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away.
+ if( skill_id == EL_WIND_STEP ) // There aren't teleport, just push the master away.
skill->blown(src,bl,(rnd()%skill->get_blewcount(skill_id,skill_lv))+1,rnd()%8,0);
sc_start(src, src,type2,100,skill_lv,skill->get_time(skill_id,skill_lv));
sc_start(src, bl,type,100,skill_lv,skill->get_time(skill_id,skill_lv));
@@ -9399,10 +9464,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
int i;
int ttype = skill->get_ele(skill_id, skill_lv);
clif->skill_nodamage(src, bl, skill_id, skill_lv, 1);
- ARR_FIND(1, 6, i, sd->charm[i] > 0 && ttype != i);
- if( i < 6 )
- pc->del_charm(sd, sd->charm[i], i); // replace with a new one.
- pc->add_charm(sd, skill->get_time(skill_id, skill_lv), 10, ttype);
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0 && ttype != i);
+ if( i < SPIRITS_TYPE_SPHERE )
+ pc->del_charm(sd, sd->spiritcharm[i], i); // replace with a new one.
+ pc->add_charm(sd, skill->get_time(skill_id, skill_lv), MAX_SPIRITCHARM, ttype);
}
break;
@@ -9410,7 +9475,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if(sd) {
struct mob_data *summon_md;
- summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), 2308, "", SZ_MEDIUM, AI_NONE);
+ summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), 2308, "", SZ_SMALL, AI_NONE);
if( summon_md ) {
summon_md->master_id = src->id;
summon_md->special_state.ai = AI_ZANZOU;
@@ -9426,17 +9491,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;
@@ -9445,10 +9509,10 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
&& rand()%100 < (10 * (5 * skill_lv - status_get_int(bl) / 2 + 45 + 5 * skill_lv))
) {
clif->skill_nodamage(src, bl, skill_id, skill_lv,
- status->change_start(src, bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), 1));
+ status->change_start(src, bl, type, 10000, skill_lv, 0, 0, 0, skill->get_time(skill_id, skill_lv), SCFLAG_NOAVOID));
status_zap(bl, tstatus->max_hp * skill_lv * 5 / 100 , 0);
if( status->get_lv(bl) <= status->get_lv(src) )
- status->change_start(src, bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, 0);
+ status->change_start(src, bl, SC_COMA, skill_lv, skill_lv, 0, src->id, 0, 0, SCFLAG_NONE);
} else if( sd )
clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
break;
@@ -9544,11 +9608,11 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER);
}
}
- heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->battle_status, status->get_lv(&hd->bl));
+ heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->bl, &hd->battle_status, status->get_lv(&hd->bl));
status->heal(bl, heal, 0, 0);
clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1));
- status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8);
- status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), 1|2|8);
+ status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
+ status->change_start(src, bl, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
}
break;
@@ -9584,7 +9648,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin
break;
for(i=0; i<qty[skill_lv - 1]; i++){ //easy way
- summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), summons[skill_lv - 1], "", SZ_MEDIUM, AI_ATTACK);
+ summon_md = mob->once_spawn_sub(src, src->m, src->x, src->y, status->get_name(src), summons[skill_lv - 1], "", SZ_SMALL, AI_ATTACK);
if (summon_md) {
summon_md->master_id = src->id;
if (summon_md->deletetimer != INVALID_TIMER)
@@ -9717,9 +9781,11 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) {
if( sd )
{
- if( ud->skill_id != AL_WARP && !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) )
+ if( ud->skill_id != AL_WARP && !skill->check_condition_castend(sd, ud->skill_id, ud->skill_lv) ) {
+ if( ud->skill_id == SA_LANDPROTECTOR )
+ clif->skill_poseffect(&sd->bl,ud->skill_id,ud->skill_lv,sd->bl.x,sd->bl.y,tick);
break;
- else
+ }else
skill->consume_requirement(sd,ud->skill_id,ud->skill_lv,1);
}
@@ -9741,7 +9807,7 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) {
if( !sd || sd->skillitem != ud->skill_id || skill->get_delay(ud->skill_id,ud->skill_lv) )
ud->canact_tick = tick + skill->delay_fix(src, ud->skill_id, ud->skill_lv);
- if (sd) { //Cooldown application
+ if (sd) { //Cooldown application
int i, cooldown = skill->get_cooldown(ud->skill_id, ud->skill_lv);
for (i = 0; i < ARRAYLENGTH(sd->skillcooldown) && sd->skillcooldown[i].id; i++) { // Increases/Decreases cooldown of a skill by item/card bonuses.
if (sd->skillcooldown[i].id == ud->skill_id){
@@ -9754,15 +9820,15 @@ int skill_castend_pos(int tid, int64 tick, int id, intptr_t data) {
}
if( battle_config.display_status_timers && sd )
clif->status_change(src, SI_POSTDELAY, 1, skill->delay_fix(src, ud->skill_id, ud->skill_lv), 0, 0, 0);
-// if( sd )
-// {
-// switch( ud->skill_id )
-// {
-// case ????:
-// sd->canequip_tick = tick + ????;
-// break;
-// }
-// }
+#if 0
+ if (sd) {
+ switch (ud->skill_id) {
+ case ????:
+ sd->canequip_tick = tick + ????;
+ break;
+ }
+ }
+#endif // 0
unit->set_walkdelay(src, tick, battle_config.default_walk_delay+skill->get_walkdelay(ud->skill_id, ud->skill_lv), 1);
status_change_end(src,SC_CAMOUFLAGE, INVALID_TIMER);// only normal attack and auto cast skills benefit from its bonuses
map->freeblock_lock();
@@ -9849,7 +9915,6 @@ int skill_castend_map (struct map_session_data *sd, uint16 skill_id, const char
}
pc_stop_attack(sd);
- pc_stop_walking(sd,0);
if(battle_config.skill_log && battle_config.skill_log&BL_PC)
ShowInfo("PC %d skill castend skill =%d map=%s\n",sd->bl.id,skill_id,mapname);
@@ -9959,7 +10024,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
int r;
//if(skill_lv <= 0) return 0;
- if(skill_id > 0 && !skill_lv) return 0; // [Celest]
+ if(skill_id > 0 && !skill_lv) return 0; // [Celest]
nullpo_ret(src);
@@ -10051,11 +10116,17 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
}
case MG_SAFETYWALL:
+ {
+ int alive = 1;
+ if ( map->foreachincell(skill->cell_overlap, src->m, x, y, BL_SKILL, skill_id, &alive, src) ) {
+ skill->unitsetting(src, skill_id, skill_lv, x, y, 0);
+ return 0; // Don't consume gems if cast on LP
+ }
+ }
case MG_FIREWALL:
case MG_THUNDERSTORM:
case AL_PNEUMA:
- case WZ_ICEWALL:
case WZ_FIREPILLAR:
case WZ_QUAGMIRE:
case WZ_VERMILION:
@@ -10086,7 +10157,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case WE_CALLPARTNER:
case WE_CALLPARENT:
case WE_CALLBABY:
- case AC_SHOWER: //Ground-placed skill implementation.
+ case AC_SHOWER: //Ground-placed skill implementation.
case MA_SHOWER:
case SA_LANDPROTECTOR:
case BD_LULLABY:
@@ -10140,6 +10211,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
case GN_THORNS_TRAP:
case GN_DEMONIC_FIRE:
case GN_HELLS_PLANT:
+ case GN_FIRE_EXPANSION_SMOKE_POWDER:
+ case GN_FIRE_EXPANSION_TEAR_GAS:
case SO_EARTHGRAVE:
case SO_DIAMONDDUST:
case SO_FIRE_INSIGNIA:
@@ -10164,7 +10237,12 @@ 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 RG_GRAFFITI: /* Graffiti [Valaris] */
+ 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:
skill->clear_unitgroup(src);
skill->unitsetting(src,skill_id,skill_lv,x,y,0);
flag|=1;
@@ -10214,7 +10292,8 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
tmpx = x - area + rnd()%(area * 2 + 1);
tmpy = y - area + rnd()%(area * 2 + 1);
- if( i == 0 && path->search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL) )
+ if( i == 0 && path->search_long(NULL, src->m, src->x, src->y, tmpx, tmpy, CELL_CHKWALL)
+ && !map->getcell(src->m, tmpx, tmpy, CELL_CHKLANDPROTECTOR))
clif->skill_poseffect(src,skill_id,skill_lv,tmpx,tmpy,tick);
if( i > 0 )
@@ -10268,7 +10347,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
struct mob_data *md;
// Correct info, don't change any of this! [Celest]
- md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_SMALL, AI_NONE);
if (md) {
md->master_id = src->id;
md->special_state.ai = (skill_id == AM_SPHEREMINE) ? AI_SPHERE : AI_FLORA;
@@ -10358,7 +10437,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;
}
@@ -10366,7 +10445,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
if (rnd()%100 < 50) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
} else {
- TBL_MOB* md = mob->once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_MEDIUM, AI_NONE);
+ TBL_MOB* md = mob->once_spawn_sub(src, src->m, x, y, "--ja--",(skill_lv < 2 ? 1084+rnd()%2 : 1078+rnd()%6),"", SZ_SMALL, AI_NONE);
int i;
if (!md) break;
if ((i = skill->get_time(skill_id, skill_lv)) > 0)
@@ -10408,7 +10487,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
sc_start(src,src,type,100,skill_lv,skill->get_time2(skill_id,skill_lv));
break;
- case AM_RESURRECTHOMUN: // [orn]
+ case AM_RESURRECTHOMUN: // [orn]
if (sd) {
if (!homun->ressurect(sd, 20*skill_lv, x, y)) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -10513,7 +10592,7 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
int class_ = 2042;
struct mob_data *md;
- md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(src, src->m, x, y, status->get_name(src), class_, "", SZ_SMALL, AI_NONE);
if( md ) {
md->master_id = src->id;
md->special_state.ai = AI_FLORA;
@@ -10577,42 +10656,27 @@ 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;
+ int aciddemocast = 5;//If player doesent know Acid Demonstration or knows level 5 or lower, effect 5 will cast level 5 Acid Demo.
struct unit_data *ud = unit->bl2ud(src);
if( !ud ) break;
for( i = 0; i < MAX_SKILLUNITGROUP && ud->skillunit[i]; i ++ ) {
if( ud->skillunit[i]->skill_id == GN_DEMONIC_FIRE &&
- distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 4 ) {
+ distance_xy(x, y, ud->skillunit[i]->unit->bl.x, ud->skillunit[i]->unit->bl.y) < 3 ) {
switch( skill_lv ) {
case 3:
ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_SMOKE_POWDER;
@@ -10622,11 +10686,13 @@ int skill_castend_pos2(struct block_list* src, int x, int y, uint16 skill_id, ui
ud->skillunit[i]->unit_id = UNT_FIRE_EXPANSION_TEAR_GAS;
clif->changetraplook(&ud->skillunit[i]->unit->bl, UNT_FIRE_EXPANSION_TEAR_GAS);
break;
- case 5:
+ case 5:// If player knows a level of Acid Demonstration greater then 5, that level will be casted.
+ if ( pc->checkskill(sd, CR_ACIDDEMONSTRATION) > 5 )
+ aciddemocast = pc->checkskill(sd, CR_ACIDDEMONSTRATION);
map->foreachinarea(skill->area_sub, src->m,
- ud->skillunit[i]->unit->bl.x - 3, ud->skillunit[i]->unit->bl.y - 3,
- ud->skillunit[i]->unit->bl.x + 3, ud->skillunit[i]->unit->bl.y + 3, BL_CHAR,
- src, CR_ACIDDEMONSTRATION, sd ? pc->checkskill(sd, CR_ACIDDEMONSTRATION) : skill_lv, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id);
+ ud->skillunit[i]->unit->bl.x - 2, ud->skillunit[i]->unit->bl.y - 2,
+ ud->skillunit[i]->unit->bl.x + 2, ud->skillunit[i]->unit->bl.y + 2, BL_CHAR,
+ src, CR_ACIDDEMONSTRATION, aciddemocast, tick, flag|BCT_ENEMY|1|SD_LEVEL, skill->castend_damage_id);
skill->delunit(ud->skillunit[i]->unit);
break;
default:
@@ -10750,7 +10816,8 @@ bool skill_dance_switch(struct skill_unit* su, int flag) {
}
prevflag = flag;
- if( !flag ) { //Transform
+ if( !flag ) {
+ //Transform
uint16 skill_id = su->val2&UF_SONG ? BA_DISSONANCE : DC_UGLYDANCE;
// backup
@@ -10768,7 +10835,8 @@ bool skill_dance_switch(struct skill_unit* su, int flag) {
group->target_flag = skill->get_unit_target(skill_id);
group->bl_flag = skill->get_unit_bl_target(skill_id);
group->interval = skill->get_unit_interval(skill_id);
- } else { //Restore
+ } else {
+ //Restore
group->skill_id = backup.skill_id;
group->skill_lv = backup.skill_lv;
group->unit_id = backup.unit_id;
@@ -10779,28 +10847,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)
@@ -10835,7 +10881,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
sd = BL_CAST(BL_PC, src);
st = status->get_status_data(src);
- sc = status->get_sc(src); // for traps, firewall and fogwall - celest
+ sc = status->get_sc(src); // for traps, firewall and fogwall - celest
switch( skill_id ) {
case SO_ELEMENTAL_SHIELD:
@@ -10862,10 +10908,10 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case AL_WARP:
val1=skill_lv+6;
- if(!(flag&1))
+ if(!(flag&1)) {
limit=2000;
- else // previous implementation (not used anymore)
- { //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex]
+ } else { // previous implementation (not used anymore)
+ //Warp Portal morphing to active mode, extract relevant data from src. [Skotlex]
if( src->type != BL_SKILL ) return NULL;
group = ((TBL_SKILL*)src)->group;
src = map->id2bl(group->src_id);
@@ -10890,7 +10936,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
limit=1000;
val1=skill_lv+2;
break;
- case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex]
+ case WZ_QUAGMIRE: //The target changes to "all" if used in a gvg map. [Skotlex]
case AM_DEMONSTRATION:
case GN_HELLS_PLANT:
if( skill_id == GN_HELLS_PLANT && map->getcell(src->m, x, y, CELL_CHKLANDPROTECTOR) )
@@ -10944,17 +10990,18 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case SA_VIOLENTGALE:
{
struct skill_unit_group *old_sg;
- if ((old_sg = skill->locate_element_field(src)) != NULL)
- { //HelloKitty confirmed that these are interchangeable,
+ if ((old_sg = skill->locate_element_field(src)) != NULL) {
+ //HelloKitty confirmed that these are interchangeable,
//so you can change element and not consume gemstones.
- if ((
- old_sg->skill_id == SA_VOLCANO ||
- old_sg->skill_id == SA_DELUGE ||
- old_sg->skill_id == SA_VIOLENTGALE
- ) && old_sg->limit > 0)
- { //Use the previous limit (minus the elapsed time) [Skotlex]
+ if (( old_sg->skill_id == SA_VOLCANO
+ || old_sg->skill_id == SA_DELUGE
+ || old_sg->skill_id == SA_VIOLENTGALE
+ )
+ && old_sg->limit > 0
+ ) {
+ //Use the previous limit (minus the elapsed time) [Skotlex]
limit = old_sg->limit - DIFF_TICK32(timer->gettick(), old_sg->tick);
- if (limit < 0) //This can happen...
+ if (limit < 0) //This can happen...
limit = skill->get_time(skill_id,skill_lv);
}
skill->clear_group(src,1);
@@ -11010,22 +11057,24 @@ 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); //TO-DO This bonus value is guessed
- val2 += pc->checkskill(sd,DC_DANCINGLESSON); //TO-DO Should be half this value
+ val1 += pc->checkskill(sd,DC_DANCINGLESSON) / 2;
+ val2 += pc->checkskill(sd,DC_DANCINGLESSON) / 2;
}
break;
case BA_ASSASSINCROSS:
-#ifdef RENEWAL
- val1 = 10 + skill_lv + (st->agi/10); // ASPD increase
if(sd)
- val1 += 4*pc->checkskill(sd,BA_MUSICALLESSON);
+ val1 = pc->checkskill(sd,BA_MUSICALLESSON) / 2;
+#ifdef RENEWAL
+ // This formula was taken from a RE calculator
+ // and the changes published on irowiki
+ // Luckily, official tests show it's the right one
+ val1 += skill_lv + (st->agi/20);
#else
- val1 = 100+(10*skill_lv)+(st->agi/10); // ASPD increase
- if(sd)
- val1 += 5*pc->checkskill(sd,BA_MUSICALLESSON);
+ val1 += 10 + skill_lv + (st->agi/10); // ASPD increase
+ val1 *= 10; // ASPD works with 1000 as 100%
#endif
break;
case DC_FORTUNEKISS:
@@ -11036,22 +11085,22 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
break;
case BD_DRUMBATTLEFIELD:
#ifdef RENEWAL
- val1 = (skill_lv+5)*25; //Watk increase
- val2 = skill_lv*10; //Def increase
+ val1 = (skill_lv+5)*25; //Watk increase
+ val2 = skill_lv*10; //Def increase
#else
- val1 = (skill_lv+1)*25; //Watk increase
- val2 = (skill_lv+1)*2; //Def increase
+ val1 = (skill_lv+1)*25; //Watk increase
+ val2 = (skill_lv+1)*2; //Def increase
#endif
break;
case BD_RINGNIBELUNGEN:
- val1 = (skill_lv+2)*25; //Watk increase
+ val1 = (skill_lv+2)*25; //Watk increase
break;
case BD_RICHMANKIM:
val1 = 25 + 11*skill_lv; //Exp increase bonus.
break;
case BD_SIEGFRIED:
- val1 = 55 + skill_lv*5; //Elemental Resistance
- val2 = skill_lv*10; //Status ailment resistance
+ val1 = 55 + skill_lv*5; //Elemental Resistance
+ val2 = skill_lv*10; //Status ailment resistance
break;
case WE_CALLPARTNER:
if (sd) val1 = sd->status.partner_id;
@@ -11141,6 +11190,10 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
case SO_WARMER:
skill->clear_group(src, 8);
break;
+ case SO_VACUUM_EXTREME:
+ val1 = x;
+ val2 = y;
+ break;
case GN_WALLOFTHORN:
if( flag&1 )
limit = 3000;
@@ -11148,13 +11201,13 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
break;
case KO_ZENKAI:
if( sd ){
- ARR_FIND(1, 6, i, sd->charm[i] > 0);
- if( i < 5 ){
- val1 = sd->charm[i]; // no. of aura
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
+ if( i < SPIRITS_TYPE_SPHERE ){
+ val1 = sd->spiritcharm[i]; // no. of aura
val2 = i; // aura type
limit += val1 * 1000;
subunt = i - 1;
- pc->del_charm(sd, sd->charm[i], i);
+ pc->del_charm(sd, sd->spiritcharm[i], i);
}
}
break;
@@ -11170,7 +11223,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
group->state.song_dance = (unit_flag&(UF_DANCE|UF_SONG)?1:0)|(unit_flag&UF_ENSEMBLE?2:0); //Signals if this is a song/dance/duet
group->state.guildaura = ( skill_id >= GD_LEADERSHIP && skill_id <= GD_HAWKEYES )?1:0;
group->item_id = req_item;
- //if tick is greater than current, do not invoke onplace function just yet. [Skotlex]
+ //if tick is greater than current, do not invoke onplace function just yet. [Skotlex]
if (DIFF_TICK(group->tick, timer->gettick()) > SKILLUNITTIMER_INTERVAL)
active_flag = 0;
@@ -11266,8 +11319,7 @@ struct skill_unit_group* skill_unitsetting(struct block_list *src, uint16 skill_
if (skill->get_unit_flag(skill_id) & UF_RANGEDSINGLEUNIT && i == (layout->count / 2))
val2 |= UF_RANGEDSINGLEUNIT; // center.
- if( range <= 0 )
- map->foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
+ map->foreachincell(skill->cell_overlap,src->m,ux,uy,BL_SKILL,skill_id, &alive, src);
if( !alive )
continue;
@@ -11294,9 +11346,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;
@@ -11325,7 +11374,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
nullpo_ret(sg=src->group);
nullpo_ret(ss=map->id2bl(sg->src_id));
- if( skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
+ if( skill->get_type(sg->skill_id) == BF_MAGIC && map->getcell(src->bl.m, src->bl.x, src->bl.y, CELL_CHKLANDPROTECTOR) && sg->skill_id != SA_LANDPROTECTOR )
return 0; //AoE skills are ineffective. [Skotlex]
sc = status->get_sc(bl);
@@ -11335,6 +11384,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.
@@ -11346,7 +11398,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
break;
} else if( sc && battle->check_target(&sg->unit->bl,bl,sg->target_flag) > 0 ) {
int sec = skill->get_time2(sg->skill_id,sg->skill_lv);
- if( status->change_start(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,8) ) {
+ if( status->change_start(ss, bl,type,10000,sg->skill_lv,1,sg->group_id,0,sec,SCFLAG_FIXEDRATE) ) {
const struct TimerData* td = sc->data[type]?timer->get(sc->data[type]->timer):NULL;
if( td )
sec = DIFF_TICK32(td->tick, tick);
@@ -11444,10 +11496,10 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (!sce)
sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
break;
+ case UNT_APPLEIDUN:
case UNT_WHISTLE:
case UNT_ASSASSINCROSS:
case UNT_POEMBRAGI:
- case UNT_APPLEIDUN:
case UNT_HUMMING:
case UNT_DONTFORGETME:
case UNT_FORTUNEKISS:
@@ -11458,12 +11510,13 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
if (!sc) return 0;
if (!sce)
sc_start4(ss,bl,type,100,sg->skill_lv,sg->val1,sg->val2,0,sg->limit);
- else if (sce->val4 == 1) {
+ else if (battle_config.song_timer_reset && sce->val4 == 1) {
//Readjust timers since the effect will not last long.
sce->val4 = 0;
timer->delete(sce->timer, status->change_timer);
sce->timer = timer->add(tick+sg->limit, status->change_timer, bl->id, type);
}
+
break;
case UNT_FOGWALL:
@@ -11480,12 +11533,13 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
sc_start4(ss,bl,type,100,sg->skill_lv,0,BCT_ENEMY,sg->group_id,sg->limit);
break;
- // officially, icewall has no problems existing on occupied cells [ultramage]
- // case UNT_ICEWALL: //Destroy the cell. [Skotlex]
- // src->val1 = 0;
- // if(src->limit + sg->tick > tick + 700)
- // src->limit = DIFF_TICK32(tick+700,sg->tick);
- // break;
+#if 0 // officially, icewall has no problems existing on occupied cells [ultramage]
+ case UNT_ICEWALL: //Destroy the cell. [Skotlex]
+ src->val1 = 0;
+ if(src->limit + sg->tick > tick + 700)
+ src->limit = DIFF_TICK32(tick+700,sg->tick);
+ break;
+#endif // 0
case UNT_MOONLIT:
//Knockback out of area if affected char isn't in Moonlit effect
@@ -11498,7 +11552,7 @@ int skill_unit_onplace(struct skill_unit *src, struct block_list *bl, int64 tick
case UNT_WALLOFTHORN:
if( status_get_mode(bl)&MD_BOSS )
- break; // iRO Wiki says that this skill don't affect to Boss monsters.
+ break; // iRO Wiki says that this skill don't affect to Boss monsters.
if( map_flag_vs(bl->m) || bl->id == src->bl.id || battle->check_target(&src->bl,bl, BCT_ENEMY) == 1 )
skill->attack(skill->get_type(sg->skill_id), ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
break;
@@ -11554,9 +11608,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;
@@ -11565,6 +11616,26 @@ 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.
@@ -11586,7 +11657,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) {
@@ -11727,7 +11798,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_MANHOLE:
if( sg->val2 == 0 && tsc && (sg->unit_id == UNT_ANKLESNARE || bl->id != sg->src_id) ) {
int sec = skill->get_time2(sg->skill_id,sg->skill_lv);
- if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, 8) ) {
+ if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,sec, SCFLAG_FIXEDRATE) ) {
const struct TimerData* td = tsc->data[type]?timer->get(tsc->data[type]->timer):NULL;
if( td )
sec = DIFF_TICK32(td->tick, tick);
@@ -11757,7 +11828,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if( bl->id != ss->id ) {
if( status_get_mode(bl)&MD_BOSS )
break;
- if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), 8) ) {
+ if( status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id, sg->skill_lv), SCFLAG_FIXEDRATE) ) {
map->moveblock(bl, src->bl.x, src->bl.y, tick);
clif->fixpos(bl);
@@ -11770,7 +11841,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_VENOMDUST:
if(tsc && !tsc->data[type])
- status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),0);
+ status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),SCFLAG_NONE);
break;
@@ -11822,7 +11893,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
skill->additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick);
break;
- case UNT_UGLYDANCE: //Ugly Dance [Skotlex]
+ case UNT_UGLYDANCE:
if (ss->id != bl->id)
skill->additional_effect(ss, bl, sg->skill_id, sg->skill_lv, BF_LONG|BF_SKILL|BF_MISC, ATK_DEF, tick);
break;
@@ -11836,20 +11907,39 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
int heal;
#ifdef RENEWAL
struct mob_data *md = BL_CAST(BL_MOB, bl);
- if( md && md->class_ == MOBID_EMPERIUM )
+ if (md && md->class_ == MOBID_EMPERIUM)
break;
#endif
- if( sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER) )
- break; // affects self only when soullinked
+ if ((sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
+ || (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1))
+ break;
+
heal = skill->calc_heal(ss,bl,sg->skill_id, sg->skill_lv, true);
if( tsc->data[SC_AKAITSUKI] && heal )
heal = ~heal + 1;
clif->skill_nodamage(&src->bl, bl, AL_HEAL, heal, 1);
status->heal(bl, heal, 0, 0);
- break;
- }
- case UNT_TATAMIGAESHI:
+ if (!battle_config.song_timer_reset)
+ sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, 0, sg->limit);
+ }
+ break;
+ case UNT_POEMBRAGI:
+ case UNT_WHISTLE:
+ case UNT_ASSASSINCROSS:
+ case UNT_HUMMING:
+ case UNT_DONTFORGETME:
+ case UNT_FORTUNEKISS:
+ case UNT_SERVICEFORYOU:
+ if (battle_config.song_timer_reset
+ || (!(battle_config.song_timer_reset) && tsc && tsc->data[type] && tsc->data[type]->val4 == 1)
+ || (sg->src_id == bl->id && !(tsc && tsc->data[SC_SOULLINK] && tsc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
+ )
+ break;
+
+ sc_start4(ss, bl, type, 100, sg->skill_lv, sg->val1, sg->val2, 0, sg->limit);
+ break;
+ case UNT_TATAMIGAESHI:
case UNT_DEMONSTRATION:
skill->attack(BF_WEAPON,ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
@@ -12073,7 +12163,7 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
clif->fixpos(bl);
sg->val2 = bl->id;
} else
- sec = 3000; // Couldn't trap it?
+ sec = 3000; // Couldn't trap it?
sg->limit = DIFF_TICK32(tick, sg->tick) + sec;
} else if( tsc->data[SC_THORNS_TRAP] && bl->id == sg->val2 )
skill->attack(skill->get_type(GN_THORNS_TRAP), ss, ss, bl, sg->skill_id, sg->skill_lv, tick, SD_LEVEL|SD_ANIMATION);
@@ -12101,11 +12191,11 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
break;
case UNT_FIRE_EXPANSION_SMOKE_POWDER:
- sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_SMOKE_POWDER), 100, sg->skill_lv, 1000);
+ sc_start(ss, bl, SC_FIRE_EXPANSION_SMOKE_POWDER, 100, sg->skill_lv, 1000);
break;
case UNT_FIRE_EXPANSION_TEAR_GAS:
- sc_start(ss, bl, status->skill2sc(GN_FIRE_EXPANSION_TEAR_GAS), 100, sg->skill_lv, 1000);
+ sc_start(ss, bl, SC_FIRE_EXPANSION_TEAR_GAS, 100, sg->skill_lv, 1000);
break;
case UNT_HELLS_PLANT:
@@ -12117,12 +12207,13 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_CLOUD_KILL:
if(tsc && !tsc->data[type])
- status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),8);
+ status->change_start(ss,bl,type,10000,sg->skill_lv,sg->group_id,0,0,skill->get_time2(sg->skill_id,sg->skill_lv),SCFLAG_FIXEDRATE);
skill->attack(skill->get_type(sg->skill_id),ss,&src->bl,bl,sg->skill_id,sg->skill_lv,tick,0);
break;
case UNT_WARMER:
- if( bl->type == BL_PC && !battle->check_undead(tstatus->race, tstatus->def_ele) && tstatus->race != RC_DEMON ) {
+ {
+ // It has effect on everything, including monsters, undead property and demon
int hp = 0;
if( ssc && ssc->data[SC_HEATER_OPTION] )
hp = tstatus->max_hp * 3 * sg->skill_lv / 100;
@@ -12134,10 +12225,9 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
if( tsc && tsc->data[SC_AKAITSUKI] && hp )
hp = ~hp + 1;
status->heal(bl, hp, 0, 0);
- sc_start(ss, bl, SC_WARMER, 100, sg->skill_lv, skill->get_time2(sg->skill_id,sg->skill_lv));
+ sc_start(ss, bl, type, 100, sg->skill_lv, sg->interval + 100);
}
break;
-
case UNT_FIRE_INSIGNIA:
case UNT_WATER_INSIGNIA:
case UNT_WIND_INSIGNIA:
@@ -12163,11 +12253,18 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
break;
case UNT_VACUUM_EXTREME:
- if ( tsc && tsc->data[SC_HALLUCINATIONWALK] ) {
+ if (tsc && (tsc->data[SC_HALLUCINATIONWALK] || tsc->data[SC_VACUUM_EXTREME])) {
return 0;
} else {
sg->limit -= 100 * tstatus->str/20;
sc_start(ss, bl, SC_VACUUM_EXTREME, 100, sg->skill_lv, sg->limit);
+
+ 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;
@@ -12212,7 +12309,8 @@ int skill_unit_onplace_timer(struct skill_unit *src, struct block_list *bl, int6
case UNT_POISON_MIST:
skill->attack(BF_MAGIC, ss, &src->bl, bl, sg->skill_id, sg->skill_lv, tick, 0);
- status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0, skill->get_time2(sg->skill_id, sg->skill_lv), 2|8);
+ status->change_start(ss, bl, SC_BLIND, rnd() % 100 > sg->skill_lv * 10, sg->skill_lv, sg->skill_id, 0, 0,
+ skill->get_time2(sg->skill_id, sg->skill_lv), SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
break;
}
@@ -12245,10 +12343,8 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
switch(sg->unit_id){
case UNT_SAFETYWALL:
case UNT_PNEUMA:
- case UNT_EPICLESIS://Arch Bishop
case UNT_NEUTRALBARRIER:
case UNT_STEALTHFIELD:
- case UNT_WARMER:
if (sce)
status_change_end(bl, type, INVALID_TIMER);
break;
@@ -12257,7 +12353,8 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
if( sce && sce->val4 == src->bl.id )
status_change_end(bl, type, INVALID_TIMER);
break;
- case UNT_HERMODE: //Clear Hermode if the owner moved.
+ case UNT_HERMODE:
+ //Clear Hermode if the owner moved.
if (sce && sce->val3 == BCT_SELF && sce->val4 == sg->group_id)
status_change_end(bl, type, INVALID_TIMER);
break;
@@ -12273,6 +12370,16 @@ int skill_unit_onout(struct skill_unit *src, struct block_list *bl, int64 tick)
}
}
break;
+ case UNT_WHISTLE:
+ case UNT_ASSASSINCROSS:
+ case UNT_POEMBRAGI:
+ case UNT_APPLEIDUN:
+ case UNT_HUMMING:
+ case UNT_DONTFORGETME:
+ case UNT_FORTUNEKISS:
+ case UNT_SERVICEFORYOU:
+ if (sg->src_id==bl->id && !(sc && sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_BARDDANCER))
+ return -1;
}
return sg->skill_id;
}
@@ -12308,8 +12415,8 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
case BD_ROKISWEIL:
case BD_INTOABYSS:
case BD_SIEGFRIED:
- if(sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == skill_id)
- { //Check if you just stepped out of your ensemble skill to cancel dancing. [Skotlex]
+ if(sc && sc->data[SC_DANCING] && (sc->data[SC_DANCING]->val1&0xFFFF) == skill_id) {
+ //Check if you just stepped out of your ensemble skill to cancel dancing. [Skotlex]
//We don't check for SC_LONGING because someone could always have knocked you back and out of the song/dance.
//FIXME: This code is not perfect, it doesn't checks for the real ensemble's owner,
//it only checks if you are doing the same ensemble. So if there's two chars doing an ensemble
@@ -12350,7 +12457,9 @@ int skill_unit_onleft(uint16 skill_id, struct block_list *bl, int64 tick) {
case DC_DONTFORGETME:
case DC_FORTUNEKISS:
case DC_SERVICEFORYOU:
- if (sce) {
+ if ((battle_config.song_timer_reset && sce) // athena style
+ || (!battle_config.song_timer_reset && sce && sce->val4 != 1)
+ ) {
timer->delete(sce->timer, status->change_timer);
//NOTE: It'd be nice if we could get the skill_lv for a more accurate extra time, but alas...
//not possible on our current implementation.
@@ -12413,11 +12522,11 @@ int skill_unit_effect(struct block_list* bl, va_list ap) {
} else {
if( flag&1 )
skill->unit_onplace(su,bl,tick);
- else
- skill->unit_onout(su,bl,tick);
+ else if (skill->unit_onout(su,bl,tick) == -1)
+ return 0; // Don't let a Bard/Dancer update their own song timer
if( flag&4 )
- skill->unit_onleft(skill_id, bl, tick);
+ skill->unit_onleft(skill_id, bl, tick);
}
if( dissonance ) skill->dance_switch(su, 1);
@@ -12467,7 +12576,7 @@ int skill_check_condition_char_sub (struct block_list *bl, va_list ap) {
struct block_list *src;
struct map_session_data *sd;
struct map_session_data *tsd;
- int *p_sd; //Contains the list of characters found.
+ int *p_sd; //Contains the list of characters found.
nullpo_ret(bl);
nullpo_ret(tsd=(struct map_session_data*)bl);
@@ -12558,7 +12667,8 @@ int skill_check_pc_partner (struct map_session_data *sd, uint16 skill_id, uint16
if (!battle_config.player_skill_partner_check || pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL))
return is_chorus ? MAX_PARTY : 99; //As if there were infinite partners.
- if (cast_flag) { //Execute the skill on the partners.
+ if (cast_flag) {
+ //Execute the skill on the partners.
struct map_session_data* tsd;
switch (skill_id) {
case PR_BENEDICTIO:
@@ -12631,7 +12741,7 @@ int skill_isammotype (struct map_session_data *sd, int skill_id)
(sd->status.weapon == W_BOW || (sd->status.weapon >= W_REVOLVER && sd->status.weapon <= W_GRENADE)) &&
skill_id != HT_PHANTASMIC &&
skill->get_type(skill_id) == BF_WEAPON &&
- !(skill->get_nk(skill_id)&NK_NO_DAMAGE) &&
+ !(skill->get_nk(skill_id)&NK_NO_DAMAGE) &&
!skill->get_spiritball(skill_id,1) //Assume spirit spheres are used as ammo instead.
);
}
@@ -12674,8 +12784,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if (sd->chatID) return 0;
- if( pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id )
- { //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex]
+ if (pc_has_permission(sd, PC_PERM_SKILL_UNCONDITIONAL) && sd->skillitem != skill_id) {
+ //GMs don't override the skillItem check, otherwise they can use items without them being consumed! [Skotlex]
sd->state.arrow_atk = skill->get_ammotype(skill_id)?1:0; //Need to do arrow state check.
sd->spiritball_old = sd->spiritball; //Need to do Spiritball check.
return 1;
@@ -12717,8 +12827,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
sd->inventory_data[i] == NULL ||
!sd->inventory_data[i]->flag.delay_consume ||
sd->status.inventory[i].amount < 1
- )
- { //Something went wrong, item exploit?
+ ) {
+ //Something went wrong, item exploit?
sd->itemid = sd->itemindex = -1;
return 0;
}
@@ -12794,6 +12904,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case RA_WUGSTRIKE:
// Other
case BS_GREED:
+ case ALL_FULL_THROTTLE:
break;
default: // in official there is no message.
return 0;
@@ -12803,12 +12914,40 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
// Check the skills that can be used whiled using mado
if( pc_ismadogear(sd) ) {
- if( !(skill_id > NC_MADOLICENCE && skill_id <= NC_DISJOINT)
- && skill_id != NC_MAGMA_ERUPTION
- && skill_id != BS_GREED ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_MADOGEAR,0);
- return 0;
- }
+ switch ( skill_id ) {
+ case BS_GREED:
+ case NC_BOOSTKNUCKLE:
+ case NC_PILEBUNKER:
+ case NC_VULCANARM:
+ case NC_FLAMELAUNCHER:
+ case NC_COLDSLOWER:
+ case NC_ARMSCANNON:
+ case NC_ACCELERATION:
+ case NC_HOVERING:
+ case NC_F_SIDESLIDE:
+ case NC_B_SIDESLIDE:
+ case NC_SELFDESTRUCTION:
+ case NC_SHAPESHIFT:
+ case NC_EMERGENCYCOOL:
+ case NC_INFRAREDSCAN:
+ case NC_ANALYZE:
+ case NC_MAGNETICFIELD:
+ case NC_NEUTRALBARRIER:
+ case NC_STEALTHFIELD:
+ case NC_REPAIR:
+ case NC_AXEBOOMERANG:
+ case NC_POWERSWING:
+ case NC_AXETORNADO:
+ case NC_SILVERSNIPER:
+ case NC_MAGICDECOY:
+ case NC_DISJOINT:
+ case NC_MAGMA_ERUPTION:
+ case ALL_FULL_THROTTLE:
+ case NC_MAGMA_ERUPTION_DOTDAMAGE:
+ break;
+ default:
+ return 0;
+ }
}
if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
@@ -12895,12 +13034,13 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
}
return 0;
case MO_EXTREMITYFIST:
- // if(sc && sc->data[SC_EXTREMITYFIST]) //To disable Asura during the 5 min skill block uncomment this...
- // return 0;
- if( sc && (sc->data[SC_BLADESTOP] || sc->data[SC_CURSEDCIRCLE_ATKER]) )
+#if 0 //To disable Asura during the 5 min skill block uncomment this block...
+ if(sc && sc->data[SC_EXTREMITYFIST])
+ return 0;
+#endif // 0
+ if (sc && (sc->data[SC_BLADESTOP] || sc->data[SC_CURSEDCIRCLE_ATKER]))
break;
- if( sc && sc->data[SC_COMBOATTACK] )
- {
+ if (sc && sc->data[SC_COMBOATTACK]) {
switch(sc->data[SC_COMBOATTACK]->val1) {
case MO_COMBOFINISH:
case CH_TIGERFIST:
@@ -12909,9 +13049,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
default:
return 0;
}
- }
- else if( !unit->can_move(&sd->bl) )
- { //Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex]
+ } else if (!unit->can_move(&sd->bl)) {
+ //Placed here as ST_MOVE_ENABLE should not apply if rooted or on a combo. [Skotlex]
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
return 0;
}
@@ -12946,14 +13085,15 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
if(!(sc && sc->data[SC_COMBOATTACK]) || sc->data[SC_COMBOATTACK]->val1 == TK_JUMPKICK)
return 0; //Combo needs to be ready
- if (sc->data[SC_COMBOATTACK]->val3) { //Kick chain
+ if (sc->data[SC_COMBOATTACK]->val3) { //Kick chain
//Do not repeat a kick.
if (sc->data[SC_COMBOATTACK]->val3 != skill_id)
break;
status_change_end(&sd->bl, SC_COMBOATTACK, INVALID_TIMER);
return 0;
}
- if(sc->data[SC_COMBOATTACK]->val1 != skill_id && !( sd && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )) { //Cancel combo wait.
+ if(sc->data[SC_COMBOATTACK]->val1 != skill_id && !( sd && sd->status.base_level >= 90 && pc->famerank(sd->status.char_id, MAPID_TAEKWON) )) {
+ //Cancel combo wait.
unit->cancel_combo(&sd->bl);
return 0;
}
@@ -13142,17 +13282,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:
/**
@@ -13269,19 +13398,16 @@ 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.
+ 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 )
- 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;
}
+ 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 SR_FALLENEMPIRE:
if( sc && sc->data[SC_COMBOATTACK] ) {
@@ -13340,8 +13466,16 @@ 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.
+ case SO_ELECTRICWALK: // Can't be casted until you've walked all cells.
if( sc && sc->data[SC_PROPERTYWALK] &&
sc->data[SC_PROPERTYWALK]->val3 < skill->get_maxcount(sc->data[SC_PROPERTYWALK]->val1,sc->data[SC_PROPERTYWALK]->val2) ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
@@ -13372,7 +13506,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case KO_DOHU_KOUKAI:
{
int ttype = skill->get_ele(skill_id, skill_lv);
- if( sd->charm[ttype] >= 10 ){
+ if( sd->spiritcharm[ttype] >= MAX_SPIRITCHARM ){
clif->skill_fail(sd, skill_id, USESKILL_FAIL_SUMMON, 0);
return 0;
}
@@ -13382,8 +13516,8 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
case KO_ZENKAI:
{
int i;
- ARR_FIND(1, 6, i, sd->charm[i] > 0); // FIXME: 4 or 6?
- if( i > 4 ) {
+ ARR_FIND(SPIRITS_TYPE_CHARM_WATER, SPIRITS_TYPE_SPHERE, i, sd->spiritcharm[i] > 0);
+ if( i >= SPIRITS_TYPE_SPHERE ) {
clif->skill_fail(sd,skill_id,USESKILL_FAIL_SUMMON,0);
return 0;
}
@@ -13411,7 +13545,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;
}
@@ -13526,7 +13660,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;
}
@@ -13560,12 +13694,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, uint16 skill_id
return 0;
}
+#if 0
// There's no need to check if the skill is part of a combo if it's
// already been checked before, see unit_skilluse_id2 [Panikon]
// Note that if this check is read part of issue:8047 will reappear!
- //if( sd->sc.data[SC_COMBOATTACK] && !skill->is_combo(skill_id ) )
- // return 0;
-
+ if( sd->sc.data[SC_COMBOATTACK] && !skill->is_combo(skill_id ) )
+ return 0;
+#endif // 0
+
return 1;
}
@@ -13890,7 +14026,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
idx = skill->get_index(skill_id);
if( idx == 0 ) // invalid skill id
- return req;
+ return req;
if( skill_lv < 1 || skill_lv > MAX_SKILL_LEVEL )
return req;
@@ -13971,7 +14107,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
continue;
break;
case WZ_FIREPILLAR: // celest
- if (skill_lv <= 5) // no gems required at level 1-5
+ if (skill_lv <= 5) // no gems required at level 1-5
continue;
break;
case AB_ADORAMUS:
@@ -14002,10 +14138,9 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
req.itemid[i] = skill->db[idx].itemid[i];
req.amount[i] = skill->db[idx].amount[i];
- if( itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN )
- {
- if( sd->special_state.no_gemstone )
- { // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card [helvetica]
+ if (itemid_isgemstone(req.itemid[i]) && skill_id != HW_GANBANTEIN) {
+ if (sd->special_state.no_gemstone) {
+ // All gem skills except Hocus Pocus and Ganbantein can cast for free with Mistress card [helvetica]
if( skill_id != SA_ABRACADABRA )
req.itemid[i] = req.amount[i] = 0;
else if( --req.amount[i] < 1 )
@@ -14117,7 +14252,7 @@ struct skill_condition skill_get_requirement(struct map_session_data* sd, uint16
case CH_TIGERFIST:
req.spiritball = 3;
break;
- case CH_CHAINCRUSH: //It should consume whatever is left as long as it's at least 1.
+ case CH_CHAINCRUSH: //It should consume whatever is left as long as it's at least 1.
req.spiritball = sd->spiritball?sd->spiritball:1;
break;
}
@@ -14167,10 +14302,10 @@ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
// calculate base cast time (reduced by dex)
if( !(skill->get_castnodex(skill_id, skill_lv)&1) ) {
int scale = battle_config.castrate_dex_scale - status_get_dex(bl);
- if( scale > 0 ) // not instant cast
+ if( scale > 0 ) // not instant cast
time = time * scale / battle_config.castrate_dex_scale;
else
- return 0; // instant cast
+ return 0; // instant cast
}
// calculate cast time reduced by item/card bonuses
@@ -14195,9 +14330,9 @@ int skill_castfix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
if (battle_config.cast_rate != 100)
time = time * battle_config.cast_rate / 100;
// return final cast time
- time = max(time, 0);
+ time = max(time, 0);
-// ShowInfo("Castime castfix = %d\n",time);
+ //ShowInfo("Castime castfix = %d\n",time);
return time;
}
@@ -14279,9 +14414,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;
}
}
@@ -14383,10 +14517,11 @@ int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
return battle_config.min_skill_delay_limit;
if (time < 0)
- time = -time + status_get_amotion(bl); // If set to <0, add to attack motion.
+ time = -time + status_get_amotion(bl); // If set to <0, add to attack motion.
// Delay reductions
- switch (skill_id) { //Monk combo skills have their delay reduced by agi/dex.
+ switch (skill_id) {
+ //Monk combo skills have their delay reduced by agi/dex.
case MO_TRIPLEATTACK:
case MO_CHAINCOMBO:
case MO_COMBOFINISH:
@@ -14401,16 +14536,16 @@ int skill_delay_fix (struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
time = 0; // There is no Delay on Basilica creation, only on cancel
break;
default:
- if (battle_config.delay_dependon_dex && !(delaynodex&1))
- { // if skill delay is allowed to be reduced by dex
+ if (battle_config.delay_dependon_dex && !(delaynodex&1)) {
+ // if skill delay is allowed to be reduced by dex
int scale = battle_config.castrate_dex_scale - status_get_dex(bl);
if (scale > 0)
time = time * scale / battle_config.castrate_dex_scale;
else //To be capped later to minimum.
time = 0;
}
- if (battle_config.delay_dependon_agi && !(delaynodex&1))
- { // if skill delay is allowed to be reduced by agi
+ if (battle_config.delay_dependon_agi && !(delaynodex&1)) {
+ // if skill delay is allowed to be reduced by agi
int scale = battle_config.castrate_dex_scale - status_get_agi(bl);
if (scale > 0)
time = time * scale / battle_config.castrate_dex_scale;
@@ -14721,7 +14856,8 @@ void skill_weaponrefine (struct map_session_data *sd, int idx)
if(item->nameid > 0 && ditem->type == IT_WEAPON)
{
- if( ditem->flag.no_refine ){ // if the item isn't refinable
+ if( ditem->flag.no_refine ) {
+ // if the item isn't refinable
clif->skill_fail(sd,sd->menuskill_id,USESKILL_FAIL_LEVEL,0);
return;
}
@@ -14802,7 +14938,7 @@ int skill_autospell (struct map_session_data *sd, uint16 skill_id)
if(!skill_lv || !lv) return 0; // Player must learn the skill before doing auto-spell [Lance]
- if(skill_id==MG_NAPALMBEAT) maxlv=3;
+ if(skill_id==MG_NAPALMBEAT) maxlv=3;
else if(skill_id==MG_COLDBOLT || skill_id==MG_FIREBOLT || skill_id==MG_LIGHTNINGBOLT){
if (sd->sc.data[SC_SOULLINK] && sd->sc.data[SC_SOULLINK]->val2 == SL_SAGE)
maxlv =10; //Soul Linker bonus. [Skotlex]
@@ -14943,7 +15079,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]
@@ -15225,9 +15361,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;
}
@@ -15430,7 +15567,7 @@ bool skill_can_cloak(struct map_session_data *sd) {
//Avoid cloaking with no wall and low skill level. [Skotlex]
//Due to the cloaking card, we have to check the wall versus to known
//skill level rather than the used one. [Skotlex]
- //if (sd && val1 < 3 && skill_check_cloaking(bl,NULL))
+ //if (sd && val1 < 3 && skill->check_cloaking(bl,NULL))
if (pc->checkskill(sd, AS_CLOAKING) < 3 && !skill->check_cloaking(&sd->bl,NULL))
return false;
@@ -15545,7 +15682,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);
@@ -15594,10 +15730,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,
@@ -15745,7 +15881,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:
@@ -15925,7 +16061,7 @@ int skill_unit_timer_sub_onplace(struct block_list* bl, va_list ap) {
nullpo_ret(group);
- if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map->getcell(bl->m, bl->x, bl->y, CELL_CHKLANDPROTECTOR) )
+ if( !(skill->get_inf2(group->skill_id)&(INF2_SONG_DANCE|INF2_TRAP|INF2_NOLP)) && map->getcell(su->bl.m, su->bl.x, su->bl.y, CELL_CHKLANDPROTECTOR) )
return 0; //AoE skills are ineffective. [Skotlex]
if( battle->check_target(&su->bl,bl,group->target_flag) <= 0 )
@@ -15943,7 +16079,7 @@ int skill_unit_timer_sub(DBKey key, DBData *data, va_list ap) {
struct skill_unit* su = DB->data2ptr(data);
struct skill_unit_group* group = su->group;
int64 tick = va_arg(ap,int64);
- bool dissonance;
+ bool dissonance;
struct block_list* bl = &su->bl;
if( !su->alive )
@@ -16188,8 +16324,8 @@ int skill_unit_move_sub(struct block_list* bl, va_list ap) {
//Necessary in case the group is deleted after calling on_place/on_out [Skotlex]
skill_id = su->group->skill_id;
- if( su->group->interval != -1 && !(skill->get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY ) //Lullaby is the exception, bugreport:411
- { //Non-dualmode unit skills with a timer don't trigger when walking, so just return
+ if( su->group->interval != -1 && !(skill->get_unit_flag(skill_id)&UF_DUALMODE) && skill_id != BD_LULLABY ) { //Lullaby is the exception, bugreport:411
+ //Non-dualmode unit skills with a timer don't trigger when walking, so just return
if( dissonance ) skill->dance_switch(su, 1);
return 0;
}
@@ -16303,11 +16439,11 @@ int skill_unit_move_unit_group(struct skill_unit_group *group, int16 m, int16 dx
return 0; //Icewalls and Wall of Thorns don't get knocked back
m_flag = (int *) aCalloc(group->unit_count, sizeof(int));
- // m_flag
- // 0: Neither of the following (skill_unit_onplace & skill_unit_onout are needed)
- // 1: Unit will move to a slot that had another unit of the same group (skill_unit_onplace not needed)
- // 2: Another unit from same group will end up positioned on this unit (skill_unit_onout not needed)
- // 3: Both 1+2.
+ // m_flag:
+ // 0: Neither of the following (skill_unit_onplace & skill_unit_onout are needed)
+ // 1: Unit will move to a slot that had another unit of the same group (skill_unit_onplace not needed)
+ // 2: Another unit from same group will end up positioned on this unit (skill_unit_onout not needed)
+ // 3: Both 1+2.
for(i=0;i<group->unit_count;i++) {
su1=&group->unit[i];
if (!su1->alive || su1->bl.m!=m)
@@ -16759,9 +16895,8 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
}
break;
default:
- if (sd->menuskill_id == AM_PHARMACY &&
- sd->menuskill_val > 10 && sd->menuskill_val <= 20)
- { //Assume Cooking Dish
+ if (sd->menuskill_id == AM_PHARMACY && sd->menuskill_val > 10 && sd->menuskill_val <= 20) {
+ //Assume Cooking Dish
if (sd->menuskill_val >= 15) //Legendary Cooking Set.
make_per = 10000; //100% Success
else
@@ -16852,9 +16987,10 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
}
}
-// if(log_config.produce > 0)
-// log_produce(sd,nameid,slot1,slot2,slot3,1);
-//TODO update PICKLOG
+#if 0 // TODO: update PICKLOG
+ if(log_config.produce > 0)
+ log_produce(sd,nameid,slot1,slot2,slot3,1);
+#endif // 0
if(equip){
clif->produce_effect(sd,0,nameid);
@@ -16865,7 +17001,8 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
int fame = 0;
tmp_item.amount = 0;
- for (i=0; i< qty; i++) { //Apply quantity modifiers.
+ for (i=0; i< qty; i++) {
+ //Apply quantity modifiers.
if( (skill_id == GN_MIX_COOKING || skill_id == GN_MAKEBOMB || skill_id == GN_S_PHARMACY) && make_per > 1){
tmp_item.amount = qty;
break;
@@ -16963,9 +17100,10 @@ int skill_produce_mix(struct map_session_data *sd, uint16 skill_id, int nameid,
}
}
//Failure
-// if(log_config.produce)
-// log_produce(sd,nameid,slot1,slot2,slot3,0);
-//TODO update PICKLOG
+#if 0 // TODO: update PICKLOG
+ if(log_config.produce)
+ log_produce(sd,nameid,slot1,slot2,slot3,0);
+#endif // 0
if(equip){
clif->produce_effect(sd,1,nameid);
@@ -17154,7 +17292,7 @@ int skill_magicdecoy(struct map_session_data *sd, int nameid) {
class_ = (nameid == ITEMID_BOODY_RED || nameid == ITEMID_CRYSTAL_BLUE) ? 2043 + nameid - ITEMID_BOODY_RED : (nameid == ITEMID_WIND_OF_VERDURE) ? 2046 : 2045;
- md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_MEDIUM, AI_NONE);
+ md = mob->once_spawn_sub(&sd->bl, sd->bl.m, x, y, sd->status.name, class_, "", SZ_SMALL, AI_NONE);
if( md ) {
md->master_id = sd->bl.id;
md->special_state.ai = AI_FLORA;
@@ -17286,7 +17424,8 @@ int skill_elementalanalysis(struct map_session_data* sd, int n, uint16 skill_lv,
return 1;
}
- if( skill_lv == 2 && rnd()%100 < 25 ) { // At level 2 have a fail chance. You loose your items if it fails.
+ if( skill_lv == 2 && rnd()%100 < 25 ) {
+ // At level 2 have a fail chance. You loose your items if it fails.
clif->skill_fail(sd,SO_EL_ANALYSIS,USESKILL_FAIL_LEVEL,0);
return 1;
}
@@ -17338,7 +17477,7 @@ int skill_changematerial(struct map_session_data *sd, int n, unsigned short *ite
}
}
else
- break; // No more items required
+ break; // No more items required
}
p++;
} while(n == j && c == n);
@@ -17468,12 +17607,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;
@@ -17617,7 +17756,8 @@ int skill_split_atoi (char *str, int *val) {
}
if(i==0) //No data found.
return 0;
- if(i==1) { //Single value, have the whole range have the same value.
+ if(i==1) {
+ //Single value, have the whole range have the same value.
for (; i < MAX_SKILL_LEVEL; i++)
val[i] = val[i-1];
return i;
@@ -17932,44 +18072,132 @@ int skill_block_check(struct block_list *bl, sc_type type , uint16 skill_id) {
if( inf == INF2_SONG_DANCE || skill->get_inf2(skill_id) == INF2_CHORUS_SKILL || inf == INF2_SPIRIT_SKILL )
return 1; // Can't do it.
switch( skill_id ) {
- case NV_FIRSTAID: case TF_HIDING: case AS_CLOAKING: case WZ_SIGHTRASHER:
- case RG_STRIPWEAPON: case RG_STRIPSHIELD: case RG_STRIPARMOR: case WZ_METEOR:
- case RG_STRIPHELM: case SC_STRIPACCESSARY: case ST_FULLSTRIP: case WZ_SIGHTBLASTER:
- case ST_CHASEWALK: case SC_ENERVATION: case SC_GROOMY: case WZ_ICEWALL:
- case SC_IGNORANCE: case SC_LAZINESS: case SC_UNLUCKY: case WZ_STORMGUST:
- case SC_WEAKNESS: case AL_RUWACH: case AL_PNEUMA: case WZ_JUPITEL:
- case AL_HEAL: case AL_BLESSING: case AL_INCAGI: case WZ_VERMILION:
- case AL_TELEPORT: case AL_WARP: case AL_HOLYWATER: case WZ_EARTHSPIKE:
- case AL_HOLYLIGHT: case PR_IMPOSITIO: case PR_ASPERSIO: case WZ_HEAVENDRIVE:
- case PR_SANCTUARY: case PR_STRECOVERY: case PR_MAGNIFICAT: case WZ_QUAGMIRE:
- case ALL_RESURRECTION: case PR_LEXDIVINA: case PR_LEXAETERNA: case HW_GRAVITATION:
- case PR_MAGNUS: case PR_TURNUNDEAD: case MG_SRECOVERY: case HW_MAGICPOWER:
- case MG_SIGHT: case MG_NAPALMBEAT: case MG_SAFETYWALL: case HW_GANBANTEIN:
- case MG_SOULSTRIKE: case MG_COLDBOLT: case MG_FROSTDIVER: case WL_DRAINLIFE:
- case MG_STONECURSE: case MG_FIREBALL: case MG_FIREWALL: case WL_SOULEXPANSION:
- case MG_FIREBOLT: case MG_LIGHTNINGBOLT: case MG_THUNDERSTORM: case MG_ENERGYCOAT:
- case WL_WHITEIMPRISON: case WL_SUMMONFB: case WL_SUMMONBL: case WL_SUMMONWB:
- case WL_SUMMONSTONE: case WL_SIENNAEXECRATE: case WL_RELEASE: case WL_EARTHSTRAIN:
- case WL_RECOGNIZEDSPELL: case WL_READING_SB: case SA_MAGICROD: case SA_SPELLBREAKER:
- case SA_DISPELL: case SA_FLAMELAUNCHER: case SA_FROSTWEAPON: case SA_LIGHTNINGLOADER:
- case SA_SEISMICWEAPON: case SA_VOLCANO: case SA_DELUGE: case SA_VIOLENTGALE:
- case SA_LANDPROTECTOR: case PF_HPCONVERSION: case PF_SOULCHANGE: case PF_SPIDERWEB:
- case PF_FOGWALL: case TK_RUN: case TK_HIGHJUMP: case TK_SEVENWIND:
- case SL_KAAHI: case SL_KAUPE: case SL_KAITE:
+ case NV_FIRSTAID:
+ case TF_HIDING:
+ case AS_CLOAKING:
+ case WZ_SIGHTRASHER:
+ case RG_STRIPWEAPON:
+ case RG_STRIPSHIELD:
+ case RG_STRIPARMOR:
+ case WZ_METEOR:
+ case RG_STRIPHELM:
+ case SC_STRIPACCESSARY:
+ case ST_FULLSTRIP:
+ case WZ_SIGHTBLASTER:
+ case ST_CHASEWALK:
+ case SC_ENERVATION:
+ case SC_GROOMY:
+ case WZ_ICEWALL:
+ case SC_IGNORANCE:
+ case SC_LAZINESS:
+ case SC_UNLUCKY:
+ case WZ_STORMGUST:
+ case SC_WEAKNESS:
+ case AL_RUWACH:
+ case AL_PNEUMA:
+ case WZ_JUPITEL:
+ case AL_HEAL:
+ case AL_BLESSING:
+ case AL_INCAGI:
+ case WZ_VERMILION:
+ case AL_TELEPORT:
+ case AL_WARP:
+ case AL_HOLYWATER:
+ case WZ_EARTHSPIKE:
+ case AL_HOLYLIGHT:
+ case PR_IMPOSITIO:
+ case PR_ASPERSIO:
+ case WZ_HEAVENDRIVE:
+ case PR_SANCTUARY:
+ case PR_STRECOVERY:
+ case PR_MAGNIFICAT:
+ case WZ_QUAGMIRE:
+ case ALL_RESURRECTION:
+ case PR_LEXDIVINA:
+ case PR_LEXAETERNA:
+ case HW_GRAVITATION:
+ case PR_MAGNUS:
+ case PR_TURNUNDEAD:
+ case MG_SRECOVERY:
+ case HW_MAGICPOWER:
+ case MG_SIGHT:
+ case MG_NAPALMBEAT:
+ case MG_SAFETYWALL:
+ case HW_GANBANTEIN:
+ case MG_SOULSTRIKE:
+ case MG_COLDBOLT:
+ case MG_FROSTDIVER:
+ case WL_DRAINLIFE:
+ case MG_STONECURSE:
+ case MG_FIREBALL:
+ case MG_FIREWALL:
+ case WL_SOULEXPANSION:
+ case MG_FIREBOLT:
+ case MG_LIGHTNINGBOLT:
+ case MG_THUNDERSTORM:
+ case MG_ENERGYCOAT:
+ case WL_WHITEIMPRISON:
+ case WL_SUMMONFB:
+ case WL_SUMMONBL:
+ case WL_SUMMONWB:
+ case WL_SUMMONSTONE:
+ case WL_SIENNAEXECRATE:
+ case WL_RELEASE:
+ case WL_EARTHSTRAIN:
+ case WL_RECOGNIZEDSPELL:
+ case WL_READING_SB:
+ case SA_MAGICROD:
+ case SA_SPELLBREAKER:
+ case SA_DISPELL:
+ case SA_FLAMELAUNCHER:
+ case SA_FROSTWEAPON:
+ case SA_LIGHTNINGLOADER:
+ case SA_SEISMICWEAPON:
+ case SA_VOLCANO:
+ case SA_DELUGE:
+ case SA_VIOLENTGALE:
+ case SA_LANDPROTECTOR:
+ case PF_HPCONVERSION:
+ case PF_SOULCHANGE:
+ case PF_SPIDERWEB:
+ case PF_FOGWALL:
+ case TK_RUN:
+ case TK_HIGHJUMP:
+ case TK_SEVENWIND:
+ case SL_KAAHI:
+ case SL_KAUPE:
+ case SL_KAITE:
// Skills that need to be confirmed.
- case SO_FIREWALK: case SO_ELECTRICWALK: case SO_SPELLFIST: case SO_EARTHGRAVE:
- case SO_DIAMONDDUST: case SO_POISON_BUSTER: case SO_PSYCHIC_WAVE: case SO_CLOUD_KILL:
- case SO_STRIKING: case SO_WARMER: case SO_VACUUM_EXTREME: case SO_VARETYR_SPEAR:
+ case SO_FIREWALK:
+ case SO_ELECTRICWALK:
+ case SO_SPELLFIST:
+ case SO_EARTHGRAVE:
+ case SO_DIAMONDDUST:
+ case SO_POISON_BUSTER:
+ case SO_PSYCHIC_WAVE:
+ case SO_CLOUD_KILL:
+ case SO_STRIKING:
+ case SO_WARMER:
+ case SO_VACUUM_EXTREME:
+ case SO_VARETYR_SPEAR:
case SO_ARRULLO:
- return 1; // Can't do it.
+ return 1; // Can't do it.
}
break;
case SC_KG_KAGEHUMI:
switch(skill_id) {
- case TF_HIDING: case AS_CLOAKING: case GC_CLOAKINGEXCEED: case SC_SHADOWFORM:
- case MI_HARMONIZE: case CG_MARIONETTE: case AL_TELEPORT: case TF_BACKSLIDING:
- case RA_CAMOUFLAGE: case ST_CHASEWALK: case GD_EMERGENCYCALL:
+ case TF_HIDING:
+ case AS_CLOAKING:
+ case GC_CLOAKINGEXCEED:
+ case SC_SHADOWFORM:
+ case MI_HARMONIZE:
+ case CG_MARIONETTE:
+ case AL_TELEPORT:
+ case TF_BACKSLIDING:
+ case RA_CAMOUFLAGE:
+ case ST_CHASEWALK:
+ case GD_EMERGENCYCALL:
return 1; // needs more info
}
break;
@@ -17982,10 +18210,10 @@ int skill_get_elemental_type( uint16 skill_id , uint16 skill_lv ) {
int type = 0;
switch( skill_id ) {
- case SO_SUMMON_AGNI: type = 2114; break;
- case SO_SUMMON_AQUA: type = 2117; break;
- case SO_SUMMON_VENTUS: type = 2120; break;
- case SO_SUMMON_TERA: type = 2123; break;
+ case SO_SUMMON_AGNI: type = 2114; break;
+ case SO_SUMMON_AQUA: type = 2117; break;
+ case SO_SUMMON_VENTUS: type = 2120; break;
+ case SO_SUMMON_TERA: type = 2123; break;
}
type += skill_lv - 1;
@@ -18120,7 +18348,7 @@ bool skill_parse_row_requiredb(char* split[], int columns, int current) {
skill->split_atoi(split[5],skill->db[idx].sp_rate);
skill->split_atoi(split[6],skill->db[idx].zeny);
- //Which weapon type are required, see doc/item_db for types
+ //Which weapon type are required, see doc/item_db for types
p = split[7];
for( j = 0; j < 32; j++ ) {
int l = atoi(p);
@@ -18543,7 +18771,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);
@@ -18749,7 +18977,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..f0a54b982 100644
--- a/src/map/skill.h
+++ b/src/map/skill.h
@@ -26,29 +26,29 @@ struct status_change_entry;
/**
* Defines
**/
-#define MAX_SKILL_DB MAX_SKILL
-#define MAX_SKILL_PRODUCE_DB 270
-#define MAX_PRODUCE_RESOURCE 10
-#define MAX_SKILL_ARROW_DB 140
-#define MAX_ARROW_RESOURCE 5
-#define MAX_SKILL_ABRA_DB 210
-#define MAX_SKILL_IMPROVISE_DB 30
-#define MAX_SKILL_LEVEL 10
-#define MAX_SKILL_UNIT_LAYOUT 45
-#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit
-#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1))
-#define MAX_SKILLTIMERSKILL 15
-#define MAX_SKILLUNITGROUP 25
-#define MAX_SKILL_ITEM_REQUIRE 10
+#define MAX_SKILL_DB MAX_SKILL
+#define MAX_SKILL_PRODUCE_DB 270
+#define MAX_PRODUCE_RESOURCE 10
+#define MAX_SKILL_ARROW_DB 140
+#define MAX_ARROW_RESOURCE 5
+#define MAX_SKILL_ABRA_DB 210
+#define MAX_SKILL_IMPROVISE_DB 30
+#define MAX_SKILL_LEVEL 10
+#define MAX_SKILL_UNIT_LAYOUT 45
+#define MAX_SQUARE_LAYOUT 5 // 11*11 Placement of a maximum unit
+#define MAX_SKILL_UNIT_COUNT ((MAX_SQUARE_LAYOUT*2+1)*(MAX_SQUARE_LAYOUT*2+1))
+#define MAX_SKILLTIMERSKILL 15
+#define MAX_SKILLUNITGROUP 25
+#define MAX_SKILL_ITEM_REQUIRE 10
#define MAX_SKILLUNITGROUPTICKSET 25
-#define MAX_SKILL_NAME_LENGTH 30
+#define MAX_SKILL_NAME_LENGTH 30
// (Epoque:) To-do: replace this macro with some sort of skill tree check (rather than hard-coded skill names)
#define skill_ischangesex(id) ( \
((id) >= BD_ADAPTATION && (id) <= DC_SERVICEFORYOU) || ((id) >= CG_ARROWVULCAN && (id) <= CG_MARIONETTE) || \
((id) >= CG_LONGINGFREEDOM && (id) <= CG_TAROTCARD) || ((id) >= WA_SWING_DANCE && (id) <= WM_UNLIMITED_HUMMING_VOICE))
-#define MAX_SKILL_SPELLBOOK_DB 17
+#define MAX_SKILL_SPELLBOOK_DB 17
#define MAX_SKILL_MAGICMUSHROOM_DB 23
//Walk intervals at which chase-skills are attempted to be triggered.
@@ -99,7 +99,7 @@ enum e_skill_inf2 {
INF2_GUILD_ONLY = 0x0800,
INF2_NO_ENEMY = 0x1000,
INF2_NOLP = 0x2000, // Spells that can ignore Land Protector
- INF2_CHORUS_SKILL = 0x4000, // Chorus skill
+ INF2_CHORUS_SKILL = 0x4000, // Chorus skill
};
@@ -112,19 +112,19 @@ enum e_skill_display {
};
enum {
- UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
- UF_NOREITERATION = 0x0002, // Spell cannot be stacked
- UF_NOFOOTSET = 0x0004, // Spell cannot be cast near/on targets
- UF_NOOVERLAP = 0x0008, // Spell effects do not overlap
- UF_PATHCHECK = 0x0010, // Only cells with a shootable path will be placed
- UF_NOPC = 0x0020, // May not target players
- UF_NOMOB = 0x0040, // May not target mobs
- UF_SKILL = 0x0080, // May target skills
- UF_DANCE = 0x0100, // Dance
- UF_ENSEMBLE = 0x0200, // Duet
- UF_SONG = 0x0400, // Song
- UF_DUALMODE = 0x0800, // Spells should trigger both ontimer and onplace/onout/onleft effects.
- UF_RANGEDSINGLEUNIT = 0x2000 // Hack for ranged layout, only display center
+ UF_DEFNOTENEMY = 0x0001, // If 'defunit_not_enemy' is set, the target is changed to 'friend'
+ UF_NOREITERATION = 0x0002, // Spell cannot be stacked
+ UF_NOFOOTSET = 0x0004, // Spell cannot be cast near/on targets
+ UF_NOOVERLAP = 0x0008, // Spell effects do not overlap
+ UF_PATHCHECK = 0x0010, // Only cells with a shootable path will be placed
+ UF_NOPC = 0x0020, // May not target players
+ UF_NOMOB = 0x0040, // May not target mobs
+ UF_SKILL = 0x0080, // May target skills
+ UF_DANCE = 0x0100, // Dance
+ UF_ENSEMBLE = 0x0200, // Duet
+ UF_SONG = 0x0400, // Song
+ UF_DUALMODE = 0x0800, // Spells should trigger both ontimer and onplace/onout/onleft effects.
+ UF_RANGEDSINGLEUNIT = 0x2000, // Hack for ranged layout, only display center
};
//Returns the cast type of the skill: ground cast, castend damage, castend no damage
@@ -1623,14 +1623,14 @@ enum {
UNT_MAKIBISHI,
UNT_VENOMFOG,
UNT_ICEMINE,
- UNT_FLAMECROSS,
- UNT_HELLBURNING,
- UNT_MAGMA_ERUPTION,
+ UNT_FLAMECROSS,
+ UNT_HELLBURNING,
+ UNT_MAGMA_ERUPTION,
UNT_KINGS_GRACE,
UNT_GLITTERING_GREED,
UNT_B_TRAP,
UNT_FIRE_RAIN,
-
+
/**
* Guild Auras
**/
@@ -1638,7 +1638,7 @@ enum {
UNT_GD_GLORYWOUNDS = 0xc2,
UNT_GD_SOULCOLD = 0xc3,
UNT_GD_HAWKEYES = 0xc4,
-
+
UNT_MAX = 0x190
};
@@ -1703,10 +1703,10 @@ struct skill_unit_group {
int bg_id;
int map;
int target_flag; //Holds BCT_* flag for battle_check_target
- int bl_flag; //Holds BL_* flag for map_foreachin* functions
+ int bl_flag; //Holds BL_* flag for map_foreachin* functions
int64 tick;
int limit,interval;
-
+
uint16 skill_id,skill_lv;
int val1,val2,val3;
char *valstr;
@@ -1724,9 +1724,9 @@ struct skill_unit_group {
struct skill_unit {
struct block_list bl;
-
+
struct skill_unit_group *group;
-
+
int limit;
int val1,val2;
short alive,range;
@@ -1852,49 +1852,49 @@ struct skill_interface {
int unit_temp[20]; // temporary storage for tracking skill unit skill ids as players move in/out of them
int unit_group_newid;
/* accesssors */
- int (*get_index) ( uint16 skill_id );
- int (*get_type) ( uint16 skill_id );
- int (*get_hit) ( uint16 skill_id );
- int (*get_inf) ( uint16 skill_id );
- int (*get_ele) ( uint16 skill_id, uint16 skill_lv );
- int (*get_nk) ( uint16 skill_id );
- int (*get_max) ( uint16 skill_id );
- int (*get_range) ( uint16 skill_id, uint16 skill_lv );
- int (*get_range2) (struct block_list *bl, uint16 skill_id, uint16 skill_lv);
- int (*get_splash) ( uint16 skill_id, uint16 skill_lv );
- int (*get_hp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_mhp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_sp) ( uint16 skill_id, uint16 skill_lv );
- int (*get_state) (uint16 skill_id);
- int (*get_spiritball) (uint16 skill_id, uint16 skill_lv);
- int (*get_zeny) ( uint16 skill_id, uint16 skill_lv );
- int (*get_num) ( uint16 skill_id, uint16 skill_lv );
- int (*get_cast) ( uint16 skill_id, uint16 skill_lv );
- int (*get_delay) ( uint16 skill_id, uint16 skill_lv );
- int (*get_walkdelay) ( uint16 skill_id, uint16 skill_lv );
- int (*get_time) ( uint16 skill_id, uint16 skill_lv );
- int (*get_time2) ( uint16 skill_id, uint16 skill_lv );
- int (*get_castnodex) ( uint16 skill_id, uint16 skill_lv );
- int (*get_delaynodex) ( uint16 skill_id ,uint16 skill_lv );
- int (*get_castdef) ( uint16 skill_id );
- int (*get_weapontype) ( uint16 skill_id );
- int (*get_ammotype) ( uint16 skill_id );
- int (*get_ammo_qty) ( uint16 skill_id, uint16 skill_lv );
- int (*get_unit_id) (uint16 skill_id,int flag);
- int (*get_inf2) ( uint16 skill_id );
- int (*get_castcancel) ( uint16 skill_id );
- int (*get_maxcount) ( uint16 skill_id, uint16 skill_lv );
- int (*get_blewcount) ( uint16 skill_id, uint16 skill_lv );
- int (*get_unit_flag) ( uint16 skill_id );
- int (*get_unit_target) ( uint16 skill_id );
- int (*get_unit_interval) ( uint16 skill_id );
- int (*get_unit_bl_target) ( uint16 skill_id );
- int (*get_unit_layout_type) ( uint16 skill_id ,uint16 skill_lv );
- int (*get_unit_range) ( uint16 skill_id, uint16 skill_lv );
- int (*get_cooldown) ( uint16 skill_id, uint16 skill_lv );
- int (*tree_get_max) ( uint16 skill_id, int b_class );
- const char* (*get_name) ( uint16 skill_id );
- const char* (*get_desc) ( uint16 skill_id );
+ int (*get_index) ( uint16 skill_id );
+ int (*get_type) ( uint16 skill_id );
+ int (*get_hit) ( uint16 skill_id );
+ int (*get_inf) ( uint16 skill_id );
+ int (*get_ele) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_nk) ( uint16 skill_id );
+ int (*get_max) ( uint16 skill_id );
+ int (*get_range) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_range2) (struct block_list *bl, uint16 skill_id, uint16 skill_lv);
+ int (*get_splash) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_hp) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_mhp) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_sp) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_state) (uint16 skill_id);
+ int (*get_spiritball) (uint16 skill_id, uint16 skill_lv);
+ int (*get_zeny) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_num) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_cast) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_delay) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_walkdelay) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_time) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_time2) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_castnodex) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_delaynodex) ( uint16 skill_id ,uint16 skill_lv );
+ int (*get_castdef) ( uint16 skill_id );
+ int (*get_weapontype) ( uint16 skill_id );
+ int (*get_ammotype) ( uint16 skill_id );
+ int (*get_ammo_qty) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_unit_id) (uint16 skill_id,int flag);
+ int (*get_inf2) ( uint16 skill_id );
+ int (*get_castcancel) ( uint16 skill_id );
+ int (*get_maxcount) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_blewcount) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_unit_flag) ( uint16 skill_id );
+ int (*get_unit_target) ( uint16 skill_id );
+ int (*get_unit_interval) ( uint16 skill_id );
+ int (*get_unit_bl_target) ( uint16 skill_id );
+ int (*get_unit_layout_type) ( uint16 skill_id ,uint16 skill_lv );
+ int (*get_unit_range) ( uint16 skill_id, uint16 skill_lv );
+ int (*get_cooldown) ( uint16 skill_id, uint16 skill_lv );
+ int (*tree_get_max) ( uint16 skill_id, int b_class );
+ const char *(*get_name) ( uint16 skill_id );
+ const char *(*get_desc) ( uint16 skill_id );
/* check */
void (*chk) (uint16* skill_id);
/* whether its CAST_GROUND, CAST_DAMAGE or CAST_NODAMAGE */
@@ -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 4a2a6c344..9cd01f7b3 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -245,7 +245,7 @@ void initChangeTables(void) {
set_sc( NPC_BARRIER , SC_BARRIER , SI_BLANK , SCB_MDEF|SCB_DEF );
add_sc( NPC_DEFENDER , SC_ARMOR );
add_sc( NPC_LICK , SC_STUN );
- set_sc( NPC_HALLUCINATION , SC_ILLUSION , SI_ILLUSION , SCB_NONE );
+ set_sc( NPC_HALLUCINATION , SC_ILLUSION , SI_ILLUSION , SCB_NONE );
add_sc( NPC_REBIRTH , SC_REBIRTH );
add_sc( RG_RAID , SC_STUN );
#ifdef RENEWAL
@@ -469,8 +469,8 @@ void initChangeTables(void) {
set_sc( HAMI_BLOODLUST , SC_HAMI_BLOODLUST , SI_BLANK , SCB_BATK|SCB_WATK );
// Homunculus S
- set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SI_LIGHT_OF_REGENE , SCB_NONE );
- set_sc( MH_OVERED_BOOST , SC_OVERED_BOOST , SI_OVERED_BOOST , SCB_FLEE|SCB_ASPD|SCB_DEF );
+ set_sc( MH_LIGHT_OF_REGENE , SC_LIGHT_OF_REGENE , SI_LIGHT_OF_REGENE , SCB_NONE );
+ set_sc( MH_OVERED_BOOST , SC_OVERED_BOOST , SI_OVERED_BOOST , SCB_FLEE|SCB_ASPD|SCB_DEF );
add_sc(MH_STAHL_HORN, SC_STUN);
set_sc(MH_ANGRIFFS_MODUS, SC_ANGRIFFS_MODUS, SI_ANGRIFFS_MODUS, SCB_BATK | SCB_DEF | SCB_FLEE | SCB_MAXHP);
@@ -529,14 +529,14 @@ void initChangeTables(void) {
set_sc( RK_DEATHBOUND , SC_DEATHBOUND , SI_DEATHBOUND , SCB_NONE );
set_sc( RK_WINDCUTTER , SC_FEAR , SI_BLANK , SCB_FLEE|SCB_HIT );
add_sc( RK_DRAGONBREATH , SC_BURNING );
- set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE );
+ set_sc( RK_MILLENNIUMSHIELD , SC_MILLENNIUMSHIELD , SI_BLANK , SCB_NONE );
set_sc( RK_REFRESH , SC_REFRESH , SI_REFRESH , SCB_NONE );
set_sc( RK_GIANTGROWTH , SC_GIANTGROWTH , SI_GIANTGROWTH , SCB_STR );
set_sc( RK_STONEHARDSKIN , SC_STONEHARDSKIN , SI_STONEHARDSKIN , SCB_NONE );
set_sc( RK_VITALITYACTIVATION, SC_VITALITYACTIVATION, SI_VITALITYACTIVATION, SCB_REGEN );
set_sc( RK_FIGHTINGSPIRIT , SC_FIGHTINGSPIRIT , SI_FIGHTINGSPIRIT , SCB_WATK|SCB_ASPD );
set_sc( RK_ABUNDANCE , SC_ABUNDANCE , SI_ABUNDANCE , SCB_NONE );
- set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE );
+ set_sc( RK_CRUSHSTRIKE , SC_CRUSHSTRIKE , SI_CRUSHSTRIKE , SCB_NONE );
add_sc( RK_DRAGONBREATH_WATER, SC_FROSTMISTY );
/**
* GC Guillotine Cross
@@ -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
@@ -677,7 +677,7 @@ void initChangeTables(void) {
set_sc_with_vfx( SO_DIAMONDDUST , SC_COLD , SI_COLD , SCB_NONE ); // it does show the snow icon on mobs but doesn't affect it.
set_sc( SO_CLOUD_KILL , SC_POISON , SI_CLOUDKILL , SCB_NONE );
set_sc( SO_STRIKING , SC_STRIKING , SI_STRIKING , SCB_WATK|SCB_CRI );
- set_sc( SO_WARMER , SC_WARMER , SI_WARMER , SCB_NONE );
+ add_sc( SO_WARMER , SC_WARMER ); // At the moment, no icon on officials
set_sc( SO_VACUUM_EXTREME , SC_VACUUM_EXTREME , SI_VACUUM_EXTREME , SCB_NONE );
set_sc( SO_ARRULLO , SC_DEEP_SLEEP , SI_DEEPSLEEP , SCB_NONE );
set_sc( SO_FIRE_INSIGNIA , SC_FIRE_INSIGNIA , SI_FIRE_INSIGNIA , SCB_MATK | SCB_BATK | SCB_WATK | SCB_ATK_ELE | SCB_REGEN );
@@ -724,25 +724,25 @@ void initChangeTables(void) {
set_sc( EL_ROCK_CRUSHER , SC_ROCK_CRUSHER , SI_ROCK_CRUSHER , SCB_DEF );
set_sc( EL_ROCK_CRUSHER_ATK, SC_ROCK_CRUSHER_ATK , SI_ROCK_CRUSHER_ATK , SCB_SPEED );
- add_sc( KO_YAMIKUMO , SC_HIDING );
- set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE );
- add_sc( KO_MAKIBISHI , SC_STUN );
- set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE );
- set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
- add_sc( KO_JYUSATSU , SC_CURSE );
- set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE );
- set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK );
- set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE );
- set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE );
- set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE );
- set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK );
- set_sc_with_vfx( OB_AKAITSUKI , SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE );
- set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE );
-
- set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
-
- add_sc( ALL_REVERSEORCISH , SC_ORCISH );
- set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SI_ANGEL_PROTECT , SCB_REGEN );
+ add_sc( KO_YAMIKUMO , SC_HIDING );
+ set_sc_with_vfx( KO_JYUMONJIKIRI , SC_KO_JYUMONJIKIRI , SI_KO_JYUMONJIKIRI , SCB_NONE );
+ add_sc( KO_MAKIBISHI , SC_STUN );
+ set_sc( KO_MEIKYOUSISUI , SC_MEIKYOUSISUI , SI_MEIKYOUSISUI , SCB_NONE );
+ set_sc( KO_KYOUGAKU , SC_KYOUGAKU , SI_KYOUGAKU , SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+ add_sc( KO_JYUSATSU , SC_CURSE );
+ set_sc( KO_ZENKAI , SC_ZENKAI , SI_ZENKAI , SCB_NONE );
+ set_sc( KO_IZAYOI , SC_IZAYOI , SI_IZAYOI , SCB_MATK );
+ set_sc( KG_KYOMU , SC_KYOMU , SI_KYOMU , SCB_NONE );
+ set_sc( KG_KAGEMUSYA , SC_KAGEMUSYA , SI_KAGEMUSYA , SCB_NONE );
+ set_sc( KG_KAGEHUMI , SC_KG_KAGEHUMI , SI_KG_KAGEHUMI , SCB_NONE );
+ set_sc( OB_ZANGETSU , SC_ZANGETSU , SI_ZANGETSU , SCB_MATK|SCB_BATK );
+ set_sc_with_vfx( OB_AKAITSUKI, SC_AKAITSUKI , SI_AKAITSUKI , SCB_NONE );
+ set_sc( OB_OBOROGENSOU , SC_GENSOU , SI_GENSOU , SCB_NONE );
+
+ set_sc( ALL_FULL_THROTTLE , SC_FULL_THROTTLE , SI_FULL_THROTTLE , SCB_SPEED|SCB_STR|SCB_AGI|SCB_VIT|SCB_INT|SCB_DEX|SCB_LUK );
+
+ add_sc( ALL_REVERSEORCISH , SC_ORCISH );
+ set_sc( ALL_ANGEL_PROTECT , SC_ANGEL_PROTECT , SI_ANGEL_PROTECT , SCB_REGEN );
add_sc( NPC_WIDEHEALTHFEAR , SC_FEAR );
add_sc( NPC_WIDEBODYBURNNING , SC_BURNING );
@@ -750,7 +750,7 @@ void initChangeTables(void) {
add_sc( NPC_WIDECOLD , SC_COLD );
add_sc( NPC_WIDE_DEEP_SLEEP , SC_DEEP_SLEEP );
add_sc( NPC_WIDESIREN , SC_SIREN );
-
+
set_sc_with_vfx( GN_ILLUSIONDOPING , SC_ILLUSIONDOPING , SI_ILLUSIONDOPING , SCB_HIT );
// Storing the target job rather than simply SC_SOULLINK simplifies code later on.
@@ -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;
@@ -1004,6 +1007,7 @@ void initChangeTables(void) {
status->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN;
status->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2;
status->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2;
+ status->ChangeFlagTable[SC_MYSTERIOUS_POWDER] |= SCB_MAXHP;
status->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED;
status->ChangeFlagTable[SC_WEDDING] = SCB_SPEED;
@@ -1018,32 +1022,32 @@ void initChangeTables(void) {
status->ChangeFlagTable[SC_DECORATION_OF_MUSIC] |= SCB_NONE;
/* status->DisplayType Table [Ind/Hercules] */
- status->DisplayType[SC_ALL_RIDING] = true;
- status->DisplayType[SC_PUSH_CART] = true;
- status->DisplayType[SC_SUMMON1] = true;
- status->DisplayType[SC_SUMMON2] = true;
- status->DisplayType[SC_SUMMON3] = true;
- status->DisplayType[SC_SUMMON4] = true;
- status->DisplayType[SC_SUMMON5] = true;
- status->DisplayType[SC_CAMOUFLAGE] = true;
- status->DisplayType[SC_DUPLELIGHT] = true;
- status->DisplayType[SC_ORATIO] = true;
- status->DisplayType[SC_FROSTMISTY] = true;
- status->DisplayType[SC_VENOMIMPRESS] = true;
- status->DisplayType[SC_HALLUCINATIONWALK] = true;
- status->DisplayType[SC_ROLLINGCUTTER] = true;
- status->DisplayType[SC_BANDING] = true;
- status->DisplayType[SC_COLD] = true;
- status->DisplayType[SC_DEEP_SLEEP] = true;
- status->DisplayType[SC_CURSEDCIRCLE_ATKER]= true;
- status->DisplayType[SC_CURSEDCIRCLE_TARGET]= true;
- status->DisplayType[SC_BLOOD_SUCKER] = true;
- status->DisplayType[SC__SHADOWFORM] = true;
- status->DisplayType[SC_MONSTER_TRANSFORM] = true;
- status->DisplayType[SC_MOONSTAR] = true;
- status->DisplayType[SC_SUPER_STAR] = true;
- status->DisplayType[SC_STRANGELIGHTS] = true;
- status->DisplayType[SC_DECORATION_OF_MUSIC] = true;
+ status->DisplayType[SC_ALL_RIDING] = true;
+ status->DisplayType[SC_PUSH_CART] = true;
+ status->DisplayType[SC_SUMMON1] = true;
+ status->DisplayType[SC_SUMMON2] = true;
+ status->DisplayType[SC_SUMMON3] = true;
+ status->DisplayType[SC_SUMMON4] = true;
+ status->DisplayType[SC_SUMMON5] = true;
+ status->DisplayType[SC_CAMOUFLAGE] = true;
+ status->DisplayType[SC_DUPLELIGHT] = true;
+ status->DisplayType[SC_ORATIO] = true;
+ status->DisplayType[SC_FROSTMISTY] = true;
+ status->DisplayType[SC_VENOMIMPRESS] = true;
+ status->DisplayType[SC_HALLUCINATIONWALK] = true;
+ status->DisplayType[SC_ROLLINGCUTTER] = true;
+ status->DisplayType[SC_BANDING] = true;
+ status->DisplayType[SC_COLD] = true;
+ status->DisplayType[SC_DEEP_SLEEP] = true;
+ status->DisplayType[SC_CURSEDCIRCLE_ATKER] = true;
+ status->DisplayType[SC_CURSEDCIRCLE_TARGET] = true;
+ status->DisplayType[SC_BLOOD_SUCKER] = true;
+ status->DisplayType[SC__SHADOWFORM] = true;
+ status->DisplayType[SC_MONSTER_TRANSFORM] = true;
+ status->DisplayType[SC_MOONSTAR] = true;
+ status->DisplayType[SC_SUPER_STAR] = true;
+ status->DisplayType[SC_STRANGELIGHTS] = true;
+ status->DisplayType[SC_DECORATION_OF_MUSIC] = true;
#ifdef RENEWAL_EDP
// renewal EDP increases your weapon atk
@@ -1134,10 +1138,10 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
struct status_change *sc;
int hp,sp;
- /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */
+ /* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */
hp = (int)cap_value(in_hp,INT_MIN,INT_MAX);
sp = (int)cap_value(in_sp,INT_MIN,INT_MAX);
-
+
if(sp && !(target->type&BL_CONSUME))
sp = 0; //Not a valid SP target.
@@ -1174,10 +1178,12 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
if( !st->hp )
flag |= 8;
+#if 0
// Let through. battle.c/skill.c have the whole logic of when it's possible or
// not to hurt someone (and this check breaks pet catching) [Skotlex]
- // if (!target->prev && !(flag&2))
- // return 0; //Cannot damage a bl not on a map, except when "charging" hp/sp
+ if (!target->prev && !(flag&2))
+ return 0; //Cannot damage a bl not on a map, except when "charging" hp/sp
+#endif // 0
sc = status->get_sc(target);
if( hp && battle_config.invincible_nodamage && src && sc && sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] )
@@ -1186,11 +1192,11 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
if( hp && !(flag&1) ) {
if( sc ) {
struct status_change_entry *sce;
-
+
#ifdef DEVOTION_REFLECT_DAMAGE
if(src && (sce = sc->data[SC_DEVOTION])) {
struct block_list *d_bl = map->id2bl(sce->val1);
-
+
if(d_bl &&((d_bl->type == BL_MER && ((TBL_MER *)d_bl)->master && ((TBL_MER *)d_bl)->master->bl.id == target->id)
|| (d_bl->type == BL_PC && ((TBL_PC *)d_bl)->devotion[sce->val2] == target->id)) && check_distance_bl(target, d_bl, sce->val3)) {
clif->damage(d_bl, d_bl, 0, 0, hp, 0, 0, 0);
@@ -1200,7 +1206,6 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
status_change_end(target, SC_DEVOTION, INVALID_TIMER);
}
#endif
-
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
status_change_end(target, SC_STONE, INVALID_TIMER);
status_change_end(target, SC_FREEZE, INVALID_TIMER);
@@ -1264,8 +1269,8 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
unit->stop_walking( target, 1 );
}
- if( st->hp || (flag&8) )
- { //Still lives or has been dead before this damage.
+ if (st->hp || (flag&8)) {
+ //Still lives or has been dead before this damage.
if (walkdelay)
unit->set_walkdelay(target, timer->gettick(), walkdelay, 0);
return (int)(hp+sp);
@@ -1283,7 +1288,7 @@ int status_damage(struct block_list *src,struct block_list *target,int64 in_hp,
case BL_HOM: flag = homun->dead((TBL_HOM*)target); break;
case BL_MER: flag = mercenary->dead((TBL_MER*)target); break;
case BL_ELEM: flag = elemental->dead((TBL_ELEM*)target); break;
- default: //Unhandled case, do nothing to object.
+ default: //Unhandled case, do nothing to object.
flag = 0;
break;
}
@@ -1366,10 +1371,10 @@ int status_heal(struct block_list *bl,int64 in_hp,int64 in_sp, int flag) {
if (st == &status->dummy || !st->hp)
return 0;
- /* here onwards we consider it a 32-type, the client does not support higher and from here onwards the value doesn't get thru percentage modifiers */
+ /* From here onwards, we consider it a 32-type as the client does not support higher and the value doesn't get through percentage modifiers */
hp = (int)cap_value(in_hp,INT_MIN,INT_MAX);
sp = (int)cap_value(in_sp,INT_MIN,INT_MAX);
-
+
sc = status->get_sc(bl);
if (sc && !sc->count)
sc = NULL;
@@ -1513,13 +1518,12 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per
if (bl->prev) //Animation only if character is already on a map.
clif->resurrection(bl, 1);
-
+
switch (bl->type) {
case BL_PC: pc->revive((TBL_PC*)bl, hp, sp); break;
case BL_MOB: mob->revive((TBL_MOB*)bl, hp); break;
case BL_HOM: homun->revive((TBL_HOM*)bl, hp, sp); break;
}
-
return 1;
}
@@ -1539,7 +1543,7 @@ int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int
hp = st->max_hp - st->hp;
else if (per_hp && !hp)
hp = 1;
-
+
if(sp > st->max_sp - st->sp)
sp = st->max_sp - st->sp;
else if (per_sp && !sp)
@@ -1562,9 +1566,9 @@ int status_fixed_revive(struct block_list *bl, unsigned int per_hp, unsigned int
* Checks whether the src can use the skill on the target,
* taking into account status/option of both source/target. [Skotlex]
* flag:
-* 0 - Trying to use skill on target.
-* 1 - Cast bar is done.
-* 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones.
+* 0 - Trying to use skill on target.
+* 1 - Cast bar is done.
+* 2 - Skill already pulled off, check is due to ground-based skills or splash-damage ones.
* src MAY be null to indicate we shouldn't check it, this is a ground-based skill attack.
* target MAY Be null, in which case the checks are only to see
* whether the source can cast or not the skill on the ground.
@@ -1600,8 +1604,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
if( src->type == BL_PC )
clif->msg((TBL_PC*)src, SKILL_CANT_USE_AREA); // This skill cannot be used within this area
else if( src->type == BL_MOB && map->list[src->m].zone->disabled_skills[i]->subtype != MZS_NONE ) {
- if( (st->mode&MD_BOSS) && !(map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS) )
- break;
+ if( st->mode&MD_BOSS ) { /** is boss **/
+ if( !( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS ) )
+ break;
+ } else { /** is not boss **/
+ if( map->list[src->m].zone->disabled_skills[i]->subtype&MZS_BOSS )
+ break;
+ }
}
return 0;
}
@@ -1692,12 +1701,13 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
}
}
if ((sc->data[SC_DANCING]->val1&0xFFFF) == CG_HERMODE && skill_id == BD_ADAPTATION)
- return 0; //Can't amp out of Wand of Hermode :/ [Skotlex]
+ return 0; //Can't amp out of Wand of Hermode :/ [Skotlex]
}
if (skill_id && //Do not block item-casted skills.
(src->type != BL_PC || ((TBL_PC*)src)->skillitem != skill_id)
- ) { //Skills blocked through status changes...
+ ) {
+ //Skills blocked through status changes...
if (!flag && ( //Blocked only from using the skill (stuff like autospell may still go through
sc->data[SC_SILENCE] ||
sc->data[SC_STEELBODY] ||
@@ -1789,17 +1799,10 @@ 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);
- //You cannot hide from ground skills.
- if( skill->get_ele(skill_id,1) == ELE_EARTH ) //TODO: Need Skill Lv here :/
+ // 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;
- else {
- switch ( skill_id ) {
- case MO_ABSORBSPIRITS: // it works when already casted and target suddenly hides.
- case SA_DISPELL:
- hide_flag &= ~OPTION_HIDE;
- break;
- }
- }
switch( target->type ) {
case BL_PC: {
@@ -1820,7 +1823,8 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
}
}
break;
- case BL_ITEM: //Allow targeting of items to pick'em up (or in the case of mobs, to loot them).
+ case BL_ITEM:
+ //Allow targeting of items to pick'em up (or in the case of mobs, to loot them).
//TODO: Would be nice if this could be used to judge whether the player can or not pick up the item it targets. [Skotlex]
if (st->mode&MD_LOOTER)
return 1;
@@ -1847,226 +1851,6 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin
return 1;
}
-//Checks whether the source can see and chase target.
-int status_check_visibility(struct block_list *src, struct block_list *target) {
- int view_range;
- struct status_change *tsc = NULL;
-
- switch (src->type) {
- case BL_MOB:
- view_range = ((TBL_MOB*)src)->min_chase;
- break;
- case BL_PET:
- view_range = ((TBL_PET*)src)->db->range2;
- break;
- default:
- view_range = AREA_SIZE;
- }
-
- if (src->m != target->m || !check_distance_bl(src, target, view_range))
- return 0;
-
- if( src->type == BL_NPC ) /* NPCs don't care for the rest */
- return 1;
-
- if( ( tsc = status->get_sc(target) ) ) {
- struct status_data *st = status->get_status_data(src);
-
- switch (target->type) { //Check for chase-walk/hiding/cloaking opponents.
- case BL_PC:
- if ( tsc->data[SC_CLOAKINGEXCEED] && !(st->mode&MD_BOSS) )
- return 0;
- if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_STEALTHFIELD] || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&MD_BOSS) &&
- ( ((TBL_PC*)target)->special_state.perfect_hiding || !(st->mode&MD_DETECTOR) ) )
- return 0;
- break;
- default:
- if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&(MD_BOSS|MD_DETECTOR)) )
- return 0;
-
- }
- }
-
- return 1;
-}
-
-// Basic ASPD value
-int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) {
- int amotion;
-#ifdef RENEWAL_ASPD
- short mod = -1;
-
- switch( sd->weapontype2 ){ // adjustment for dual wielding
- case W_DAGGER: mod = 0; break; // 0, 1, 1
- case W_1HSWORD:
- case W_1HAXE: mod = 1;
- if( (sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS ) // 0, 2, 3
- mod = sd->weapontype2 / W_1HSWORD + W_1HSWORD / sd->weapontype2 ;
- }
-
- amotion = ( sd->status.weapon < MAX_WEAPON_TYPE && mod < 0 )
- ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
- : ((status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] // dual-wield
- + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod
- - status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]
- + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]);
-
- if ( sd->status.shield )
- amotion += ( 2000 - status->aspd_base[pc->class2idx(sd->status.class_)][W_FIST] ) +
- ( status->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000 );
-
-#else
- // base weapon delay
- amotion = (sd->status.weapon < MAX_WEAPON_TYPE)
- ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
- : (status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield
-
- // percentual delay reduction from stats
- amotion -= amotion * (4*st->agi + st->dex)/1000;
-#endif
-
- // raw delay adjustment from bAspd bonus
- amotion += sd->bonus.aspd_add;
-
- /* angra manyu disregards aspd_base and similar */
- if( sd->equip_index[EQI_HAND_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid == ITEMID_ANGRA_MANYU )
- return 0;
-
- return amotion;
-}
-
-unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) {
- int flag = 0, str, dex,
-#ifdef RENEWAL
- rstr,
-#endif
- dstr;
-
-
- if(!(bl->type&battle_config.enable_baseatk))
- return 0;
-
- if (bl->type == BL_PC)
- switch(((TBL_PC*)bl)->status.weapon){
- case W_BOW:
- case W_MUSICAL:
- case W_WHIP:
- case W_REVOLVER:
- case W_RIFLE:
- case W_GATLING:
- case W_SHOTGUN:
- case W_GRENADE:
- flag = 1;
- }
- if (flag) {
-#ifdef RENEWAL
- rstr =
-#endif
- str = st->dex;
- dex = st->str;
- } else {
-#ifdef RENEWAL
- rstr =
-#endif
- str = st->str;
- dex = st->dex;
- }
- //Normally only players have base-atk, but homunc have a different batk
- // equation, hinting that perhaps non-players should use this for batk.
- // [Skotlex]
- dstr = str/10;
- str += dstr*dstr;
- if (bl->type == BL_PC)
-#ifdef RENEWAL
- str = (int)(rstr + (float)dex/5 + (float)st->luk/3 + (float)((TBL_PC*)bl)->status.base_level/4);
- else if(bl->type == BL_MOB)
- str = rstr + ((TBL_MOB*)bl)->level;
-#else
- str+= dex/5 + st->luk/5;
-#endif
- return cap_value(str, 0, USHRT_MAX);
-}
-
-#ifndef RENEWAL
-static inline unsigned short status_base_matk_min(const struct status_data *st){ return st->int_+(st->int_/7)*(st->int_/7); }
-#endif // not RENEWAL
-static inline unsigned short status_base_matk_max(const struct status_data *st){ return st->int_+(st->int_/5)*(st->int_/5); }
-
-unsigned short status_base_matk(const struct status_data *st, int level) {
-#ifdef RENEWAL
- return st->int_+(st->int_/2)+(st->dex/5)+(st->luk/3)+(level/4);
-#else
- return 0;
-#endif
-}
-
-//Fills in the misc data that can be calculated from the other status info (except for level)
-void status_calc_misc(struct block_list *bl, struct status_data *st, int level) {
- //Non players get the value set, players need to stack with previous bonuses.
- if( bl->type != BL_PC )
- st->batk =
- st->hit = st->flee =
- st->def2 = st->mdef2 =
- st->cri = st->flee2 = 0;
-
-#ifdef RENEWAL // renewal formulas
- st->matk_min = st->matk_max = bl->type == BL_PC ? status->base_matk(st, level) : level + st->int_;
- st->hit += level + st->dex + (bl->type == BL_PC ? st->luk/3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
- st->flee += level + st->agi + (bl->type == BL_PC ? st->luk/5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
- st->def2 += (int)(((float)level + st->vit)/2 + ( bl->type == BL_PC ? ((float)st->agi/5) : 0 )); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
- st->mdef2 += (int)( bl->type == BL_PC ?(st->int_ + ((float)level/4) + ((float)(st->dex+st->vit)/5)):((float)(st->int_ + level)/4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
-#else // not RENEWAL
- st->matk_min = status_base_matk_min(st);
- st->matk_max = status_base_matk_max(st);
- st->hit += level + st->dex;
- st->flee += level + st->agi;
- st->def2 += st->vit;
- st->mdef2 += st->int_ + (st->vit>>1);
-#endif // RENEWAL
-
- if( bl->type&battle_config.enable_critical )
- st->cri += 10 + (st->luk*10/3); //(every 1 luk = +0.3 critical)
- else
- st->cri = 0;
-
- if (bl->type&battle_config.enable_perfect_flee)
- st->flee2 += st->luk + 10; //(every 10 luk = +1 perfect flee)
- else
- st->flee2 = 0;
-
- if (st->batk) {
- int temp = st->batk + status->base_atk(bl, st);
- st->batk = cap_value(temp, 0, USHRT_MAX);
- } else
- st->batk = status->base_atk(bl, st);
- if (st->cri)
- switch (bl->type) {
- case BL_MOB:
- if(battle_config.mob_critical_rate != 100)
- st->cri = st->cri*battle_config.mob_critical_rate/100;
- if(!st->cri && battle_config.mob_critical_rate)
- st->cri = 10;
- break;
- case BL_PC:
- //Players don't have a critical adjustment setting as of yet.
- break;
- case BL_MER:
-#ifdef RENEWAL
- st->matk_min = st->matk_max = status_base_matk_max(st);
- st->def2 = st->vit + level / 10 + st->vit / 5;
- st->mdef2 = level / 10 + st->int_ / 5;
-#endif
- break;
- default:
- if(battle_config.critical_rate != 100)
- st->cri = st->cri*battle_config.critical_rate/100;
- if (!st->cri && battle_config.critical_rate)
- st->cri = 10;
- }
- if(bl->type&BL_REGEN)
- status->calc_regen(bl, st, status->get_regen_data(bl));
-}
-
//Skotlex: Calculates the initial status for the given mob
//first will only be false when the mob leveled up or got a GuardUp level.
int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
@@ -2169,7 +1953,7 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
if (flag&2 && battle_config.mob_size_influence) {
// change for sized monsters [Valaris]
- if (md->special_state.size==SZ_SMALL) {
+ if (md->special_state.size==SZ_MEDIUM) {
mstatus->max_hp>>=1;
mstatus->max_sp>>=1;
if (!mstatus->max_hp) mstatus->max_hp = 1;
@@ -2204,8 +1988,8 @@ int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) {
status->calc_misc(&md->bl, mstatus, md->level);
- if(flag&4)
- { // Strengthen Guardians - custom value +10% / lv
+ if (flag&4) {
+ // Strengthen Guardians - custom value +10% / lv
struct guild_castle *gc;
gc=guild->mapname2gc(map->list[md->bl.m].name);
if (!gc)
@@ -2286,7 +2070,7 @@ int status_calc_pet_(struct pet_data *pd, enum e_status_calc_opt opt)
status->calc_misc(&pd->bl, &pd->status, lv);
- if (! (opt&SCO_FIRST) ) //Not done the first time because the pet is not visible yet
+ if (! (opt&SCO_FIRST) ) //Not done the first time because the pet is not visible yet
clif->send_petstatus(sd);
}
} else if ( opt&SCO_FIRST ) {
@@ -2385,7 +2169,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
b_max_weight = sd->max_weight;
b_cart_weight_max = sd->cart_weight_max;
- pc->calc_skilltree(sd); // SkillTree calculation
+ pc->calc_skilltree(sd); // SkillTree calculation
sd->max_weight = status->max_weight_base[pc->class2idx(sd->status.class_)]+sd->status.str*300;
@@ -2461,7 +2245,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_CLAIRVOYANCE);
memset(&sd->special_state,0,sizeof(sd->special_state));
-
+
if (!sd->state.permanent_speed) {
memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
bstatus->speed = DEFAULT_WALK_SPEED;
@@ -2470,19 +2254,20 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
memset(&bstatus->max_hp, 0, sizeof(struct status_data)-(sizeof(bstatus->hp)+sizeof(bstatus->sp)));
bstatus->speed = pSpeed;
}
-
+
//FIXME: Most of these stuff should be calculated once, but how do I fix the memset above to do that? [Skotlex]
//Give them all modes except these (useful for clones)
bstatus->mode = MD_MASK&~(MD_BOSS|MD_PLANT|MD_DETECTOR|MD_ANGRY|MD_TARGETWEAK);
- bstatus->size = (sd->class_&JOBL_BABY)?SZ_MEDIUM:SZ_SMALL;
- if (battle_config.character_size && (pc_isriding(sd) || pc_isridingdragon(sd)) ) { //[Lupus]
+ bstatus->size = (sd->class_&JOBL_BABY)?SZ_SMALL:SZ_MEDIUM;
+ 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
- if(battle_config.character_size&SZ_SMALL)
+ } else {
+ if(battle_config.character_size&SZ_MEDIUM)
bstatus->size++;
+ }
}
bstatus->aspd_rate = 1000;
bstatus->ele_lv = 1;
@@ -2557,8 +2342,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
bstatus->def += sd->inventory_data[index]->def;
- if(opt&SCO_FIRST && sd->inventory_data[index]->equip_script)
- { //Execute equip-script on login
+ if (opt&SCO_FIRST && sd->inventory_data[index]->equip_script) {
+ //Execute equip-script on login
script->run(sd->inventory_data[index]->equip_script,0,sd->bl.id,0);
if (!calculating)
return 1;
@@ -2608,8 +2393,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
return 1;
}
- if(sd->status.inventory[index].card[0]==CARD0_FORGE)
- { // Forged weapon
+ if (sd->status.inventory[index].card[0]==CARD0_FORGE) {
+ // Forged weapon
wd->star += (sd->status.inventory[index].card[1]>>8);
if(wd->star >= 15) wd->star = 40; // 3 Star Crumbs now give +40 dmg
if(pc->famerank(MakeDWord(sd->status.inventory[index].card[2],sd->status.inventory[index].card[3]) ,MAPID_BLACKSMITH))
@@ -2637,7 +2422,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
if(sd->equip_index[EQI_AMMO] >= 0){
index = sd->equip_index[EQI_AMMO];
- if(sd->inventory_data[index]){ // Arrows
+ if (sd->inventory_data[index]) {
+ // Arrows
sd->bonus.arrow_atk += sd->inventory_data[index]->atk;
sd->state.lr_flag = 2;
if( !itemdb_is_GNthrowable(sd->inventory_data[index]->nameid) ) //don't run scripts on throwable items
@@ -2652,7 +2438,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
for( i = 0; i < sd->combo_count; i++ ) {
struct item_combo *combo = itemdb->id2combo(sd->combos[i].id);
unsigned char j;
-
+
/**
* ensure combo usage is allowed at this location
**/
@@ -2665,10 +2451,10 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
if( k != map->list[sd->bl.m].zone->disabled_items_count )
break;
}
-
+
if( j != combo->count )
continue;
-
+
script->run(sd->combos[i].bonus,0,sd->bl.id,0);
if (!calculating) //Abort, script->run retriggered this.
return 1;
@@ -2771,9 +2557,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];
@@ -3053,9 +2840,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)
@@ -3065,9 +2852,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;
@@ -3085,7 +2872,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);
@@ -3178,7 +2965,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) {
sd->subele[ELE_HOLY] += sc->data[SC_PROVIDENCE]->val2;
sd->subrace[RC_DEMON] += sc->data[SC_PROVIDENCE]->val2;
}
- if(sc->data[SC_ARMORPROPERTY]) { //This status change should grant card-type elemental resist.
+ if(sc->data[SC_ARMORPROPERTY]) {
+ //This status change should grant card-type elemental resist.
sd->subele[ELE_WATER] += sc->data[SC_ARMORPROPERTY]->val1;
sd->subele[ELE_EARTH] += sc->data[SC_ARMORPROPERTY]->val2;
sd->subele[ELE_FIRE] += sc->data[SC_ARMORPROPERTY]->val3;
@@ -3265,94 +3053,17 @@ int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt
return 0;
}
-int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
- struct status_data *hstatus = &hd->base_status;
- struct s_homunculus *hom = &hd->homunculus;
- int skill_lv;
- int amotion;
-
- hstatus->str = hom->str / 10;
- hstatus->agi = hom->agi / 10;
- hstatus->vit = hom->vit / 10;
- hstatus->dex = hom->dex / 10;
- hstatus->int_ = hom->int_ / 10;
- hstatus->luk = hom->luk / 10;
-
- if ( opt&SCO_FIRST ) { //[orn]
- const struct s_homunculus_db *db = hd->homunculusDB;
- hstatus->def_ele = db->element;
- hstatus->ele_lv = 1;
- hstatus->race = db->race;
- hstatus->size = (hom->class_ == db->evo_class)?db->evo_size:db->base_size;
- hstatus->rhw.range = 1 + hstatus->size;
- hstatus->mode = MD_CANMOVE|MD_CANATTACK;
- hstatus->speed = DEFAULT_WALK_SPEED;
- if (battle_config.hom_setting&0x8 && hd->master)
- hstatus->speed = status->get_speed(&hd->master->bl);
-
- hstatus->hp = 1;
- hstatus->sp = 1;
- }
- skill_lv = hom->level/10 + hstatus->vit/5;
- hstatus->def = cap_value(skill_lv, 0, 99);
-
- skill_lv = hom->level/10 + hstatus->int_/5;
- hstatus->mdef = cap_value(skill_lv, 0, 99);
-
- hstatus->max_hp = hom->max_hp;
- hstatus->max_sp = hom->max_sp;
-
- homun->calc_skilltree(hd, 0);
-
- if((skill_lv=homun->checkskill(hd,HAMI_SKIN)) > 0)
- hstatus->def += skill_lv * 4;
-
- if((skill_lv = homun->checkskill(hd,HVAN_INSTRUCT)) > 0) {
- hstatus->int_ += 1 +skill_lv/2 +skill_lv/4 +skill_lv/5;
- hstatus->str += 1 +skill_lv/3 +skill_lv/3 +skill_lv/4;
- }
-
- if((skill_lv=homun->checkskill(hd,HAMI_SKIN)) > 0)
- hstatus->max_hp += skill_lv * 2 * hstatus->max_hp / 100;
-
- if((skill_lv = homun->checkskill(hd,HLIF_BRAIN)) > 0)
- hstatus->max_sp += (1 +skill_lv/2 -skill_lv/4 +skill_lv/5) * hstatus->max_sp / 100;
-
- if ( opt&SCO_FIRST ) {
- hd->battle_status.hp = hom->hp;
- hd->battle_status.sp = hom->sp;
- }
-
- hstatus->rhw.atk = hstatus->dex;
- hstatus->rhw.atk2 = hstatus->str + hom->level;
-
- hstatus->aspd_rate = 1000;
-
- amotion = (1000 -4*hstatus->agi -hstatus->dex) * hd->homunculusDB->baseASPD/1000;
- hstatus->amotion = cap_value(amotion,battle_config.max_aspd,2000);
- hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus.
-
- status->calc_misc(&hd->bl, hstatus, hom->level);
-
-#ifdef RENEWAL
- hstatus->matk_max = hstatus->matk_min;
-#endif
-
- status_cpy(&hd->battle_status, hstatus);
- return 1;
-}
-
int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) {
struct status_data *estatus = &ed->base_status;
struct s_elemental *ele = &ed->elemental;
struct map_session_data *sd = ed->master;
- if( !sd )
+ if ( !sd )
return 0;
- if( opt&SCO_FIRST ) {
+ if ( opt&SCO_FIRST ) {
memcpy(estatus, &ed->db->status, sizeof(struct status_data));
- if( !ele->mode )
+ if ( !ele->mode )
estatus->mode = EL_MODE_PASSIVE;
else
estatus->mode = ele->mode;
@@ -3372,7 +3083,7 @@ int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt
estatus->flee = ele->flee;
estatus->hit = ele->hit;
- memcpy(&ed->battle_status,estatus,sizeof(struct status_data));
+ memcpy(&ed->battle_status, estatus, sizeof(struct status_data));
} else {
status->calc_misc(&ed->bl, estatus, 0);
status_cpy(&ed->battle_status, estatus);
@@ -3415,6 +3126,89 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) {
return 0;
}
+int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) {
+ struct status_data *hstatus = &hd->base_status;
+ struct s_homunculus *hom = &hd->homunculus;
+ int skill_lv;
+ int amotion;
+
+ hstatus->str = hom->str / 10;
+ hstatus->agi = hom->agi / 10;
+ hstatus->vit = hom->vit / 10;
+ hstatus->dex = hom->dex / 10;
+ hstatus->int_ = hom->int_ / 10;
+ hstatus->luk = hom->luk / 10;
+
+ APPLY_HOMUN_LEVEL_STATWEIGHT();
+
+ if ( opt&SCO_FIRST ) { //[orn]
+ const struct s_homunculus_db *db = hd->homunculusDB;
+ hstatus->def_ele = db->element;
+ hstatus->ele_lv = 1;
+ hstatus->race = db->race;
+ hstatus->size = (hom->class_ == db->evo_class) ? db->evo_size : db->base_size;
+ hstatus->rhw.range = 1 + hstatus->size;
+ hstatus->mode = MD_CANMOVE | MD_CANATTACK;
+ hstatus->speed = DEFAULT_WALK_SPEED;
+ if ( battle_config.hom_setting & 0x8 && hd->master )
+ hstatus->speed = status->get_speed(&hd->master->bl);
+
+ hstatus->hp = 1;
+ hstatus->sp = 1;
+ }
+
+ hstatus->aspd_rate = 1000;
+
+#ifdef RENEWAL
+ amotion = hd->homunculusDB->baseASPD;
+ amotion = amotion - amotion * (hstatus->dex + hom->dex_value) / 1000 - (hstatus->agi + hom->agi_value) * amotion / 250;
+#else
+ skill_lv = hom->level / 10 + hstatus->vit / 5;
+ hstatus->def = cap_value(skill_lv, 0, 99);
+
+ skill_lv = hom->level / 10 + hstatus->int_ / 5;
+ hstatus->mdef = cap_value(skill_lv, 0, 99);
+ amotion = (1000 - 4 * hstatus->agi - hstatus->dex) * hd->homunculusDB->baseASPD / 1000;
+#endif
+
+ hstatus->amotion = cap_value(amotion, battle_config.max_aspd, 2000);
+ hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus.
+
+
+ hstatus->max_hp = hom->max_hp;
+ hstatus->max_sp = hom->max_sp;
+
+ homun->calc_skilltree(hd, 0);
+
+ if ( (skill_lv = homun->checkskill(hd, HAMI_SKIN)) > 0 )
+ hstatus->def += skill_lv * 4;
+
+ if ( (skill_lv = homun->checkskill(hd, HVAN_INSTRUCT)) > 0 ) {
+ hstatus->int_ += 1 + skill_lv / 2 + skill_lv / 4 + skill_lv / 5;
+ hstatus->str += 1 + skill_lv / 3 + skill_lv / 3 + skill_lv / 4;
+ }
+
+ if ( (skill_lv = homun->checkskill(hd, HAMI_SKIN)) > 0 )
+ hstatus->max_hp += skill_lv * 2 * hstatus->max_hp / 100;
+
+ if ( (skill_lv = homun->checkskill(hd, HLIF_BRAIN)) > 0 )
+ hstatus->max_sp += (1 + skill_lv / 2 - skill_lv / 4 + skill_lv / 5) * hstatus->max_sp / 100;
+
+ if ( opt&SCO_FIRST ) {
+ hd->battle_status.hp = hom->hp;
+ hd->battle_status.sp = hom->sp;
+ }
+
+#ifndef RENEWAL
+ hstatus->rhw.atk = hstatus->dex;
+ hstatus->rhw.atk2 = hstatus->str + hom->level;
+#endif
+
+ status->calc_misc(&hd->bl, hstatus, hom->level);
+
+ status_cpy(&hd->battle_status, hstatus);
+ return 1;
+}
//Calculates base regen values.
void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) {
@@ -3554,8 +3348,8 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str
|| sc->data[SC_MAGICMUSHROOM]
|| sc->data[SC_RAISINGDRAGON]
|| sc->data[SC_SATURDAY_NIGHT_FEVER]
- ) //No regen
- regen->flag = 0;
+ )
+ regen->flag = 0; //No regen
if ( sc->data[SC_DANCING] || sc->data[SC_OBLIVIONCURSE] || sc->data[SC_MAXIMIZEPOWER] || sc->data[SC_REBOUND]
|| ( bl->type == BL_PC && (((TBL_PC*)bl)->class_&MAPID_UPPERMASK) == MAPID_MONK
@@ -3583,8 +3377,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)
@@ -3610,6 +3403,21 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
if (!bst || !st)
return;
+ /** [Playtester]
+ * This needs to be done even if there is currently no status change active, because
+ * we need to update the speed on the client when the last status change ends.
+ **/
+ if(flag&SCB_SPEED) {
+ struct unit_data *ud = unit->bl2ud(bl);
+ /** [Skotlex]
+ * Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
+ * because if you step on something while walking, the moment this
+ * piece of code triggers the walk-timer is set on INVALID_TIMER)
+ **/
+ if (ud)
+ ud->state.change_walk_target = ud->state.speed_changed = 1;
+ }
+
if((!(bl->type&BL_REGEN)) && (!sc || !sc->count)) { //No difference.
status_cpy(st, bst);
return;
@@ -3698,13 +3506,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
st->lhw.atk2 = status->calc_watk(bl, sc, bst->lhw.atk2, true);
}
}
-
- if( bl->type&BL_HOM ) {
- st->rhw.atk += (st->dex - bst->dex);
- st->rhw.atk2 += (st->str - bst->str);
- if( st->rhw.atk2 < st->rhw.atk )
- st->rhw.atk2 = st->rhw.atk;
- }
}
if(flag&SCB_HIT) {
@@ -3786,16 +3587,9 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
if(flag&SCB_SPEED) {
- struct unit_data *ud = unit->bl2ud(bl);
st->speed = status->calc_speed(bl, sc, bst->speed);
- //Re-walk to adjust speed (we do not check if walktimer != INVALID_TIMER
- //because if you step on something while walking, the moment this
- //piece of code triggers the walk-timer is set on INVALID_TIMER) [Skotlex]
- if (ud)
- ud->state.change_walk_target = ud->state.speed_changed = 1;
-
if( bl->type&BL_PC && !(sd && sd->state.permanent_speed) && st->speed < battle_config.max_walk_speed )
st->speed = battle_config.max_walk_speed;
@@ -3845,9 +3639,9 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
}
// No status changes alter these yet.
- // if(flag&SCB_SIZE)
- // if(flag&SCB_RACE)
- // if(flag&SCB_RANGE)
+ //if(flag&SCB_SIZE)
+ //if(flag&SCB_RACE)
+ //if(flag&SCB_RANGE)
if(flag&SCB_MAXHP) {
if( bl->type&BL_PC ) {
@@ -3891,76 +3685,82 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) {
if(flag&SCB_MATK) {
status->update_matk(bl);
}
+
+ if ( flag&SCB_DSPD ) {
+ int dmotion;
+ if ( bl->type&BL_PC ) {
+ if (bst->agi == st->agi)
+ st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
+ else {
+ dmotion = 800-st->agi*4;
+ st->dmotion = cap_value(dmotion, 400, 800);
+ if ( battle_config.pc_damage_delay_rate != 100 )
+ st->dmotion = st->dmotion*battle_config.pc_damage_delay_rate / 100;
+ //It's safe to ignore bst->dmotion since no bonus affects it.
+ st->dmotion = status->calc_dmotion(bl, sc, st->dmotion);
+ }
+ } else if ( bl->type&BL_HOM ) {
+ dmotion = 800 - st->agi * 4;
+ st->dmotion = cap_value(dmotion, 400, 800);
+ st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
+ } else { // mercenary and mobs
+ st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
+ }
+ }
if(flag&SCB_ASPD) {
int amotion;
- if( bl->type&BL_PC ) {
- amotion = status->base_amotion_pc(sd,st);
-#ifndef RENEWAL_ASPD
- st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
-
- if(st->aspd_rate != 1000)
- amotion = amotion*st->aspd_rate/1000;
+ if ( bl->type&BL_HOM ) {
+#ifdef RENEWAL
+ amotion = ((TBL_HOM*)bl)->homunculusDB->baseASPD;
+ amotion = amotion - amotion * status_get_homdex(bl) / 1000 - status_get_homagi(bl) * amotion / 250;
+ amotion = (amotion * status->calc_aspd(bl, sc, 1) + status->calc_aspd(bl, sc, 2)) / -100 + amotion;
#else
- // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200))
- amotion -= (int)(sqrt( (pow(st->agi, 2) / 2) + (pow(st->dex, 2) / 5) ) / 4 + ((float)status->calc_aspd(bl, sc, 1) * st->agi / 200)) * 10;
+ amotion = (1000 - 4 * st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD / 1000;
- if( (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) != 0 ) // RE ASPD percertage modifier
- amotion -= (( amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd) )
- * (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) / 10 + 5) / 10;
+ amotion = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
- if(st->aspd_rate != 1000) // absolute percentage modifier
- amotion = ( 200 - (200-amotion/10) * st->aspd_rate / 1000 ) * 10;
+ if ( st->aspd_rate != 1000 )
+ amotion = amotion*st->aspd_rate / 1000;
#endif
amotion = status->calc_fix_aspd(bl, sc, amotion);
- st->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000);
+ st->amotion = cap_value(amotion, battle_config.max_aspd, 2000);
- st->adelay = 2*st->amotion;
- } else if( bl->type&BL_HOM ) {
- amotion = (1000 - 4*st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000;
+ st->adelay = st->amotion;
+ } else if ( bl->type&BL_PC ) {
+ amotion = status->base_amotion_pc(sd, st);
+#ifndef RENEWAL_ASPD
st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
if(st->aspd_rate != 1000)
amotion = amotion*st->aspd_rate/1000;
+#else
+ // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200))
+ amotion -= (int)(sqrt((pow(st->agi, 2) / 2) + (pow(st->dex, 2) / 5)) / 4 + ((float)status->calc_aspd(bl, sc, 1) * st->agi / 200)) * 10;
+
+ if ( (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) != 0 ) // RE ASPD percertage modifier
+ amotion -= ((amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd))
+ * (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) / 10 + 5) / 10;
+ if ( st->aspd_rate != 1000 ) // absolute percentage modifier
+ amotion = (200 - (200 - amotion / 10) * st->aspd_rate / 1000) * 10;
+#endif
amotion = status->calc_fix_aspd(bl, sc, amotion);
- st->amotion = cap_value(amotion,battle_config.max_aspd,2000);
+ st->amotion = cap_value(amotion, ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd), 2000);
- st->adelay = st->amotion;
+ st->adelay = 2 * st->amotion;
} else { // mercenary and mobs
amotion = bst->amotion;
st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate);
- if(st->aspd_rate != 1000)
- amotion = amotion*st->aspd_rate/1000;
+ if ( st->aspd_rate != 1000 )
+ amotion = amotion*st->aspd_rate / 1000;
amotion = status->calc_fix_aspd(bl, sc, amotion);
st->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000);
- temp = bst->adelay*st->aspd_rate/1000;
- st->adelay = cap_value(temp, battle_config.monster_max_aspd*2, 4000);
- }
- }
-
- if(flag&SCB_DSPD) {
- int dmotion;
- if( bl->type&BL_PC ) {
- if (bst->agi == st->agi)
- st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
- else {
- dmotion = 800-st->agi*4;
- st->dmotion = cap_value(dmotion, 400, 800);
- if(battle_config.pc_damage_delay_rate != 100)
- st->dmotion = st->dmotion*battle_config.pc_damage_delay_rate/100;
- //It's safe to ignore bst->dmotion since no bonus affects it.
- st->dmotion = status->calc_dmotion(bl, sc, st->dmotion);
- }
- } else if( bl->type&BL_HOM ) {
- dmotion = 800-st->agi*4;
- st->dmotion = cap_value(dmotion, 400, 800);
- st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
- } else { // mercenary and mobs
- st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion);
+ temp = bst->adelay*st->aspd_rate / 1000;
+ st->adelay = cap_value(temp, battle_config.monster_max_aspd * 2, 4000);
}
}
@@ -3986,7 +3786,7 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca
return;
}
}
-
+
// remember previous values
st = status->get_status_data(bl);
memcpy(&bst, st, sizeof(struct status_data));
@@ -4006,8 +3806,12 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca
if( bl->type == BL_PET )
return; // pets are not affected by statuses
- if( opt&SCO_FIRST && bl->type == BL_MOB )
+ if( opt&SCO_FIRST && bl->type == BL_MOB ) {
+#ifdef RENEWAL
+ status->update_matk(bl); // Otherwise, the mob will spawn with lower MATK values
+#endif
return; // assume there will be no statuses active
+ }
status->calc_bl_main(bl, flag);
@@ -4148,6 +3952,245 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca
clif->mercenary_updatestatus(ed->master, SP_SP);
}
}
+//Checks whether the source can see and chase target.
+int status_check_visibility(struct block_list *src, struct block_list *target) {
+ int view_range;
+ struct status_change *tsc = NULL;
+
+ switch ( src->type ) {
+ case BL_MOB:
+ view_range = ((TBL_MOB*)src)->min_chase;
+ break;
+ case BL_PET:
+ view_range = ((TBL_PET*)src)->db->range2;
+ break;
+ default:
+ view_range = AREA_SIZE;
+ }
+
+ if ( src->m != target->m || !check_distance_bl(src, target, view_range) )
+ return 0;
+
+ if ( src->type == BL_NPC ) /* NPCs don't care for the rest */
+ return 1;
+
+ if ( (tsc = status->get_sc(target)) ) {
+ struct status_data *st = status->get_status_data(src);
+
+ switch ( target->type ) { //Check for chase-walk/hiding/cloaking opponents.
+ case BL_PC:
+ if ( tsc->data[SC_CLOAKINGEXCEED] && !(st->mode&MD_BOSS) )
+ return 0;
+ if ( (tsc->option&(OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || tsc->data[SC_STEALTHFIELD] || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&MD_BOSS) &&
+ (((TBL_PC*)target)->special_state.perfect_hiding || !(st->mode&MD_DETECTOR)) )
+ return 0;
+ break;
+ default:
+ if ( (tsc->option&(OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&(MD_BOSS | MD_DETECTOR)) )
+ return 0;
+
+ }
+ }
+
+ return 1;
+}
+
+// Basic ASPD value
+int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) {
+ int amotion;
+#ifdef RENEWAL_ASPD
+ short mod = -1;
+
+ switch ( sd->weapontype2 ) { // adjustment for dual wielding
+ case W_DAGGER:
+ mod = 0;
+ break; // 0, 1, 1
+ case W_1HSWORD:
+ case W_1HAXE:
+ mod = 1;
+ if ( (sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS ) // 0, 2, 3
+ mod = sd->weapontype2 / W_1HSWORD + W_1HSWORD / sd->weapontype2;
+ }
+
+ amotion = (sd->status.weapon < MAX_WEAPON_TYPE && mod < 0)
+ ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
+ : ((status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] // dual-wield
+ + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod
+ - status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]
+ + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]);
+
+ if ( sd->status.shield )
+ amotion += (2000 - status->aspd_base[pc->class2idx(sd->status.class_)][W_FIST]) +
+ (status->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000);
+
+#else
+ // base weapon delay
+ amotion = (sd->status.weapon < MAX_WEAPON_TYPE)
+ ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon
+ : (status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield
+
+ // percentual delay reduction from stats
+ amotion -= amotion * (4 * st->agi + st->dex) / 1000;
+#endif
+ // raw delay adjustment from bAspd bonus
+ amotion += sd->bonus.aspd_add;
+
+ /* angra manyu disregards aspd_base and similar */
+ if ( sd->equip_index[EQI_HAND_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid == ITEMID_ANGRA_MANYU )
+ return 0;
+
+ return amotion;
+}
+
+unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) {
+ int flag = 0, str, dex, dstr;
+
+ if ( !(bl->type&battle_config.enable_baseatk) )
+ return 0;
+
+ if ( bl->type == BL_PC )
+ switch ( ((TBL_PC*)bl)->status.weapon ) {
+ case W_BOW:
+ case W_MUSICAL:
+ case W_WHIP:
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ case W_GRENADE:
+ flag = 1;
+ }
+ if ( flag ) {
+#ifdef RENEWAL
+ dstr =
+#endif
+ str = st->dex;
+ dex = st->str;
+ } else {
+#ifdef RENEWAL
+ dstr =
+#endif
+ str = st->str;
+ dex = st->dex;
+ }
+ //Normally only players have base-atk, but homunc have a different batk
+ // equation, hinting that perhaps non-players should use this for batk.
+ // [Skotlex]
+#ifdef RENEWAL
+ if ( bl->type == BL_HOM )
+ str = 2 * (((TBL_HOM*)bl)->homunculus.level + status_get_homstr(bl));
+#else
+ dstr = str / 10;
+ str += dstr*dstr;
+#endif
+ if ( bl->type == BL_PC )
+#ifdef RENEWAL
+ str = (int)(dstr + (float)dex / 5 + (float)st->luk / 3 + (float)((TBL_PC*)bl)->status.base_level / 4);
+ else if ( bl->type == BL_MOB )
+ str = dstr + ((TBL_MOB*)bl)->level;
+#else
+ str += dex / 5 + st->luk / 5;
+#endif
+ return cap_value(str, 0, USHRT_MAX);
+}
+
+#ifndef RENEWAL
+static inline unsigned short status_base_matk_min(const struct status_data *st) { return st->int_ + (st->int_ / 7)*(st->int_ / 7); }
+#endif // not RENEWAL
+static inline unsigned short status_base_matk_max(const struct status_data *st) { return st->int_ + (st->int_ / 5)*(st->int_ / 5); }
+
+unsigned short status_base_matk(struct block_list *bl, const struct status_data *st, int level) {
+#ifdef RENEWAL
+ switch ( bl->type ) {
+ case BL_MOB:
+ return st->int_ + level;
+ case BL_HOM:
+ return status_get_homint(bl) + level;
+ case BL_PC:
+ default: // temporary until all are formulated
+ return st->int_ + (st->int_ / 2) + (st->dex / 5) + (st->luk / 3) + (level / 4);
+ }
+#else
+ return 0;
+#endif
+}
+
+//Fills in the misc data that can be calculated from the other status info (except for level)
+void status_calc_misc(struct block_list *bl, struct status_data *st, int level) {
+ //Non players get the value set, players need to stack with previous bonuses.
+ if ( bl->type != BL_PC )
+ st->batk =
+ st->hit = st->flee =
+ st->def2 = st->mdef2 =
+ st->cri = st->flee2 = 0;
+
+#ifdef RENEWAL // renewal formulas
+ if ( bl->type == BL_HOM ) {
+ st->def2 = status_get_homvit(bl) + status_get_homagi(bl) / 2;
+ st->mdef2 = (status_get_homvit(bl) + status_get_homint(bl)) / 2;
+ st->def += status_get_homvit(bl) + level / 2;
+ st->mdef = (int)(((float)status_get_homvit(bl) + level) / 4 + (float)status_get_homint(bl) / 2);
+ st->hit = level + st->dex + 150;
+ st->flee = level + status_get_homagi(bl);
+ st->rhw.atk = (status_get_homstr(bl) + status_get_homdex(bl)) / 5;
+ st->rhw.atk2 = (status_get_homluk(bl) + status_get_homstr(bl) + status_get_homdex(bl)) / 3;
+ } else {
+ st->hit += level + st->dex + (bl->type == BL_PC ? st->luk / 3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175
+ st->flee += level + st->agi + (bl->type == BL_PC ? st->luk / 5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100
+ st->def2 += (int)(((float)level + st->vit) / 2 + (bl->type == BL_PC ? ((float)st->agi / 5) : 0)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def)
+ st->mdef2 += (int)(bl->type == BL_PC ? (st->int_ + ((float)level / 4) + ((float)(st->dex + st->vit) / 5)) : ((float)(st->int_ + level) / 4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef)
+ }
+#else // not RENEWAL
+ st->matk_min = status_base_matk_min(st);
+ st->matk_max = status_base_matk_max(st);
+ st->hit += level + st->dex;
+ st->flee += level + st->agi;
+ st->def2 += st->vit;
+ st->mdef2 += st->int_ + (st->vit >> 1);
+#endif // RENEWAL
+
+ if ( bl->type&battle_config.enable_critical )
+ st->cri += 10 + (st->luk * 10 / 3); //(every 1 luk = +0.3 critical)
+ else
+ st->cri = 0;
+
+ if ( bl->type&battle_config.enable_perfect_flee )
+ st->flee2 += st->luk + 10; //(every 10 luk = +1 perfect flee)
+ else
+ st->flee2 = 0;
+
+ if ( st->batk ) {
+ int temp = st->batk + status->base_atk(bl, st);
+ st->batk = cap_value(temp, 0, USHRT_MAX);
+ } else
+ st->batk = status->base_atk(bl, st);
+ if ( st->cri )
+ switch ( bl->type ) {
+ case BL_MOB:
+ if ( battle_config.mob_critical_rate != 100 )
+ st->cri = st->cri*battle_config.mob_critical_rate / 100;
+ if ( !st->cri && battle_config.mob_critical_rate )
+ st->cri = 10;
+ break;
+ case BL_PC:
+ //Players don't have a critical adjustment setting as of yet.
+ break;
+ case BL_MER:
+#ifdef RENEWAL
+ st->matk_min = st->matk_max = status_base_matk_max(st);
+ st->def2 = st->vit + level / 10 + st->vit / 5;
+ st->mdef2 = level / 10 + st->int_ / 5;
+#endif
+ break;
+ default:
+ if ( battle_config.critical_rate != 100 )
+ st->cri = st->cri*battle_config.critical_rate / 100;
+ if ( !st->cri && battle_config.critical_rate )
+ st->cri = 10;
+ }
+ if ( bl->type&BL_REGEN )
+ status->calc_regen(bl, st, status->get_regen_data(bl));
+}
/*==========================================
* Apply shared stat mods from status changes [DracoRPG]
@@ -4157,14 +4200,14 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(str,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ str += str * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
str -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
if(sc->data[SC_BEYOND_OF_WARCRY])
str += sc->data[SC_BEYOND_OF_WARCRY]->val3;
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && str < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
str += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_CHASEWALK2])
@@ -4195,6 +4238,8 @@ unsigned short status_calc_str(struct block_list *bl, struct status_change *sc,
str -= ((sc->data[SC_MARIONETTE_MASTER]->val3)>>16)&0xFF;
if(sc->data[SC_MARIONETTE])
str += ((sc->data[SC_MARIONETTE]->val3)>>16)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ str += ((sc->data[SC_SOULLINK]->val3)>>16)&0xFF;
if(sc->data[SC_GIANTGROWTH])
str += 30;
if(sc->data[SC_SAVAGE_STEAK])
@@ -4204,9 +4249,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;
- if(sc->data[SC_FULL_THROTTLE])
- str += str * 20 / 100;
+ str -= sc->data[SC_KYOUGAKU]->val3;
return (unsigned short)cap_value(str,0,USHRT_MAX);
}
@@ -4216,12 +4259,12 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(agi,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ agi += agi * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
agi -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && agi < 50)
- return 50;
if(sc->data[SC_CONCENTRATION] && !sc->data[SC_QUAGMIRE])
agi += (agi-sc->data[SC_CONCENTRATION]->val3)*sc->data[SC_CONCENTRATION]->val2/100;
if(sc->data[SC_INCALLSTATUS])
@@ -4239,7 +4282,7 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
if(sc->data[SC_INC_AGI])
agi += sc->data[SC_INC_AGI]->val2;
if(sc->data[SC_GS_ACCURACY])
- agi += 4; // added based on skill updates [Reddozen]
+ agi += 4; // added based on skill updates [Reddozen]
if(sc->data[SC_DEC_AGI])
agi -= sc->data[SC_DEC_AGI]->val2;
if(sc->data[SC_QUAGMIRE])
@@ -4250,6 +4293,8 @@ unsigned short status_calc_agi(struct block_list *bl, struct status_change *sc,
agi -= ((sc->data[SC_MARIONETTE_MASTER]->val3)>>8)&0xFF;
if(sc->data[SC_MARIONETTE])
agi += ((sc->data[SC_MARIONETTE]->val3)>>8)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ agi += ((sc->data[SC_SOULLINK]->val3)>>8)&0xFF;
if(sc->data[SC_ADORAMUS])
agi -= sc->data[SC_ADORAMUS]->val2;
if(sc->data[SC_DROCERA_HERB_STEAMED])
@@ -4259,12 +4304,10 @@ 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;
- if(sc->data[SC_FULL_THROTTLE])
- agi += agi * 20 / 100;
return (unsigned short)cap_value(agi,0,USHRT_MAX);
}
@@ -4274,12 +4317,12 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(vit,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ vit += vit * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
vit -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(vit,0,USHRT_MAX);
}
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && vit < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
vit += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_INCVIT])
@@ -4298,6 +4341,8 @@ unsigned short status_calc_vit(struct block_list *bl, struct status_change *sc,
vit -= sc->data[SC_MARIONETTE_MASTER]->val3&0xFF;
if(sc->data[SC_MARIONETTE])
vit += sc->data[SC_MARIONETTE]->val3&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ vit += sc->data[SC_SOULLINK]->val3&0xFF;
if(sc->data[SC_LAUDAAGNUS])
vit += 4 + sc->data[SC_LAUDAAGNUS]->val1;
if(sc->data[SC_MINOR_BBQ])
@@ -4307,12 +4352,10 @@ 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;
- if(sc->data[SC_FULL_THROTTLE])
- vit += vit * 20 / 100;
return (unsigned short)cap_value(vit,0,USHRT_MAX);
}
@@ -4322,14 +4365,14 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(int_,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ int_ += int_ * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
int_ -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
if(sc->data[SC_MELODYOFSINK])
int_ -= sc->data[SC_MELODYOFSINK]->val3;
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && int_ < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
int_ += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_INCINT])
@@ -4356,6 +4399,8 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
int_ -= ((sc->data[SC_MARIONETTE_MASTER]->val4)>>16)&0xFF;
if(sc->data[SC_MARIONETTE])
int_ += ((sc->data[SC_MARIONETTE]->val4)>>16)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ int_ += ((sc->data[SC_SOULLINK]->val4)>>16)&0xFF;
if(sc->data[SC_MANDRAGORA])
int_ -= 4 * sc->data[SC_MANDRAGORA]->val1;
if(sc->data[SC_COCKTAIL_WARG_BLOOD])
@@ -4365,7 +4410,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])
@@ -4373,8 +4418,6 @@ unsigned short status_calc_int(struct block_list *bl, struct status_change *sc,
if(sc->data[SC__STRIPACCESSARY])
int_ -= int_ * sc->data[SC__STRIPACCESSARY]->val2 / 100;
}
- if(sc->data[SC_FULL_THROTTLE])
- int_ += int_ * 20 / 100;
return (unsigned short)cap_value(int_,0,USHRT_MAX);
}
@@ -4384,12 +4427,12 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(dex,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ dex += dex * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
dex -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(dex,0,USHRT_MAX);
}
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && dex < 50)
- return 50;
if(sc->data[SC_CONCENTRATION] && !sc->data[SC_QUAGMIRE])
dex += (dex-sc->data[SC_CONCENTRATION]->val4)*sc->data[SC_CONCENTRATION]->val2/100;
if(sc->data[SC_INCALLSTATUS])
@@ -4415,11 +4458,13 @@ unsigned short status_calc_dex(struct block_list *bl, struct status_change *sc,
dex >>= 1;
}
if(sc->data[SC_GS_ACCURACY])
- dex += 4; // added based on skill updates [Reddozen]
+ dex += 4; // added based on skill updates [Reddozen]
if(sc->data[SC_MARIONETTE_MASTER])
dex -= ((sc->data[SC_MARIONETTE_MASTER]->val4)>>8)&0xFF;
if(sc->data[SC_MARIONETTE])
dex += ((sc->data[SC_MARIONETTE]->val4)>>8)&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ dex += ((sc->data[SC_SOULLINK]->val4)>>8)&0xFF;
if(sc->data[SC_SIROMA_ICE_TEA])
dex += sc->data[SC_SIROMA_ICE_TEA]->val1;
if(sc->data[SC_INSPIRATION])
@@ -4427,14 +4472,12 @@ 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;
if(sc->data[SC__STRIPACCESSARY] && bl->type != BL_PC)
dex -= dex * sc->data[SC__STRIPACCESSARY]->val2 / 100;
- if(sc->data[SC_FULL_THROTTLE])
- dex += dex * 20 / 100;
return (unsigned short)cap_value(dex,0,USHRT_MAX);
}
@@ -4444,14 +4487,14 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
if(!sc || !sc->count)
return cap_value(luk,0,USHRT_MAX);
+ if(sc->data[SC_FULL_THROTTLE])
+ luk += luk * 20 / 100;
if(sc->data[SC_HARMONIZE]) {
luk -= sc->data[SC_HARMONIZE]->val2;
return (unsigned short)cap_value(luk,0,USHRT_MAX);
}
if(sc->data[SC_CURSE])
return 0;
- if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH && luk < 50)
- return 50;
if(sc->data[SC_INCALLSTATUS])
luk += sc->data[SC_INCALLSTATUS]->val1;
if(sc->data[SC_INCLUK])
@@ -4468,6 +4511,8 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
luk -= sc->data[SC_MARIONETTE_MASTER]->val4&0xFF;
if(sc->data[SC_MARIONETTE])
luk += sc->data[SC_MARIONETTE]->val4&0xFF;
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ luk += sc->data[SC_SOULLINK]->val4&0xFF;
if(sc->data[SC_PUTTI_TAILS_NOODLES])
luk += sc->data[SC_PUTTI_TAILS_NOODLES]->val1;
if(sc->data[SC_INSPIRATION])
@@ -4475,7 +4520,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;
@@ -4483,8 +4528,6 @@ unsigned short status_calc_luk(struct block_list *bl, struct status_change *sc,
luk -= luk * sc->data[SC__STRIPACCESSARY]->val2 / 100;
if(sc->data[SC_BANANA_BOMB])
luk -= luk * sc->data[SC_BANANA_BOMB]->val1 / 100;
- if(sc->data[SC_FULL_THROTTLE])
- luk += luk * 20 / 100;
return (unsigned short)cap_value(luk,0,USHRT_MAX);
}
@@ -4547,9 +4590,10 @@ unsigned short status_calc_batk(struct block_list *bl, struct status_change *sc,
batk -= batk * 25/100;
if( sc->data[SC_ZANGETSU] )
batk += sc->data[SC_ZANGETSU]->val2;
- //Curse shouldn't effect on this? <- Curse OR Bleeding??
- // if(sc->data[SC_BLOODING])
- // batk -= batk * 25/100;
+#if 0 //Curse shouldn't effect on this? <- Curse OR Bleeding??
+ if(sc->data[SC_BLOODING])
+ batk -= batk * 25/100;
+#endif // 0
if(sc->data[SC_HLIF_FLEET])
batk += batk * sc->data[SC_HLIF_FLEET]->val3/100;
if(sc->data[SC__ENERVATION])
@@ -4591,7 +4635,7 @@ unsigned short status_calc_watk(struct block_list *bl, struct status_change *sc,
watk += sc->data[SC_SHIELDSPELL_DEF]->val2;
if(sc->data[SC_INSPIRATION])
watk += sc->data[SC_INSPIRATION]->val2;
- if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 )
+ if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
watk += (10 + 10 * sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
if( sc->data[SC_TROPIC_OPTION] )
watk += sc->data[SC_TROPIC_OPTION]->val2;
@@ -4776,6 +4820,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])
@@ -4797,6 +4843,8 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in
hit += hit * sc->data[SC_INCHITRATE]->val1/100;
if(sc->data[SC_BLIND])
hit -= hit * 25/100;
+ if(sc->data[SC_FIRE_EXPANSION_TEAR_GAS])
+ hit -= hit * 50 / 100;
if(sc->data[SC__GROOMY])
hit -= hit * sc->data[SC__GROOMY]->val3 / 100;
if(sc->data[SC_FEAR])
@@ -4805,7 +4853,7 @@ signed short status_calc_hit(struct block_list *bl, struct status_change *sc, in
hit /= 2;
if(sc->data[SC_ILLUSIONDOPING])
hit -= hit * (5 + sc->data[SC_ILLUSIONDOPING]->val1) / 100; //custom
-
+
return (short)cap_value(hit,1,SHRT_MAX);
}
@@ -4827,6 +4875,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])
@@ -4880,6 +4930,10 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
flee -= flee * ( 20 + 5 * sc->data[SC_GLOOMYDAY]->val1 ) / 100;
if( sc->data[SC_SATURDAY_NIGHT_FEVER] )
flee -= flee * (40 + 10 * sc->data[SC_SATURDAY_NIGHT_FEVER]->val1) / 100;
+ if ( sc->data[SC_FIRE_EXPANSION_SMOKE_POWDER] )
+ flee += flee * 20 / 100;
+ if ( sc->data[SC_FIRE_EXPANSION_TEAR_GAS] )
+ flee -= flee * 50 / 100;
if( sc->data[SC_WIND_STEP_OPTION] )
flee += flee * sc->data[SC_WIND_STEP_OPTION]->val2 / 100;
if( sc->data[SC_ZEPHYR] )
@@ -4888,7 +4942,7 @@ signed short status_calc_flee(struct block_list *bl, struct status_change *sc, i
if(status_get_element(bl) == ELE_WATER) //water type
flee /= 2;
}
-
+
if( sc->data[SC_OVERED_BOOST] ) // should be final and unmodifiable by any means
flee = sc->data[SC_OVERED_BOOST]->val2;
@@ -4927,8 +4981,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])
@@ -4948,7 +5000,7 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
if(sc->data[SC_STEELBODY])
return 90;
#endif
-
+
if(sc->data[SC_STONEHARDSKIN])
def += sc->data[SC_STONEHARDSKIN]->val1;
if(sc->data[SC_DRUMBATTLE])
@@ -4956,7 +5008,7 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def
if(sc->data[SC_STONESKIN])
def += sc->data[SC_STONESKIN]->val2;
- if(sc->data[SC_HAMI_DEFENCE]) //[orn]
+ if(sc->data[SC_HAMI_DEFENCE]) //[orn]
def += sc->data[SC_HAMI_DEFENCE]->val2;
if(sc->data[SC_EARTH_INSIGNIA] && sc->data[SC_EARTH_INSIGNIA]->val1 == 2)
@@ -5032,6 +5084,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
@@ -5047,7 +5101,7 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i
return 0;
if(sc->data[SC_SUN_COMFORT])
def2 += sc->data[SC_SUN_COMFORT]->val2;
- if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 0 )
+ if( sc->data[SC_BANDING] && sc->data[SC_BANDING]->val2 > 1 )
def2 += (5 + sc->data[SC_BANDING]->val1) * (sc->data[SC_BANDING]->val2);
if(sc->data[SC_ANGELUS])
#ifdef RENEWAL //in renewal only the VIT stat bonus is boosted by angelus
@@ -5204,16 +5258,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;
}
}
@@ -5272,7 +5326,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if( sc->data[SC__GROOMY] )
val = max( val, sc->data[SC__GROOMY]->val2);
if( sc->data[SC_GLOOMYDAY] )
- val = max( val, sc->data[SC_GLOOMYDAY]->val3 ); // Should be 50 (-50% speed)
+ val = max( val, sc->data[SC_GLOOMYDAY]->val3 ); // Should be 50 (-50% speed)
if( sc->data[SC_STEALTHFIELD_MASTER] )
val = max( val, 30 );
if( sc->data[SC_BANDING_DEFENCE] )
@@ -5329,7 +5383,7 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
if( sc->data[SC_WIND_STEP_OPTION] )
val = max( val, sc->data[SC_WIND_STEP_OPTION]->val2 );
if( sc->data[SC_FULL_THROTTLE] )
- val = max( val, 30);
+ val = max( val, 25);
//FIXME: official items use a single bonus for this [ultramage]
if( sc->data[SC_MOVHASTE_HORSE] ) // temporary item-based speedup
val = max( val, 25 );
@@ -5369,119 +5423,123 @@ unsigned short status_calc_speed(struct block_list *bl, struct status_change *sc
// flag&2 - percentage value
short status_calc_aspd(struct block_list *bl, struct status_change *sc, short flag) {
#ifdef RENEWAL_ASPD
- int i, pots = 0, skills1 = 0, skills2 = 0;
+ int i, pots = 0, bonus = 0;
- if(!sc || !sc->count)
+ if (!sc || !sc->count)
return 0;
- if(sc->data[i=SC_ATTHASTE_INFINITY] ||
- sc->data[i=SC_ATTHASTE_POTION3] ||
- sc->data[i=SC_ATTHASTE_POTION2] ||
- sc->data[i=SC_ATTHASTE_POTION1])
- pots += sc->data[i]->val1;
-
- if( !sc->data[SC_QUAGMIRE] ){
- if(sc->data[SC_TWOHANDQUICKEN] && skills1 < 7)
- skills1 = 7;
-
- if(sc->data[SC_ONEHANDQUICKEN] && skills1 < 7) skills1 = 7;
-
- if(sc->data[SC_MER_QUICKEN] && skills1 < 7) // needs more info
- skills1 = 7;
-
- if(sc->data[SC_ADRENALINE2] && skills1 < 6)
- skills1 = 6;
-
- if(sc->data[SC_ADRENALINE] && skills1 < 7)
- skills1 = 7;
-
- if(sc->data[SC_SPEARQUICKEN] && skills1 < 7)
- skills1 = 7;
+ if (flag&1) {
+ // ASPD fixed values
+ if (sc->data[i=SC_ATTHASTE_INFINITY]
+ || sc->data[i=SC_ATTHASTE_POTION3]
+ || sc->data[i=SC_ATTHASTE_POTION2]
+ || sc->data[i=SC_ATTHASTE_POTION1]
+ )
+ pots += sc->data[i]->val1;
+
+ if (!sc->data[SC_QUAGMIRE]) {
+ if(sc->data[SC_TWOHANDQUICKEN] && bonus < 7)
+ bonus = 7;
+ if(sc->data[SC_ONEHANDQUICKEN] && bonus < 7)
+ bonus = 7;
+ if(sc->data[SC_MER_QUICKEN] && bonus < 7) // needs more info
+ bonus = 7;
+ if(sc->data[SC_ADRENALINE2] && bonus < 6)
+ bonus = 6;
+ if(sc->data[SC_ADRENALINE] && bonus < 7)
+ bonus = 7;
+ if(sc->data[SC_SPEARQUICKEN] && bonus < 7)
+ bonus = 7;
+ if(sc->data[SC_HLIF_FLEET] && bonus < 5)
+ bonus = 5;
+ }
- if(sc->data[SC_HLIF_FLEET] && skills1 < 5)
- skills1 = 5;
- }
+ if (sc->data[SC_ASSNCROS] && bonus < sc->data[SC_ASSNCROS]->val2) {
+ if (bl->type!=BL_PC)
+ bonus = sc->data[SC_ASSNCROS]->val2;
+ else {
+ switch (((TBL_PC*)bl)->status.weapon)
+ {
+ case W_BOW:
+ case W_REVOLVER:
+ case W_RIFLE:
+ case W_GATLING:
+ case W_SHOTGUN:
+ case W_GRENADE:
+ break;
+ default:
+ bonus = sc->data[SC_ASSNCROS]->val2;
+ }
+ }
+ }
- if((sc->data[SC_BERSERK]) && skills1 < 15)
- skills1 = 15;
- else if(sc->data[SC_GS_MADNESSCANCEL] && skills1 < 20)
- skills1 = 20;
+ if ((sc->data[SC_BERSERK]) && bonus < 15)
+ bonus = 15;
+ else if (sc->data[SC_GS_MADNESSCANCEL] && bonus < 20)
+ bonus = 20;
- if(sc->data[SC_DONTFORGETME])
- skills2 -= sc->data[SC_DONTFORGETME]->val2;
- if(sc->data[SC_LONGING])
- skills2 -= sc->data[SC_LONGING]->val2;
- if(sc->data[SC_STEELBODY])
- skills2 -= 25;
- if(sc->data[SC_SKA])
- skills2 -= 25;
- if(sc->data[SC_DEFENDER])
- skills2 -= sc->data[SC_DEFENDER]->val4 / 10;
- if(sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) // needs more info
- skills2 -= 25;
- if(sc->data[SC_GRAVITATION])
- skills2 -= sc->data[SC_GRAVITATION]->val2; // needs more info
- if(sc->data[SC_JOINTBEAT]) { // needs more info
- if( sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST )
- skills2 -= 25;
- if( sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE )
- skills2 -= 10;
- }
- if( sc->data[SC_FROSTMISTY] )
- skills2 -= 15;
- if( sc->data[SC_HALLUCINATIONWALK_POSTDELAY] )
- skills2 -= 50;
- if( sc->data[SC_PARALYSE] )
- skills2 -= 10;
- if( sc->data[SC__BODYPAINT] )
- skills2 -= sc->data[SC__BODYPAINT]->val1;
- if( sc->data[SC__INVISIBILITY] )
- skills2 -= sc->data[SC__INVISIBILITY]->val2 ;
- if( sc->data[SC__GROOMY] )
- skills2 -= sc->data[SC__GROOMY]->val2;
- if( sc->data[SC_GLOOMYDAY] )
- skills2 -= ( 15 + 5 * sc->data[SC_GLOOMYDAY]->val1 );
- if( sc->data[SC_EARTHDRIVE] )
- skills2 -= 25;
- if( sc->data[SC_MELON_BOMB] )
- skills2 -= sc->data[SC_MELON_BOMB]->val1;
- if( sc->data[SC_PAIN_KILLER] )
- skills2 -= sc->data[SC_PAIN_KILLER]->val2;
-
- if( sc->data[SC_SWING] )
- skills2 += sc->data[SC_SWING]->val3;
- if( sc->data[SC_DANCE_WITH_WUG] )
- skills2 += sc->data[SC_DANCE_WITH_WUG]->val3;
- if( sc->data[SC_GENTLETOUCH_CHANGE] )
- skills2 += sc->data[SC_GENTLETOUCH_CHANGE]->val3;
- if( sc->data[SC_BOOST500] )
- skills2 += sc->data[SC_BOOST500]->val1;
- if( sc->data[SC_EXTRACT_SALAMINE_JUICE] )
- skills2 += sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1;
- if( sc->data[SC_INCASPDRATE] )
- skills2 += sc->data[SC_INCASPDRATE]->val1;
- if( sc->data[SC_GS_GATLINGFEVER] )
- skills2 += sc->data[SC_GS_GATLINGFEVER]->val1;
- if( sc->data[SC_STAR_COMFORT] )
- skills2 += 3 * sc->data[SC_STAR_COMFORT]->val1;
- if( sc->data[SC_ASSNCROS] && !skills1){
- if (bl->type!=BL_PC)
- skills2 += sc->data[SC_ASSNCROS]->val2;
- else
- switch(((TBL_PC*)bl)->status.weapon)
- {
- case W_BOW:
- case W_REVOLVER:
- case W_RIFLE:
- case W_GATLING:
- case W_SHOTGUN:
- case W_GRENADE:
- break;
- default:
- skills2 += sc->data[SC_ASSNCROS]->val2;
+ } else {
+ // ASPD percentage values
+ if (sc->data[SC_DONTFORGETME])
+ bonus -= sc->data[SC_DONTFORGETME]->val2;
+ if (sc->data[SC_LONGING])
+ bonus -= sc->data[SC_LONGING]->val2;
+ if (sc->data[SC_STEELBODY])
+ bonus -= 25;
+ if (sc->data[SC_SKA])
+ bonus -= 25;
+ if (sc->data[SC_DEFENDER])
+ bonus -= sc->data[SC_DEFENDER]->val4 / 10;
+ if (sc->data[SC_GOSPEL] && sc->data[SC_GOSPEL]->val4 == BCT_ENEMY) // needs more info
+ bonus -= 25;
+ if (sc->data[SC_GRAVITATION])
+ bonus -= sc->data[SC_GRAVITATION]->val2; // needs more info
+ if (sc->data[SC_JOINTBEAT]) { // needs more info
+ if (sc->data[SC_JOINTBEAT]->val2&BREAK_WRIST)
+ bonus -= 25;
+ if (sc->data[SC_JOINTBEAT]->val2&BREAK_KNEE)
+ bonus -= 10;
}
- }
- return ( flag&1? (skills1 + pots) : skills2 );
+ if (sc->data[SC_FROSTMISTY])
+ bonus -= 15;
+ if (sc->data[SC_HALLUCINATIONWALK_POSTDELAY])
+ bonus -= 50;
+ if (sc->data[SC_PARALYSE])
+ bonus -= 10;
+ if (sc->data[SC__BODYPAINT])
+ bonus -= sc->data[SC__BODYPAINT]->val1;
+ if (sc->data[SC__INVISIBILITY])
+ bonus -= sc->data[SC__INVISIBILITY]->val2 ;
+ if (sc->data[SC__GROOMY])
+ bonus -= sc->data[SC__GROOMY]->val2;
+ if (sc->data[SC_GLOOMYDAY])
+ bonus -= (15 + 5 * sc->data[SC_GLOOMYDAY]->val1);
+ if (sc->data[SC_EARTHDRIVE])
+ bonus -= 25;
+ if (sc->data[SC_MELON_BOMB])
+ bonus -= sc->data[SC_MELON_BOMB]->val1;
+ if (sc->data[SC_PAIN_KILLER])
+ bonus -= sc->data[SC_PAIN_KILLER]->val2;
+
+ if (sc->data[SC_SWING]) // TODO: SC_SWING shouldn't stack with skill1 modifiers
+ bonus += sc->data[SC_SWING]->val3;
+ if (sc->data[SC_DANCE_WITH_WUG])
+ bonus += sc->data[SC_DANCE_WITH_WUG]->val3;
+ if (sc->data[SC_GENTLETOUCH_CHANGE])
+ bonus += sc->data[SC_GENTLETOUCH_CHANGE]->val3;
+ if (sc->data[SC_BOOST500])
+ bonus += sc->data[SC_BOOST500]->val1;
+ if (sc->data[SC_EXTRACT_SALAMINE_JUICE])
+ bonus += sc->data[SC_EXTRACT_SALAMINE_JUICE]->val1;
+ if (sc->data[SC_INCASPDRATE])
+ bonus += sc->data[SC_INCASPDRATE]->val1;
+ if (sc->data[SC_GS_GATLINGFEVER])
+ bonus += sc->data[SC_GS_GATLINGFEVER]->val1;
+ if (sc->data[SC_STAR_COMFORT])
+ bonus += 3 * sc->data[SC_STAR_COMFORT]->val1;
+ }
+
+ return (bonus + pots);
#else
return 0;
#endif
@@ -5500,7 +5558,7 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int
aspd -= 10;
if (sc->data[SC_OVERED_BOOST]) // should be final and unmodifiable by any means
- aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3 * 10;
+ aspd = (200 - sc->data[SC_OVERED_BOOST]->val3) * 10;
return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway
}
@@ -5569,6 +5627,7 @@ short status_calc_aspd_rate(struct block_list *bl, struct status_change *sc, int
max = sc->data[SC_ASSNCROS]->val2;
}
}
+
aspd_rate -= max;
if(sc->data[SC_BERSERK])
@@ -5668,6 +5727,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])
@@ -5735,6 +5796,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])
@@ -5857,8 +5920,8 @@ const char* status_get_name(struct block_list *bl) {
/*==========================================
* Get the class of the current bl
* return
-* 0 = fail
-* class_id = success
+* 0 = fail
+* class_id = success
*------------------------------------------*/
int status_get_class(struct block_list *bl) {
nullpo_ret(bl);
@@ -5876,8 +5939,8 @@ int status_get_class(struct block_list *bl) {
/*==========================================
* Get the base level of the current bl
* return
-* 1 = fail
-* level = success
+* 1 = fail
+* level = success
*------------------------------------------*/
int status_get_lv(struct block_list *bl) {
nullpo_ret(bl);
@@ -5983,7 +6046,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;
@@ -6026,7 +6091,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;
@@ -6047,7 +6114,7 @@ int status_get_emblem_id(struct block_list *bl) {
case BL_MOB: {
struct map_session_data *msd;
struct mob_data *md = (struct mob_data *)bl;
- if (md->guardian_data) //Guardian's guild [Skotlex]
+ if (md->guardian_data) //Guardian's guild [Skotlex]
return (md->guardian_data->g) ? md->guardian_data->g->emblem_id:0;
if (md->special_state.ai && (msd = map->id2sd(md->master_id)) != NULL)
return msd->guild_emblem_id; //Alchemist's mobs [Skotlex]
@@ -6148,8 +6215,9 @@ 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) {
- switch (class_) { //Adapt class to a Mounted one.
+ if (pc_isridingpeco(sd)) {
+ switch (class_) {
+ //Adapt class to a Mounted one.
case JOB_KNIGHT:
class_ = JOB_KNIGHT2;
break;
@@ -6234,7 +6302,7 @@ void status_set_viewdata(struct block_list *bl, int class_)
ShowError("status_set_viewdata (NPC): No view data for class %d\n", class_);
}
break;
- case BL_HOM: //[blackhole89]
+ case BL_HOM: //[blackhole89]
{
struct homun_data *hd = (struct homun_data*)bl;
if (vd)
@@ -6285,36 +6353,33 @@ void status_change_init(struct block_list *bl) {
memset(sc, 0, sizeof (struct status_change));
}
-//Applies SC defense to a given status change.
-//Returns the adjusted duration based on flag values.
-//the flag values are the same as in status->change_start.
+/**
+ * Applies SC defense to a given status change.
+ *
+ * @see status_change_start for the expected parameters.
+ * @return the adjusted duration based on flag values.
+ */
int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int tick, int flag) {
//Percentual resistance: 10000 = 100% Resist
//Example: 50% -> sc_def=5000 -> 25%; 5000ms -> tick_def=5000 -> 2500ms
int sc_def = 0, tick_def = -1; //-1 = use sc_def
//Linear resistance substracted from rate and tick after percentual resistance was applied
//Example: 25% -> sc_def2=2000 -> 5%; 2500ms -> tick_def2=2000 -> 500ms
- int sc_def2 = 0, tick_def2 = -1; //-1 = use sc_def2 (pre-re only)
+ int sc_def2 = 0, tick_def2 = 0;
- struct status_data *st;
+ struct status_data *st, *bst;
struct status_change *sc;
struct map_session_data *sd;
nullpo_ret(bl);
-
+
if(!src)
return tick ? tick : 1; // If no source, it can't be resisted (NPC given)
/// Returns the 'bl's level, capped to 'cap'
#define SCDEF_LVL_CAP(bl, cap) ( (bl) ? (status->get_lv(bl) > (cap) ? (cap) : status->get_lv(bl)) : 0 )
-/// Renewal level modifier.
-/// In renewal, returns the difference between the levels of 'bl' and 'src', both capped to 'maxlv', multiplied by 'factor'
-/// In pre-renewal, returns zero.
-#ifdef RENEWAL
+/// returns the difference between the levels of 'bl' and 'src', both capped to 'maxlv', multiplied by 'factor'
#define SCDEF_LVL_DIFF(bl, src, maxlv, factor) ( ( SCDEF_LVL_CAP((bl), (maxlv)) - SCDEF_LVL_CAP((src), (maxlv)) ) * (factor) )
-#else
-#define SCDEF_LVL_DIFF(bl, src, maxlv, factor) 0
-#endif
//Status that are blocked by Golden Thief Bug card or Wand of Hermod
if (status->isimmune(bl))
@@ -6342,17 +6407,12 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_QUAGMIRE:
case SC_NJ_SUITON:
case SC_SWING:
- case SC__ENERVATION:
- case SC__GROOMY:
- case SC__IGNORANCE:
- case SC__LAZINESS:
- case SC__UNLUCKY:
- case SC__WEAKNESS:
return 0;
}
sd = BL_CAST(BL_PC,bl);
st = status->get_status_data(bl);
+ bst = status->get_base_status(bl);
sc = status->get_sc(bl);
if( sc && !sc->count )
sc = NULL;
@@ -6386,15 +6446,12 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
case SC_STUN:
sc_def = st->vit*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
tick_def2 = st->luk*10;
-#endif
break;
case SC_POISON:
case SC_DPOISON:
sc_def = st->vit*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
if (sd) {
//For players: 60000 - 450*vit - 100*luk
tick_def = st->vit*75;
@@ -6404,38 +6461,40 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
tick>>=1;
tick_def = (st->vit*200)/3;
}
-#endif
break;
case SC_SILENCE:
#ifdef RENEWAL
sc_def = st->int_*100;
sc_def2 = (st->vit + st->luk) * 5 + SCDEF_LVL_DIFF(bl, src, 99, 10);
- tick_def2 = st->luk * 10;
#else
sc_def = st->vit*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
#endif
+ tick_def2 = st->luk * 10;
break;
case SC_BLOODING:
#ifdef RENEWAL
sc_def = st->agi*100;
- tick_def2 = st->luk*10;
#else
sc_def = st->vit*100;
#endif
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+ tick_def2 = st->luk*10;
break;
case SC_SLEEP:
+#ifdef RENEWAL
+ sc_def = st->agi*100;
+ sc_def2 = (st->int_ + st->luk) * 5 + SCDEF_LVL_DIFF(bl, src, 99, 10);
+#else
sc_def = st->int_*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
- tick_def2 = st->luk*10;
#endif
+ tick_def2 = st->luk*10;
break;
case SC_DEEP_SLEEP:
- sc_def = st->int_*50;
+ sc_def = bst->int_*50;
tick_def = 0; // Linear reduction instead
- tick_def2 = st->int_ * 50 + SCDEF_LVL_CAP(bl, 150) * 50; // kRO balance update lists this formula
+ tick_def2 = bst->int_ * 50 + SCDEF_LVL_CAP(bl, 150) * 50; // kRO balance update lists this formula
break;
case SC_DEC_AGI:
case SC_ADORAMUS:
@@ -6443,7 +6502,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
sc_def = st->mdef*100;
#ifndef RENEWAL
sc_def2 = st->luk*10;
- tick_def2 = 0; //No duration reduction
#endif
tick_def = 0; //No duration reduction
break;
@@ -6451,50 +6509,30 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
sc_def = st->mdef*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
tick_def = 0; //No duration reduction
-#ifndef RENEWAL
- tick_def2 = 0; //No duration reduction
-#endif
break;
case SC_FREEZE:
sc_def = st->mdef*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
- tick_def = 0; //No duration reduction
-#ifdef RENEWAL
tick_def2 = status_get_luk(src) * -10; //Caster can increase final duration with luk
-#else
- tick_def2 = 0; //No duration reduction
-#endif
break;
case SC_CURSE:
// Special property: immunity when luk is zero
if (st->luk == 0)
return 0;
-#ifndef RENEWAL
- // Special property: immunity when luk is greater than level
- if (st->luk > status->get_lv(bl))
- return 0;
-#endif
sc_def = st->luk*100;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(NULL, src, 99, 10); // Curse only has a level penalty and no resistance
tick_def = st->vit*100;
-#ifdef RENEWAL
tick_def2 = st->luk*10;
-#endif
break;
case SC_BLIND:
sc_def = (st->vit + st->int_)*50;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
tick_def2 = st->luk*10;
-#endif
break;
case SC_CONFUSION:
sc_def = (st->str + st->int_)*50;
sc_def2 = st->luk*10 + SCDEF_LVL_DIFF(bl, src, 99, 10);
-#ifdef RENEWAL
- sc_def2 = -sc_def2; // Reversed sc_def2
tick_def2 = st->luk*10;
-#endif
break;
case SC_ANKLESNARE:
if(st->mode&MD_BOSS) // Lasts 5 times less on bosses
@@ -6506,7 +6544,6 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
if (sd) //Duration greatly reduced for players.
tick /= 15;
sc_def2 = st->vit*25 + st->agi*10 + SCDEF_LVL_CAP(bl, 99) * 20; // Linear Reduction of Rate
- tick_def2 = 0; //No duration reduction
break;
case SC_MARSHOFABYSS:
//5 second (Fixed) + 25 second - {( INT + LUK ) / 20 second }
@@ -6548,10 +6585,10 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
tick_def2 = (st->vit + st->agi) * 70;
break;
case SC_COLD:
- tick_def2 = st->vit*100 + status->get_lv(bl)*20;
+ tick_def2 = bst->vit*100 + status->get_lv(bl)*20;
break;
case SC_VACUUM_EXTREME:
- tick_def2 = st->str*50;
+ tick_def2 = bst->str*50;
break;
case SC_MANDRAGORA:
sc_def = (st->vit + st->luk)*20;
@@ -6559,9 +6596,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;
@@ -6612,16 +6646,9 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
//When tick def not set, reduction is the same for both.
if(tick_def == -1)
tick_def = sc_def;
- if(tick_def2 == -1) {
-#ifdef RENEWAL
- tick_def2 = 0;
-#else
- tick_def2 = sc_def2;
-#endif
- }
//Natural resistance
- if (!(flag&8)) {
+ if (!(flag&SCFLAG_FIXEDRATE)) {
rate -= rate*sc_def/10000;
rate -= sc_def2;
@@ -6655,7 +6682,7 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
if (tick < 1) return 1;
//Rate reduction
- if (flag&2)
+ if (flag&SCFLAG_FIXEDTICK)
return tick;
tick -= tick*tick_def/10000;
@@ -6687,19 +6714,19 @@ int status_get_sc_def(struct block_list *src, struct block_list *bl, enum sc_typ
void status_display_add(struct map_session_data *sd, enum sc_type type, int dval1, int dval2, int dval3) {
struct sc_display_entry *entry;
int i;
-
+
for( i = 0; i < sd->sc_display_count; i++ ) {
if( sd->sc_display[i]->type == type )
break;
}
-
+
if( i != sd->sc_display_count ) {
sd->sc_display[i]->val1 = dval1;
sd->sc_display[i]->val2 = dval2;
sd->sc_display[i]->val3 = dval3;
return;
}
-
+
entry = ers_alloc(pc->sc_display_ers, struct sc_display_entry);
entry->type = type;
@@ -6742,17 +6769,23 @@ void status_display_remove(struct map_session_data *sd, enum sc_type type) {
}
}
}
-/*==========================================
-* Starts a status change.
-* 'type' = type, 'val1~4' depend on the type.
-* 'rate' = base success rate. 10000 = 100%
-* 'tick' is base duration
-* 'flag':
-* &1: Cannot be avoided (it has to start)
-* &2: Tick should not be reduced (by vit, luk, lv, etc)
-* &4: sc_data loaded, no value has to be altered.
-* &8: rate should not be reduced
-*------------------------------------------*/
+/**
+ * Starts a status change.
+ *
+ * @param src Status change source bl.
+ * @param bl Status change target bl.
+ * @param type Status change type.
+ * @param rate Base success rate. 1 means 0.01%, 10000 means 100%.
+ * @param val1 Additional value (meaning depends on type).
+ * @param val2 Additional value (meaning depends on type).
+ * @param val3 Additional value (meaning depends on type).
+ * @param val4 Additional value (meaning depends on type).
+ * @param tick Base duration (milliseconds).
+ * @param flag Special flags (@see enum scstart_flag).
+ *
+ * @retval 0 if no status change happened.
+ * @retval 1 if the status change was successfully applied.
+ */
int status_change_start(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, int tick, int flag) {
struct map_session_data *sd = NULL;
struct status_change* sc;
@@ -6780,8 +6813,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
struct mob_data *md = BL_CAST(BL_MOB,bl);
if(md && (md->class_ == MOBID_EMPERIUM || mob_is_battleground(md)) && type != SC_SAFETYWALL && type != SC_PNEUMA)
return 0; //Emperium/BG Monsters can't be afflicted by status changes
- //if(md && mob_is_gvg(md) && status->sc2scb_flag(type)&SCB_MAXHP)
- // return 0; //prevent status addinh hp to gvg mob (like bloodylust=hp*3 etc...
+#if 0
+ if(md && mob_is_gvg(md) && status->sc2scb_flag(type)&SCB_MAXHP)
+ return 0; //prevent status addinh hp to gvg mob (like bloodylust=hp*3 etc...
+#endif // 0
}
if( sc->data[SC_REFRESH] ) {
@@ -6855,7 +6890,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
sd = BL_CAST(BL_PC, bl);
//Adjust tick according to status resistances
- if( !(flag&(1|4)) ) {
+ if( !(flag&(SCFLAG_NOAVOID|SCFLAG_LOADED)) ) {
tick = status->get_sc_def(src, bl, type, rate, tick, flag);
if( !tick ) return 0;
}
@@ -6877,7 +6912,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:
@@ -6885,7 +6920,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0;
case SC_FREEZE:
//Undead are immune to Freeze/Stone
- if (undead_flag && !(flag&1))
+ if (undead_flag && !(flag&SCFLAG_NOAVOID))
return 0;
case SC_SLEEP:
case SC_STUN:
@@ -6926,7 +6961,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
return 0; //Overthrust can't take effect if under Max Overthrust. [Skotlex]
case SC_OVERTHRUSTMAX:
if( sc->option&OPTION_MADOGEAR )
- return 0;//Overthrust and Overthrust Max cannot be used on Mado Gear [Ind]
+ return 0; //Overthrust and Overthrust Max cannot be used on Mado Gear [Ind]
break;
case SC_ADRENALINE:
if(sd && !pc_check_weapontype(sd,skill->get_weapontype(BS_ADRENALINE)))
@@ -6962,7 +6997,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_CARTBOOST:
case SC_ASSNCROS:
if(sc->option&OPTION_MADOGEAR)
- return 0;//Mado is immune to wind walk, cart boost, etc (others above) [Ind]
+ return 0; //Mado is immune to wind walk, cart boost, etc (others above) [Ind]
case SC_INC_AGI:
if (sc->data[SC_QUAGMIRE])
return 0;
@@ -6994,7 +7029,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
//Strip skills, need to divest something or it fails.
case SC_NOEQUIPWEAPON:
- if (sd && !(flag&4)) { //apply sc anyway if loading saved sc_data
+ if (sd && !(flag&SCFLAG_LOADED)) { //apply sc anyway if loading saved sc_data
int i;
opt_flag = 0; //Reuse to check success condition.
if(sd->bonus.unstripable_equip&EQP_WEAPON)
@@ -7012,7 +7047,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_NOEQUIPSHIELD:
if( val2 == 1 ) val2 = 0; //GX effect. Do not take shield off..
else
- if (sd && !(flag&4)) {
+ if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_SHIELD)
return 0;
@@ -7024,7 +7059,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_NOEQUIPARMOR:
- if (sd && !(flag&4)) {
+ if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_ARMOR)
return 0;
@@ -7036,7 +7071,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (tick == 1) return 1; //Minimal duration: Only strip without causing the SC
break;
case SC_NOEQUIPHELM:
- if (sd && !(flag&4)) {
+ if (sd && !(flag&SCFLAG_LOADED)) {
int i;
if(sd->bonus.unstripable_equip&EQP_HELM)
return 0;
@@ -7135,7 +7170,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
{ // it doesn't stack or even renewed
int i = SC_TOXIN;
for(; i<= SC_LEECHESEND; i++)
- if(sc->data[i]) return 0;
+ if(sc->data[i]) return 0;
}
break;
case SC_MAGNETICFIELD:
@@ -7149,7 +7184,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
}
//Check for BOSS resistances
- if(st->mode&MD_BOSS && !(flag&1)) {
+ if(st->mode&MD_BOSS && !(flag&SCFLAG_NOAVOID)) {
if (type>=SC_COMMON_MIN && type <= SC_COMMON_MAX)
return 0;
switch (type) {
@@ -7210,9 +7245,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if (sc->data[SC_STONE] && sc->opt1 == OPT1_STONE)
status_change_end(bl, SC_STONE, INVALID_TIMER);
}
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
case SC_INC_AGI:
status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
+ if(sc->data[SC_SOULLINK] && sc->data[SC_SOULLINK]->val2 == SL_HIGH)
+ status_change_end(bl, SC_SOULLINK, INVALID_TIMER);
break;
case SC_QUAGMIRE:
status_change_end(bl, SC_CONCENTRATION, INVALID_TIMER);
@@ -7285,8 +7324,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
status_change_end(bl, SC_ASSUMPTIO, INVALID_TIMER);
break;
case SC_CARTBOOST:
- if(sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS])
- { //Cancel Decrease Agi, but take no further effect [Skotlex]
+ if (sc->data[SC_DEC_AGI] || sc->data[SC_ADORAMUS]) {
+ //Cancel Decrease Agi, but take no further effect [Skotlex]
status_change_end(bl, SC_DEC_AGI, INVALID_TIMER);
status_change_end(bl, SC_ADORAMUS, INVALID_TIMER);
return 0;
@@ -7547,7 +7586,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
vd = status->get_viewdata(bl);
calc_flag = status->ChangeFlagTable[type];
- if(!(flag&4)) { //&4 - Do not parse val settings when loading SCs
+ if(!(flag&SCFLAG_LOADED)) { // Do not parse val settings when loading SCs
switch(type) {
case SC_ADORAMUS:
sc_start(src,bl,SC_BLIND,100,val1,skill->get_time(status->sc2skill(type),val1));
@@ -7558,16 +7597,16 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_ENDURE:
val2 = 7; // Hit-count [Celest]
- if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !val4 ) {
+ if( !(flag&SCFLAG_NOAVOID) && (bl->type&(BL_PC|BL_MER)) && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground && !val4 ) {
struct map_session_data *tsd;
if( sd ) {
int i;
for( i = 0; i < 5; i++ ) {
if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL);
}
} else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, 1);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, val3, val4, tick, SCFLAG_ALL);
}
//val4 signals infinite endure (if val4 == 2 it is infinite endure from Berserk)
if( val4 )
@@ -7588,7 +7627,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
tick_time = val2 = tick>0?tick:60000;
tick = -1; // duration sent to the client should be infinite
break;
- case SC_EDP: // [Celest]
+ case SC_EDP: // [Celest]
val2 = val1 + 2; //Chance to Poison enemies.
val3 = 50*(val1+1); //Damage increase (+50 +50*lv%)
#ifdef RENEWAL_EDP
@@ -7628,7 +7667,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
tick = -1;
break;
case SC_ENCHANTPOISON:
- val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate
+ val2= 250+50*val1; //Poisoning Chance (2.5+0.5%) in 1/10000 rate
case SC_ASPERSIO:
case SC_PROPERTYFIRE:
case SC_PROPERTYWATER:
@@ -7655,16 +7694,16 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_REFLECTSHIELD:
val2=10+val1*3; // %Dmg reflected
- if( !(flag&1) && (bl->type&(BL_PC|BL_MER)) ) {
+ if( !(flag&SCFLAG_NOAVOID) && (bl->type&(BL_PC|BL_MER)) ) {
struct map_session_data *tsd;
if( sd ) {
int i;
for( i = 0; i < 5; i++ ) {
if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
} else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
break;
case SC_NOEQUIPWEAPON:
@@ -7877,17 +7916,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
//val4&1 signals the presence of a wall.
//val4&2 makes cloak not end on normal attacks [Skotlex]
//val4&4 makes cloak not end on using skills
- if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB*)bl)->special_state.clone) ) //Standard cloaking.
+ if (bl->type == BL_PC || (bl->type == BL_MOB && ((TBL_MOB*)bl)->special_state.clone) ) //Standard cloaking.
val4 |= battle_config.pc_cloak_check_type&7;
else
val4 |= battle_config.monster_cloak_check_type&7;
break;
- case SC_SIGHT: /* splash status */
+ case SC_SIGHT: /* splash status */
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.
@@ -7907,7 +7946,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_AUTOGUARD:
- if( !(flag&1) ) {
+ if( !(flag&SCFLAG_NOAVOID) ) {
struct map_session_data *tsd;
int i,t;
for( i = val2 = 0; i < val1; i++) {
@@ -7919,17 +7958,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
if( sd ) {
for( i = 0; i < 5; i++ ) {
if( sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
}
else if( bl->type == BL_MER && ((TBL_MER*)bl)->devotion_flag && (tsd = ((TBL_MER*)bl)->master) )
- status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, 1);
+ status->change_start(bl, &tsd->bl, type, 10000, val1, val2, 0, 0, tick, SCFLAG_ALL);
}
}
break;
case SC_DEFENDER:
- if (!(flag&1)) {
+ if (!(flag&SCFLAG_NOAVOID)) {
val2 = 5 + 15*val1; //Damage reduction
val3 = 0; // unused, previously speed adjustment
val4 = 250 - 50*val1; //Aspd adjustment
@@ -7940,7 +7979,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
for (i = 0; i < 5; i++) {
//See if there are devoted characters, and pass the status to them. [Skotlex]
if (sd->devotion[i] && (tsd = map->id2sd(sd->devotion[i])))
- status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,1);
+ status->change_start(bl, &tsd->bl,type,10000,val1,5+val1*5,val3,val4,tick,SCFLAG_NOAVOID);
}
}
}
@@ -8030,6 +8069,23 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
stat = (psce->val4 >> 0)&0xFF; stat = min(stat, max_stat - tst->luk ); val4 |= cap_value(stat,0,0xFF);
}
break;
+ case SC_SOULLINK:
+ //1st Transcendent Spirit works similar to Marionette Control
+ if(sd && val2 == SL_HIGH) {
+ int stat,max_stat;
+ // Fetch target's stats
+ struct status_data* status2 = status->get_status_data(bl); // Battle status
+ val3 = 0;
+ val4 = 0;
+ max_stat = (status->get_lv(bl)-10<50)?status->get_lv(bl)-10:50;
+ stat = max(0, max_stat - status2->str ); val3 |= cap_value(stat,0,0xFF)<<16;
+ stat = max(0, max_stat - status2->agi ); val3 |= cap_value(stat,0,0xFF)<<8;
+ stat = max(0, max_stat - status2->vit ); val3 |= cap_value(stat,0,0xFF);
+ stat = max(0, max_stat - status2->int_); val4 |= cap_value(stat,0,0xFF)<<16;
+ stat = max(0, max_stat - status2->dex ); val4 |= cap_value(stat,0,0xFF)<<8;
+ stat = max(0, max_stat - status2->luk ); val4 |= cap_value(stat,0,0xFF);
+ }
+ break;
case SC_SWORDREJECT:
val2 = 15*val1; //Reflect chance
val3 = 3; //Reflections
@@ -8067,7 +8123,9 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
while( i >= 0 ) {
type2 = types[i];
if( d_sc->data[type2] )
- sc_start(bl, bl, type2, 100, d_sc->data[type2]->val1, skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1));
+ status->change_start(bl, bl, type2, 10000, d_sc->data[type2]->val1, 0, 0, 0,
+ skill->get_time(status->sc2skill(type2),d_sc->data[type2]->val1),
+ (type2 != SC_DEFENDER) ? SCFLAG_NOICON : SCFLAG_NONE);
i--;
}
}
@@ -8154,7 +8212,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_KAAHI:
val2 = 200*val1; //HP heal
val3 = 5*val1; //SP cost
- val4 = INVALID_TIMER; //Kaahi Timer.
+ val4 = INVALID_TIMER; //Kaahi Timer.
break;
case SC_BLESSING:
if ((!undead_flag && st->race!=RC_DEMON) || bl->type == BL_PC)
@@ -8290,7 +8348,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
//2. Set restore point (val3 -> return map, val4 return coords
val3 = map_index;
val4 = pos;
- } else if (!val3
+ } else if (!val3
|| val3 == sd->mapindex
|| !sd->sc.data[SC_JAILED] // If player is being jailed and is already in jail (issue: 8206)
) { //Use save point.
@@ -8344,11 +8402,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_STONESKIN:
- if (val2 == NPC_ANTIMAGIC)
- { //Boost mdef
+ if (val2 == NPC_ANTIMAGIC) {
+ //Boost mdef
val2 =-20;
val3 = 20;
- } else { //Boost def
+ } else {
+ //Boost def
val2 = 20;
val3 =-20;
}
@@ -8466,7 +8525,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
tick_time = 4000; // [GodLesZ] tick time
break;
case SC_PYREXIA:
- status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,11); // Blind status that last for 30 seconds
+ status->change_start(src, bl,SC_BLIND,10000,val1,0,0,0,30000,SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); // Blind status that last for 30 seconds
val4 = tick / 3000;
tick_time = 3000; // [GodLesZ] tick time
break;
@@ -8578,20 +8637,33 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC__ENERVATION:
val2 = 20 + 10 * val1; // ATK Reduction
- if( sd ) pc->delspiritball(sd,sd->spiritball,0);
+ if ( sd ) {
+ int i;
+ pc->delspiritball(sd, sd->spiritball, 0);
+ for (i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++)
+ pc->del_charm(sd, sd->spiritcharm[i], i);
+ }
break;
case SC__GROOMY:
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:
@@ -8688,8 +8760,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;
@@ -8785,18 +8859,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) ) * 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;
@@ -8804,7 +8876,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_HEATER_OPTION:
val2 = 120; // Watk. TODO: Renewal (Atk2)
val3 = (sd ? sd->status.job_level : 0); // % Increase damage.
- val4 = 3; // Change into fire element.
+ val4 = 3; // Change into fire element.
break;
case SC_TROPIC_OPTION:
val2 = 180; // Watk. TODO: Renewal (Atk2)
@@ -8814,16 +8886,16 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val2 = 40;
break;
case SC_COOLER_OPTION:
- val2 = 80; // Bonus Matk
+ val2 = 80; // Bonus Matk
val3 = (sd ? sd->status.job_level : 0); // % Freezing chance
- val4 = 1; // Change into water elemet
+ val4 = 1; // Change into water elemet
break;
case SC_CHILLY_AIR_OPTION:
val2 = 120; // Matk. TODO: Renewal (Matk1)
val3 = MG_COLDBOLT;
break;
case SC_WIND_STEP_OPTION:
- val2 = 50; // % Increase speed and flee.
+ val2 = 50; // % Increase speed and flee.
break;
case SC_BLAST_OPTION:
val2 = (sd ? sd->status.job_level : 0); // % Increase damage
@@ -8855,7 +8927,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
case SC_WATER_DROP_OPTION:
case SC_WIND_CURTAIN_OPTION:
case SC_STONE_SHIELD_OPTION:
- val2 = 100; // Elemental modifier.
+ val2 = 100; // Elemental modifier.
break;
case SC_TROPIC:
case SC_CHILLY_AIR:
@@ -8887,10 +8959,10 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
tick_time = val3;
break;
case SC_WATER_BARRIER:
- val3 = 20; // Reductions. Atk2, Flee1
+ val3 = 20; // Reductions. Atk2, Flee1
break;
case SC_ZEPHYR:
- val2 = 25; // Flee.
+ val2 = 25; // Flee.
break;
case SC_TIDAL_WEAPON:
val2 = 20; // Increase Elemental's attack.
@@ -8905,13 +8977,17 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val1 = 15;
break;
case SC_STOMACHACHE:
- val2 = 8; // SP consume.
+ val2 = 8; // SP consume.
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;
@@ -9036,8 +9112,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val2 = 20+(20*val1);
break;
default:
- if( calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0 )
- { //Status change with no calc, no icon, and no skill associated...?
+ if (calc_flag == SCB_NONE && status->SkillChangeTable[type] == 0 && status->IconChangeTable[type] == 0) {
+ //Status change with no calc, no icon, and no skill associated...?
ShowError("UnknownStatusChange [%d]\n", type);
return 0;
}
@@ -9058,13 +9134,10 @@ 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;
}
}
- /* values that must be set regardless of flag&4 e.g. val_flag */
+ /* values that must be set regardless of SCFLAG_LOADED e.g. val_flag */
switch(type) {
case SC_FIGHTINGSPIRIT:
val_flag |= 1|2;
@@ -9181,6 +9254,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:
@@ -9188,7 +9264,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
val_flag |= 1;
break;
}
-
+
/* [Ind/Hercules] */
if( sd && status->DisplayType[type] ) {
int dval1 = 0, dval2 = 0, dval3 = 0;
@@ -9239,7 +9315,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);
@@ -9293,13 +9368,13 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
opt_flag = 1;
switch(type) {
//OPT1
- case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
- case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
- case SC_STUN: sc->opt1 = OPT1_STUN; break;
- case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break;
- case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil]
- case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break;
- case SC_COLD: sc->opt1 = OPT1_CRYSTALIZE; break;
+ case SC_STONE: sc->opt1 = OPT1_STONEWAIT; break;
+ case SC_FREEZE: sc->opt1 = OPT1_FREEZE; break;
+ case SC_STUN: sc->opt1 = OPT1_STUN; break;
+ case SC_SLEEP: sc->opt1 = OPT1_SLEEP; break;
+ case SC_BURNING: sc->opt1 = OPT1_BURNING; break; // Burning need this to be showed correctly. [pakpil]
+ case SC_WHITEIMPRISON: sc->opt1 = OPT1_IMPRISON; break;
+ case SC_COLD: sc->opt1 = OPT1_CRYSTALIZE; break;
//OPT2
case SC_POISON: sc->opt2 |= OPT2_POISON; break;
case SC_CURSE: sc->opt2 |= OPT2_CURSE; break;
@@ -9325,7 +9400,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
break;
case SC_OVERTHRUSTMAX:
case SC_OVERTHRUST:
- case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know...
+ case SC_SWOO: //Why does it shares the same opt as Overthrust? Perhaps we'll never know...
sc->opt3 |= OPT3_OVERTHRUST;
opt_flag = 0;
break;
@@ -9361,10 +9436,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
opt_flag = 0;
sc->opt3 |= OPT3_BERSERK;
break;
-// case ???: // doesn't seem to do anything
-// sc->opt3 |= OPT3_LIGHTBLADE;
-// opt_flag = 0;
-// break;
+#if 0
+ case ???: // doesn't seem to do anything
+ sc->opt3 |= OPT3_LIGHTBLADE;
+ opt_flag = 0;
+ break;
+#endif // 0
case SC_DANCING:
if ((val1&0xFFFF) == CG_MOONLIT)
sc->opt3 |= OPT3_MOONLIT;
@@ -9399,10 +9476,12 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
sc->opt3 |= OPT3_UNDEAD;
opt_flag = 0;
break;
-// case ???: // from DA_CONTRACT (looks like biolab mobs aura)
-// sc->opt3 |= OPT3_CONTRACT;
-// opt_flag = 0;
-// break;
+#if 0
+ case ???: // from DA_CONTRACT (looks like biolab mobs aura)
+ sc->opt3 |= OPT3_CONTRACT;
+ opt_flag = 0;
+ break;
+#endif // 0
//OPTION
case SC_HIDING:
sc->option |= OPTION_HIDE;
@@ -9468,7 +9547,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
clif->changelook(bl,LOOK_CLOTHES_COLOR,vd->cloth_color);
}
}
- if (calc_flag&SCB_DYE) { //Reset DYE color
+ if (calc_flag&SCB_DYE) {
+ //Reset DYE color
if (vd && vd->cloth_color) {
val4 = vd->cloth_color;
clif->changelook(bl,LOOK_CLOTHES_COLOR,0);
@@ -9476,7 +9556,7 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t
calc_flag&=~SCB_DYE;
}
- if( !(flag&4 && status->DisplayType[type]) )
+ if(!(flag&SCFLAG_NOICON) && !(flag&SCFLAG_LOADED && status->DisplayType[type]))
clif->status_change(bl,status->IconChangeTable[type],1,tick,(val_flag&1)?val1:1,(val_flag&2)?val2:0,(val_flag&4)?val3:0);
/**
@@ -9670,7 +9750,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
#ifdef ANTI_MAYAP_CHEAT
bool invisible = false;
#endif
-
+
nullpo_ret(bl);
sc = status->get_sc(bl);
@@ -9686,7 +9766,7 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
if( sd && sce->timer == INVALID_TIMER && !sd->state.loggingout )
chrif->del_scdata_single(sd->status.account_id,sd->status.char_id,type);
-
+
if (tid == INVALID_TIMER) {
if (type == SC_ENDURE && sce->val4)
//Do not end infinite endure.
@@ -10132,9 +10212,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;
@@ -10312,10 +10389,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
opt_flag = 0;
sc->opt3 &= ~OPT3_BERSERK;
break;
- // case ???: // doesn't seem to do anything
- // sc->opt3 &= ~OPT3_LIGHTBLADE;
- // opt_flag = 0;
- // break;
+#if 0
+ case ???: // doesn't seem to do anything
+ sc->opt3 &= ~OPT3_LIGHTBLADE;
+ opt_flag = 0;
+ break;
+#endif // 0
case SC_DANCING:
if ((sce->val1&0xFFFF) == CG_MOONLIT)
sc->opt3 &= ~OPT3_MOONLIT;
@@ -10350,16 +10429,19 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
sc->opt3 &= ~OPT3_UNDEAD;
opt_flag = 0;
break;
- // case ???: // from DA_CONTRACT (looks like biolab mobs aura)
- // sc->opt3 &= ~OPT3_CONTRACT;
- // opt_flag = 0;
- // break;
+#if 0
+ case ???: // from DA_CONTRACT (looks like biolab mobs aura)
+ sc->opt3 &= ~OPT3_CONTRACT;
+ opt_flag = 0;
+ break;
+#endif // 0
default:
opt_flag = 0;
}
#ifdef ANTI_MAYAP_CHEAT
if (invisible && !(sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_INVISIBLE))) {
+ clif->slide(bl, bl->x, bl->y);
clif->fixpos(bl);
}
#endif
@@ -10392,8 +10474,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
if(opt_flag&4) //Out of hiding, invoke on place.
skill->unit_move(bl,timer->gettick(),1);
- if(opt_flag&2 && sd && map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC))
- npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event.
+ if (opt_flag & 2 && sd) {
+ if (map->getcell(bl->m,bl->x,bl->y,CELL_CHKNPC))
+ npc->touch_areanpc(sd,bl->m,bl->x,bl->y); //Trigger on-touch event.
+ else
+ npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);
+ }
ers_free(status->data_ers, sce);
return 1;
@@ -10515,14 +10601,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;
@@ -10584,10 +10673,11 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_KNOWLEDGE:
if (!sd) break;
- if(bl->m == sd->feel_map[0].m ||
- bl->m == sd->feel_map[1].m ||
- bl->m == sd->feel_map[2].m)
- { //Timeout will be handled by pc->setpos
+ if (bl->m == sd->feel_map[0].m
+ || bl->m == sd->feel_map[1].m
+ || bl->m == sd->feel_map[2].m
+ ) {
+ //Timeout will be handled by pc->setpos
sce->timer = INVALID_TIMER;
return 0;
}
@@ -10717,12 +10807,13 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
break;
case SC_SPLASHER:
- // custom Venom Splasher countdown timer
- //if (sce->val4 % 1000 == 0) {
- // char counter[10];
- // snprintf (counter, 10, "%d", sce->val4/1000);
- // clif->message(bl, counter);
- //}
+#if 0 // custom Venom Splasher countdown timer
+ if (sce->val4 % 1000 == 0) {
+ char counter[10];
+ snprintf (counter, 10, "%d", sce->val4/1000);
+ clif->message(bl, counter);
+ }
+#endif // 0
if((sce->val4 -= 500) > 0) {
sc_timer_next(500 + tick, status->change_timer, bl->id, data);
return 0;
@@ -10961,7 +11052,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC__REPRODUCE:
if( --(sce->val4) >= 0 ) {
- if( !status_charge(bl, 0, 9 - (1 + sce->val1) / 2) )
+ if( !status->charge(bl, 0, 9 - (1 + sce->val1) / 2) )
break;
sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
@@ -11032,10 +11123,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_SIRCLEOFNATURE:
if( --(sce->val4) >= 0 ) {
- if( !status_charge(bl,0,sce->val3) )
+ if( !status->charge(bl,0,sce->val3) )
break;
status->heal(bl, sce->val2, 0, 1);
- sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+ sc_timer_next(1000 + tick, status->change_timer, bl->id, data);
return 0;
}
break;
@@ -11051,7 +11142,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_SATURDAY_NIGHT_FEVER:
if( --(sce->val3) >= 0 ) {
- if( !status_charge(bl, st->max_hp * 1 / 100, st->max_sp * 1 / 100) )
+ if( !status->charge(bl, st->max_hp * 1 / 100, st->max_sp * 1 / 100) )
break;
sc_timer_next(3000+tick, status->change_timer, bl->id, data);
return 0;
@@ -11060,7 +11151,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
case SC_MELODYOFSINK:
if( --(sce->val4) >= 0 ) {
- status_charge(bl, 0, st->max_sp * ( 2 * sce->val1 + 2 * sce->val2 ) / 100);
+ status->charge(bl, 0, st->max_sp * ( 2 * sce->val1 + 2 * sce->val2 ) / 100);
sc_timer_next(1000+tick, status->change_timer, bl->id, data);
return 0;
}
@@ -11139,11 +11230,11 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) {
if(--(sce->val4) >= 0) {
// 1% SP Upkeep Cost
int sp = st->max_sp / 100;
-
+
if( st->sp <= sp )
status_change_end(bl,SC_STEALTHFIELD_MASTER,INVALID_TIMER);
- if( !status_charge(bl,0,sp) )
+ if( !status->charge(bl,0,sp) )
break;
if( !sc->data[SC_STEALTHFIELD_MASTER] )
@@ -11317,10 +11408,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;
@@ -11360,20 +11454,41 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
min = (int)(watk->atk - variance + strdex_bonus) + watk->atk2;
max = (int)(watk->atk + variance + strdex_bonus) + watk->atk2;
- }else if( watk->atk ){
+ }
+ else if (bl->type == BL_MOB && watk->atk){
min = watk->atk * 80 / 100;
max = watk->atk * 120 / 100;
}
+ else if (bl->type == BL_HOM && watk->atk){
+ if (flag & 4){
+ max = min = status->get_matk(bl, 2);
+ }
+ else{
+ min = watk->atk;
+ max = watk->atk2;
+ }
+ }
if( !(flag&1) ){
if( max > min )
- max = min + rnd()%(max - min);
+ max = min + rnd()%(max - min + 1);
else
max = min;
}
- if( bl->type == BL_PC && ((TBL_PC*)bl)->right_weapon.overrefine > 0 && !(flag&2) )
- max += rnd()%((TBL_PC*)bl)->right_weapon.overrefine + 1;
+ if ( bl->type == BL_PC && !(flag & 2) ) {
+ struct map_session_data *sd = (struct map_session_data *)bl;
+ short index = sd->equip_index[EQI_HAND_R], refine;
+ if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON
+ && (refine = sd->status.inventory[index].refine) < 16 && refine ) {
+ int r = status->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100;
+ if ( r )
+ max += (rnd() % 100) % r + 1;
+ }
+
+ if ( sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] > 0 )
+ max += 10 * max * sd->spiritcharm[SPIRITS_TYPE_CHARM_LAND] / 100;
+ }
max = status->calc_watk(bl, sc, max, false);
@@ -11384,31 +11499,21 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl
}
/**
- * Gets a random matk value depending on min matk and max matk
- **/
-unsigned short status_get_rand_matk( unsigned short matk_max, unsigned short matk_min ) {
- if( matk_max > matk_min )
- return matk_min + rnd()%(matk_max - matk_min);
- else
- return matk_min;
-}
-
-/**
- * Get bl's matk_max and matk_min values depending on flag
- * @param flag
- * 0 - Get MATK
- * 1 - Get MATK w/o SC bonuses
- * 3 - Get MATK w/o EATK & SC bonuses
- **/
-void status_get_matk_sub( struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min ) {
+* Get bl's matk_max and matk_min values depending on flag
+* @param flag
+* 0 - Get MATK
+* 1 - Get MATK w/o SC bonuses
+* 3 - Get MATK w/o EATK & SC bonuses
+**/
+void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min) {
struct status_data *st;
struct status_change *sc;
struct map_session_data *sd;
- if( bl == NULL )
+ if ( bl == NULL )
return;
- if( flag != 0 && flag != 1 && flag != 3 ) {
+ if ( flag != 0 && flag != 1 && flag != 3 ) {
ShowError("status_get_matk_sub: Unknown flag %d!\n", flag);
return;
}
@@ -11419,107 +11524,135 @@ void status_get_matk_sub( struct block_list *bl, int flag, unsigned short *matk_
#ifdef RENEWAL
/**
- * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK)
- * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers
- **/
- *matk_min = status->base_matk(st, status->get_lv(bl));
+ * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK)
+ * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers
+ **/
+ *matk_min = status->base_matk(bl, st, status->get_lv(bl));
// Any +MATK you get from skills and cards, including cards in weapon, is added here.
- if( sd && sd->bonus.ematk > 0 && flag != 3 )
+ if ( sd && sd->bonus.ematk > 0 && flag != 3 )
*matk_min += sd->bonus.ematk;
- if( flag != 3 )
+ if ( flag != 3 )
*matk_min = status->calc_ematk(bl, sc, *matk_min);
*matk_max = *matk_min;
- //This is the only portion in MATK that varies depending on the weapon level and refinement rate.
- if( bl->type&BL_PC && (st->rhw.matk + st->lhw.matk) > 0 ) {
- int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks
- int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level
- *matk_min += wMatk - variance;
- *matk_max += wMatk + variance;
- } else if( bl->type&BL_MOB ) {
- *matk_min = *matk_max = status_get_int(bl) + status->get_lv(bl);
+ switch ( bl->type ) {
+ case BL_PC:
+ //This is the only portion in MATK that varies depending on the weapon level and refinement rate.
+ if ( (st->rhw.matk + st->lhw.matk) > 0 ) {
+ int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks
+ int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level
+ *matk_min += wMatk - variance;
+ *matk_max += wMatk + variance;
+ }
+ break;
+ case BL_MOB:
*matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
*matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100;
+ break;
+ case BL_HOM:
+ *matk_min += (status_get_homint(bl) + status_get_homdex(bl)) / 5;
+ *matk_max += (status_get_homluk(bl) + status_get_homint(bl) + status_get_homdex(bl)) / 3;
+ break;
}
+
#else // not RENEWAL
- *matk_min = status_base_matk_min(st) + (sd?sd->bonus.ematk:0);
- *matk_max = status_base_matk_max(st) + (sd?sd->bonus.ematk:0);
+ *matk_min = status_base_matk_min(st) + (sd ? sd->bonus.ematk : 0);
+ *matk_max = status_base_matk_max(st) + (sd ? sd->bonus.ematk : 0);
#endif
- if (sd && sd->matk_rate != 100) {
- *matk_max = (*matk_max) * sd->matk_rate/100;
- *matk_min = (*matk_min) * sd->matk_rate/100;
+ if ( sd && sd->matk_rate != 100 ) {
+ *matk_max = (*matk_max) * sd->matk_rate / 100;
+ *matk_min = (*matk_min) * sd->matk_rate / 100;
}
- if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk
- || (sc && sc->data[SC_RECOGNIZEDSPELL]))
+ if ( (bl->type&BL_HOM && battle_config.hom_setting & 0x20) //Hom Min Matk is always the same as Max Matk
+ || (sc && sc->data[SC_RECOGNIZEDSPELL]) )
*matk_min = *matk_max;
#ifdef RENEWAL
- if( sd && sd->right_weapon.overrefine > 0 ) {
- (*matk_min)++;
- *matk_max += sd->right_weapon.overrefine - 1;
+ if ( sd && !(flag & 2) ) {
+ short index = sd->equip_index[EQI_HAND_R], refine;
+ if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON
+ && (refine = sd->status.inventory[index].refine) < 16 && refine ) {
+ int r = status->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100;
+ if ( r )
+ *matk_max += (rnd() % 100) % r + 1;
+ }
}
#endif
+
+ *matk_min = status->calc_matk(bl, sc, *matk_min, false);
+ *matk_max = status->calc_matk(bl, sc, *matk_max, false);
+
return;
}
/**
- * Get bl's matk value depending on flag
- * @param flag [malufett]
- * 1 - Get MATK w/o SC bonuses
- * 2 - Get modified MATK
- * 3 - Get MATK w/o eATK & SC bonuses
- * @retval 1 failure
- * @retval MATK success
- *
- * Shouldn't change _any_ value! [Panikon]
- **/
-int status_get_matk( struct block_list *bl, int flag ) {
+* Gets a random matk value depending on min matk and max matk
+**/
+unsigned short status_get_rand_matk(unsigned short matk_max, unsigned short matk_min) {
+ if ( matk_max > matk_min )
+ return matk_min + rnd() % (matk_max - matk_min);
+ else
+ return matk_min;
+}
+
+/**
+* Get bl's matk value depending on flag
+* @param flag [malufett]
+* 1 - Get MATK w/o SC bonuses
+* 2 - Get modified MATK
+* 3 - Get MATK w/o eATK & SC bonuses
+* @retval 1 failure
+* @retval MATK success
+*
+* Shouldn't change _any_ value! [Panikon]
+**/
+int status_get_matk(struct block_list *bl, int flag) {
struct status_data *st;
unsigned short matk_max, matk_min;
- if( bl == NULL )
+ if ( bl == NULL )
return 1;
- if( flag < 1 || flag > 3 ) {
+ if ( flag < 1 || flag > 3 ) {
ShowError("status_get_matk: Unknown flag %d!\n", flag);
return 1;
}
- if( (st = status->get_status_data(bl)) == NULL )
+ if ( (st = status->get_status_data(bl)) == NULL )
return 0;
// Just get matk
- if( flag == 2 )
+ if ( flag == 2 )
return status_get_rand_matk(st->matk_max, st->matk_min);
- status_get_matk_sub( bl, flag, &matk_max, &matk_min );
+ status_get_matk_sub(bl, flag, &matk_max, &matk_min);
// Get unmodified from sc matk
return status_get_rand_matk(matk_max, matk_min);
}
/**
- * Updates bl's MATK values
- **/
-void status_update_matk( struct block_list *bl ) {
+* Updates bl's MATK values
+**/
+void status_update_matk(struct block_list *bl) {
struct status_data *st;
struct status_change *sc;
unsigned short matk_max, matk_min;
- if( bl == NULL )
+ if ( bl == NULL )
return;
- if( (st = status->get_status_data(bl)) == NULL )
+ if ( (st = status->get_status_data(bl)) == NULL )
return;
- if( (sc = status->get_sc(bl)) == NULL )
+ if ( (sc = status->get_sc(bl)) == NULL )
return;
- status_get_matk_sub( bl, 0, &matk_max, &matk_min );
+ status_get_matk_sub(bl, 0, &matk_max, &matk_min);
// Update matk
st->matk_min = status->calc_matk(bl, sc, matk_min, true);
@@ -11669,7 +11802,7 @@ int status_change_spread( struct block_list *src, struct block_list *bl ) {
data.val2 = sc->data[i]->val2;
data.val3 = sc->data[i]->val3;
data.val4 = sc->data[i]->val4;
- status->change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,1|2|8);
+ status->change_start(src,bl,(sc_type)i,10000,data.val1,data.val2,data.val3,data.val4,data.tick,SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE);
flag = 1;
}
}
@@ -12053,7 +12186,7 @@ int status_readdb(void)
sv->readdb(map->db_path, "pre-re/job_db1.txt", ',', 5+MAX_WEAPON_TYPE, 5+MAX_WEAPON_TYPE, -1, status->readdb_job1);
#endif
sv->readdb(map->db_path, "job_db2.txt", ',', 1, 1+MAX_LEVEL, -1, status->readdb_job2);
- sv->readdb(map->db_path, "size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->atkmods), status->readdb_sizefix);
+ sv->readdb(map->db_path, DBPATH"size_fix.txt", ',', MAX_WEAPON_TYPE, MAX_WEAPON_TYPE, ARRAYLENGTH(status->atkmods), status->readdb_sizefix);
sv->readdb(map->db_path, DBPATH"refine_db.txt", ',', 4+MAX_REFINE, 4+MAX_REFINE, ARRAYLENGTH(status->refine_info), status->readdb_refine);
sv->readdb(map->db_path, "sc_config.txt", ',', 2, 2, SC_MAX, status->readdb_scconfig);
@@ -12204,7 +12337,7 @@ void status_defaults(void) {
status->readdb = status_readdb;
status->init = do_init_status;
status->final = do_final_status;
-
+
status->initChangeTables = initChangeTables;
status->initDummyData = initDummyData;
status->base_amotion_pc = status_base_amotion_pc;
diff --git a/src/map/status.h b/src/map/status.h
index 942f86d7c..63f9854d5 100644
--- a/src/map/status.h
+++ b/src/map/status.h
@@ -67,6 +67,20 @@ typedef enum sc_conf_type {
SC_NO_CLEAR = 0x80,
} sc_conf_type;
+/**
+ * Flags to be used with status->change_start
+ */
+enum scstart_flag {
+ // Note: When updating this enum, also update the documentation in doc/script_commands.txt and the constants in db/const.txt
+ SCFLAG_NONE = 0x00, ///< No special behavior.
+ SCFLAG_NOAVOID = 0x01, ///< Cannot be avoided (it has to start).
+ SCFLAG_FIXEDTICK = 0x02, ///< Tick should not be reduced (by vit, luk, lv, etc).
+ SCFLAG_LOADED = 0x04, ///< sc_data was loaded, no value has to be altered.
+ SCFLAG_FIXEDRATE = 0x08, ///< rate should not be reduced (not evaluated in status_change_start, but in some calls to other functions).
+ SCFLAG_NOICON = 0x10, ///< Status icon (SI) should not be sent.
+ SCFLAG_ALL = SCFLAG_NONE|SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_LOADED|SCFLAG_FIXEDRATE|SCFLAG_NOICON
+};
+
// Status changes listing. These code are for use by the server.
typedef enum sc_type {
SC_NONE = -1,
@@ -88,7 +102,7 @@ typedef enum sc_type {
SC_BURNING,
SC_DEEP_SLEEP,
SC_COMMON_MAX = 14, // end
-
+
//Next up, we continue on 20, to leave enough room for additional "common" ailments in the future.
SC_PROVOKE = 20,
SC_ENDURE,
@@ -253,7 +267,7 @@ typedef enum sc_type {
SC_DONTFORGETME, //180
SC_FORTUNE,
SC_SERVICEFORYOU,
- SC_STOP, //Prevents inflicted chars from walking. [Skotlex]
+ SC_STOP, //Prevents inflicted chars from walking. [Skotlex]
SC_STRUP,
SC_SOULLINK,
SC_COMA, //Not a real SC_, it makes a char's HP/SP hit 1.
@@ -310,7 +324,7 @@ typedef enum sc_type {
SC_NJ_SUITON,
SC_NJ_NEN,
SC_KNOWLEDGE,
- SC_SMA_READY, //240
+ SC_SMA_READY, //240
SC_FLING,
SC_HLIF_AVOID,
SC_HLIF_CHANGE,
@@ -320,7 +334,7 @@ typedef enum sc_type {
SC_HAMI_DEFENCE,
SC_INCASPDRATE,
SC_PLUSAVOIDVALUE,
- SC_JAILED, //250
+ SC_JAILED, //250
SC_ENCHANTARMS,
SC_MAGICALATTACK,
SC_STONESKIN,
@@ -665,7 +679,7 @@ typedef enum sc_type {
SC_ZANGETSU,
SC_GENSOU,
SC_AKAITSUKI,
-
+
//homon S
SC_STYLE_CHANGE,
SC_GOLDENE_FERSE, // 540
@@ -691,13 +705,13 @@ typedef enum sc_type {
SC_TELEKINESIS_INTENSE,
SC_OFFERTORIUM,
SC_FRIGG_SONG, // 560
-
+
SC_ALL_RIDING,
SC_HANBOK,
SC_MONSTER_TRANSFORM,
SC_ANGEL_PROTECT,
SC_ILLUSIONDOPING,
-
+
SC_MTF_ASPD,
SC_MTF_RANGEATK,
SC_MTF_MATK,
@@ -710,13 +724,13 @@ typedef enum sc_type {
SC_OKTOBERFEST,
SC_STRANGELIGHTS,
SC_DECORATION_OF_MUSIC,
-
+
SC__MAELSTROM,
SC__CHAOS,
-
+
SC__FEINTBOMB_MASTER,
SC_FALLENEMPIRE,
- SC_FLASHCOMBO,
+ SC_FLASHCOMBO, // 580
//Vellum Weapon reductions
SC_DEFSET,
@@ -724,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;
@@ -1185,7 +1205,7 @@ enum si_type {
SI_ECHOSONG = 443,
SI_HARMONIZE = 444,
SI_STRIKING = 445,
- SI_WARMER = 446,
+ //SI_WARMER = 446,
SI_MOONLITSERENADE = 447,
SI_SATURDAYNIGHTFEVER = 448,
SI_SITDOWN_FORCE = 449,
@@ -1474,21 +1494,21 @@ enum si_type {
//SI_ = 735,
SI_CHILL = 736,
SI_BURNT = 737,
-// SI_PCCAFE_PLAY_TIME = 738,
-// SI_TWISTED_TIME = 739,
+ //SI_PCCAFE_PLAY_TIME = 738,
+ //SI_TWISTED_TIME = 739,
SI_FLASHCOMBO = 740,
-// SI_JITTER_BUFF1 = 741,
-// SI_JITTER_BUFF2 = 742,
-// SI_JITTER_BUFF3 = 743,
-// SI_JITTER_BUFF4 = 744,
-// SI_JITTER_BUFF5 = 745,
-// SI_JITTER_BUFF6 = 746,
-// SI_JITTER_BUFF7 = 747,
-// SI_JITTER_BUFF8 = 748,
-// SI_JITTER_BUFF9 = 749,
-// SI_JITTER_BUFF10 = 750,
-// SI_CUP_OF_BOZA = 751,
+ //SI_JITTER_BUFF1 = 741,
+ //SI_JITTER_BUFF2 = 742,
+ //SI_JITTER_BUFF3 = 743,
+ //SI_JITTER_BUFF4 = 744,
+ //SI_JITTER_BUFF5 = 745,
+ //SI_JITTER_BUFF6 = 746,
+ //SI_JITTER_BUFF7 = 747,
+ //SI_JITTER_BUFF8 = 748,
+ //SI_JITTER_BUFF9 = 749,
+ //SI_JITTER_BUFF10 = 750,
+ //SI_CUP_OF_BOZA = 751,
SI_B_TRAP = 752,
SI_E_CHAIN = 753,
SI_E_QD_SHOT_READY = 754,
@@ -1514,38 +1534,38 @@ enum si_type {
SI_PACKING_ENVELOPE9 = 774,
SI_PACKING_ENVELOPE10 = 775,
SI_GLASTHEIM_TRANS = 776,
-// SI_ZONGZI_POUCH_TRANS = 777,
+ //SI_ZONGZI_POUCH_TRANS = 777,
SI_HEAT_BARREL_AFTER = 778,
SI_DECORATION_OF_MUSIC = 779,
-// SI_OVERSEAEXPUP = 780,
-// SI_CLOWN_N_GYPSY_CARD = 781,
-// SI_OPEN_NPC_MARKET = 782,
-// SI_BEEF_RIB_STEW = 783,
-// SI_PORK_RIB_STEW = 784,
-// SI_CHUSEOK_MONDAY = 785,
-// SI_CHUSEOK_TUESDAY = 786,
-// SI_CHUSEOK_WEDNESDAY = 787,
-// SI_CHUSEOK_THURSDAY = 788,
-// SI_CHUSEOK_FRIDAY = 789,
-// SI_CHUSEOK_WEEKEND = 790,
-// SI_ALL_LIGHTGUARD = 791,
-// SI_ALL_LIGHTGUARD_COOL_TIME = 792,
-// SI_MTF_MHP = 793,
-// SI_MTF_MSP = 794,
-// SI_MTF_PUMPKIN = 795,
-// SI_MTF_HITFLEE = 796,
-// SI_MTF_CRIDAMAGE2 = 797,
-// SI_MTF_SPDRAIN = 798,
-// SI_ACUO_MINT_GUM = 799,
-// ...
-// SI_GUILD_STORAGE = 810,
-// ...
-// SI_JUMPINGCLAN = 815,
-// ...
-// SI_MTF_RANGEATK2 = 818,
-// SI_MTF_ASPD2 = 819,
-// SI_MTF_MATK2 = 820,
+ //SI_OVERSEAEXPUP = 780,
+ //SI_CLOWN_N_GYPSY_CARD = 781,
+ //SI_OPEN_NPC_MARKET = 782,
+ //SI_BEEF_RIB_STEW = 783,
+ //SI_PORK_RIB_STEW = 784,
+ //SI_CHUSEOK_MONDAY = 785,
+ //SI_CHUSEOK_TUESDAY = 786,
+ //SI_CHUSEOK_WEDNESDAY = 787,
+ //SI_CHUSEOK_THURSDAY = 788,
+ //SI_CHUSEOK_FRIDAY = 789,
+ //SI_CHUSEOK_WEEKEND = 790,
+ //SI_ALL_LIGHTGUARD = 791,
+ //SI_ALL_LIGHTGUARD_COOL_TIME = 792,
+ //SI_MTF_MHP = 793,
+ //SI_MTF_MSP = 794,
+ //SI_MTF_PUMPKIN = 795,
+ //SI_MTF_HITFLEE = 796,
+ //SI_MTF_CRIDAMAGE2 = 797,
+ //SI_MTF_SPDRAIN = 798,
+ //SI_ACUO_MINT_GUM = 799,
+ // ...
+ //SI_GUILD_STORAGE = 810,
+ // ...
+ //SI_JUMPINGCLAN = 815,
+ // ...
+ //SI_MTF_RANGEATK2 = 818,
+ //SI_MTF_ASPD2 = 819,
+ //SI_MTF_MATK2 = 820,
SI_MAX,
};
@@ -1580,7 +1600,6 @@ enum e_mode
MD_CHANGETARGET_MELEE = 0x1000,
MD_CHANGETARGET_CHASE = 0x2000,
MD_TARGETWEAK = 0x4000,
- MD_RANDOMTARGET = 0x8000,
MD_MASK = 0xFFFF,
};
@@ -1662,18 +1681,18 @@ enum {
OPTION_DRAGON5 = 0x04000000,
OPTION_HANBOK = 0x08000000,
OPTION_OKTOBERFEST = 0x10000000,
-
+
#ifndef NEW_CARTS
OPTION_CART1 = 0x00000008,
OPTION_CART2 = 0x00000080,
OPTION_CART3 = 0x00000100,
OPTION_CART4 = 0x00000200,
OPTION_CART5 = 0x00000400,
-
+
/* compound constant for older carts */
OPTION_CART = OPTION_CART1|OPTION_CART2|OPTION_CART3|OPTION_CART4|OPTION_CART5,
#endif
-
+
// compound constants
OPTION_DRAGON = OPTION_DRAGON1|OPTION_DRAGON2|OPTION_DRAGON3|OPTION_DRAGON4|OPTION_DRAGON5,
OPTION_COSTUME = OPTION_WEDDING|OPTION_XMAS|OPTION_SUMMER|OPTION_HANBOK|OPTION_OKTOBERFEST,
@@ -1806,7 +1825,7 @@ struct regen_data_sub {
struct {
unsigned int hp,sp;
} tick;
-
+
//Regen rates (where every 1 means +100% regen)
struct {
unsigned char hp,sp;
@@ -1823,18 +1842,18 @@ struct regen_data {
struct {
unsigned int hp,sp,shp,ssp;
} tick;
-
+
//Regen rates (where every 1 means +100% regen)
struct {
unsigned char
hp,sp,shp,ssp;
} rate;
-
+
struct {
- unsigned walk:1; //Can you regen even when walking?
- unsigned gc:1; //Tags when you should have double regen due to GVG castle
+ unsigned walk:1; //Can you regen even when walking?
+ unsigned gc:1; //Tags when you should have double regen due to GVG castle
unsigned overweight :2; //overweight state (1: 50%, 2: 90%)
- unsigned block :2; //Block regen flag (1: Hp, 2: Sp)
+ unsigned block :2; //Block regen flag (1: Hp, 2: Sp)
} state;
//skill-regen, sitting-skill-regen (since not all chars with regen need it)
@@ -1920,10 +1939,17 @@ struct status_change {
#define status_get_size(bl) (status->get_status_data(bl)->size)
#define status_get_mode(bl) (status->get_status_data(bl)->mode)
+#define status_get_homstr(bl) (st->str + ((TBL_HOM*)bl)->homunculus.str_value)
+#define status_get_homagi(bl) (st->agi + ((TBL_HOM*)bl)->homunculus.agi_value)
+#define status_get_homvit(bl) (st->vit + ((TBL_HOM*)bl)->homunculus.vit_value)
+#define status_get_homint(bl) (st->int_ + ((TBL_HOM*)bl)->homunculus.int_value)
+#define status_get_homdex(bl) (st->dex + ((TBL_HOM*)bl)->homunculus.dex_value)
+#define status_get_homluk(bl) (st->luk + ((TBL_HOM*)bl)->homunculus.luk_value)
+
//Short version, receives rate in 1->100 range, and does not uses a flag setting.
-#define sc_start(src, bl, type, rate, val1, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),0,0,0,(tick),0))
-#define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),0))
-#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),0))
+#define sc_start(src, bl, type, rate, val1, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),0,0,0,(tick),SCFLAG_NONE))
+#define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),SCFLAG_NONE))
+#define sc_start4(src, bl, type, rate, val1, val2, val3, val4, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),(val3),(val4),(tick),SCFLAG_NONE))
#define status_change_end(bl,type,tid) (status->change_end_((bl),(type),(tid),__FILE__,__LINE__))
@@ -2043,14 +2069,14 @@ struct status_interface {
defType (*calc_mdef) (struct block_list *bl, struct status_change *sc, int mdef, bool viewable);
short (*calc_mdef2) (struct block_list *bl, struct status_change *sc, int mdef2, bool viewable);
unsigned short (*calc_batk)(struct block_list *bl, struct status_change *sc, int batk, bool viewable);
- unsigned short (*base_matk) (const struct status_data *st, int level);
+ unsigned short(*base_matk) (struct block_list *bl, const struct status_data *st, int level);
int (*get_weapon_atk) (struct block_list *src, struct weapon_atk *watk, int flag);
int (*get_total_mdef) (struct block_list *src);
int (*get_total_def) (struct block_list *src);
int (*get_matk) (struct block_list *src, int flag);
void (*update_matk) ( struct block_list *bl );
int (*readdb) (void);
-
+
void (*initChangeTables) (void);
void (*initDummyData) (void);
int (*base_amotion_pc) (struct map_session_data *sd, struct status_data *st);
diff --git a/src/map/storage.c b/src/map/storage.c
index 217f14a3a..755f50cb7 100644
--- a/src/map/storage.c
+++ b/src/map/storage.c
@@ -85,13 +85,13 @@ int storage_storageopen(struct map_session_data *sd)
if(sd->state.storage_flag)
return 1; //Already open?
-
- if( !pc_can_give_items(sd) )
- { //check is this GM level is allowed to put items to storage
+
+ if( !pc_can_give_items(sd) ) {
+ //check is this GM level is allowed to put items to storage
clif->message(sd->fd, msg_txt(246));
return 1;
}
-
+
sd->state.storage_flag = 1;
storage->sortitem(sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
clif->storagelist(sd, sd->status.storage.items, ARRAYLENGTH(sd->status.storage.items));
@@ -128,7 +128,7 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo
if( item_data->nameid <= 0 || amount <= 0 )
return 1;
-
+
data = itemdb->search(item_data->nameid);
if( data->stack.storage && amount > data->stack.amount )
@@ -136,12 +136,12 @@ int storage_additem(struct map_session_data* sd, struct item* item_data, int amo
return 1;
}
- if( !itemdb_canstore(item_data, pc_get_group_level(sd)) )
- { //Check if item is storable. [Skotlex]
+ if (!itemdb_canstore(item_data, pc_get_group_level(sd))) {
+ //Check if item is storable. [Skotlex]
clif->message (sd->fd, msg_txt(264));
return 1;
}
-
+
if( item_data->bound > IBT_ACCOUNT && !pc_can_give_bound_items(sd) ) {
clif->message(sd->fd, msg_txt(294));
return 1;
@@ -200,8 +200,8 @@ int storage_delitem(struct map_session_data* sd, int n, int amount)
* Add an item to the storage from the inventory.
* @index : inventory idx
* return
- * 0 : fail
- * 1 : success
+ * 0 : fail
+ * 1 : success
*------------------------------------------*/
int storage_storageadd(struct map_session_data* sd, int index, int amount) {
nullpo_ret(sd);
@@ -216,7 +216,7 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount) {
return 0; // No item on that spot
if( amount < 1 || amount > sd->status.inventory[index].amount )
- return 0;
+ return 0;
if( storage->additem(sd,&sd->status.inventory[index],amount) == 0 )
pc->delitem(sd,index,amount,0,4,LOG_TYPE_STORAGE);
@@ -230,8 +230,8 @@ int storage_storageadd(struct map_session_data* sd, int index, int amount) {
* Retrieve an item from the storage into inventory
* @index : storage idx
* return
- * 0 : fail
- * 1 : success
+ * 0 : fail
+ * 1 : success
*------------------------------------------*/
int storage_storageget(struct map_session_data* sd, int index, int amount)
{
@@ -242,7 +242,7 @@ int storage_storageget(struct map_session_data* sd, int index, int amount)
if( sd->status.storage.items[index].nameid <= 0 )
return 0; //Nothing there
-
+
if( amount < 1 || amount > sd->status.storage.items[index].amount )
return 0;
@@ -258,22 +258,22 @@ int storage_storageget(struct map_session_data* sd, int index, int amount)
* Move an item from cart to storage.
* @index : cart inventory index
* return
- * 0 : fail
- * 1 : success
+ * 0 : fail
+ * 1 : success
*------------------------------------------*/
int storage_storageaddfromcart(struct map_session_data* sd, int index, int amount)
{
nullpo_ret(sd);
if( sd->status.storage.storage_amount > MAX_STORAGE )
- return 0; // storage full / storage closed
+ return 0; // storage full / storage closed
if( index < 0 || index >= MAX_CART )
- return 0;
+ return 0;
if( sd->status.cart[index].nameid <= 0 )
return 0; //No item there.
-
+
if( amount < 1 || amount > sd->status.cart[index].amount )
return 0;
@@ -287,8 +287,8 @@ int storage_storageaddfromcart(struct map_session_data* sd, int index, int amoun
* Get from Storage to the Cart inventory
* @index : storage index
* return
- * 0 : fail
- * 1 : success
+ * 0 : fail
+ * 1 : success
*------------------------------------------*/
int storage_storagegettocart(struct map_session_data* sd, int index, int amount) {
int flag = 0;
@@ -296,13 +296,13 @@ int storage_storagegettocart(struct map_session_data* sd, int index, int amount)
if( index < 0 || index >= MAX_STORAGE )
return 0;
-
+
if( sd->status.storage.items[index].nameid <= 0 )
return 0; //Nothing there.
-
+
if( amount < 1 || amount > sd->status.storage.items[index].amount )
return 0;
-
+
if( (flag = pc->cart_additem(sd,&sd->status.storage.items[index],amount,LOG_TYPE_STORAGE)) == 0 )
storage->delitem(sd,index,amount);
else {
@@ -333,7 +333,7 @@ void storage_storageclose(struct map_session_data* sd) {
*------------------------------------------*/
void storage_storage_quit(struct map_session_data* sd, int flag) {
nullpo_retv(sd);
-
+
if (map->save_settings&4)
chrif->save(sd, flag); //Invokes the storage saving as well.
@@ -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;
@@ -372,9 +367,9 @@ int guild_storage_delete(int guild_id) {
/*==========================================
* Attempt to open guild storage for sd
* return
-* 0 : success (open or req to create a new one)
-* 1 : fail
-* 2 : no guild for sd
+* 0 : success (open or req to create a new one)
+* 1 : fail
+* 2 : no guild for sd
*------------------------------------------*/
int storage_guild_storageopen(struct map_session_data* sd)
{
@@ -387,22 +382,22 @@ int storage_guild_storageopen(struct map_session_data* sd)
if(sd->state.storage_flag)
return 1; //Can't open both storages at a time.
-
+
if( !pc_can_give_items(sd) ) { //check is this GM level can open guild storage and store items [Lupus]
clif->message(sd->fd, msg_txt(246));
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;
}
if(gstor->storage_status)
return 1;
-
+
if( gstor->lock )
return 1;
-
+
gstor->storage_status = 1;
sd->state.storage_flag = 2;
storage->sortitem(gstor->items, ARRAYLENGTH(gstor->items));
@@ -414,8 +409,8 @@ int storage_guild_storageopen(struct map_session_data* sd)
/*==========================================
* Attempt to add an item in guild storage, then refresh it
* return
-* 0 : success
-* 1 : fail
+* 0 : success
+* 1 : fail
*------------------------------------------*/
int guild_storage_additem(struct map_session_data* sd, struct guild_storage* stor, struct item* item_data, int amount)
{
@@ -436,8 +431,8 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
return 1;
}
- if( !itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time )
- { //Check if item is storable. [Skotlex]
+ if (!itemdb_canguildstore(item_data, pc_get_group_level(sd)) || item_data->expire_time) {
+ //Check if item is storable. [Skotlex]
clif->message (sd->fd, msg_txt(264));
return 1;
}
@@ -446,7 +441,7 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
clif->message(sd->fd, msg_txt(294));
return 1;
}
-
+
if(itemdb->isstackable2(data)){ //Stackable
for(i=0;i<MAX_GUILD_STORAGE;i++){
if(compare_item(&stor->items[i], item_data)) {
@@ -461,10 +456,10 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
}
//Add item
for(i=0;i<MAX_GUILD_STORAGE && stor->items[i].nameid;i++);
-
+
if(i>=MAX_GUILD_STORAGE)
return 1;
-
+
memcpy(&stor->items[i],item_data,sizeof(stor->items[0]));
stor->items[i].amount=amount;
stor->storage_amount++;
@@ -477,8 +472,8 @@ int guild_storage_additem(struct map_session_data* sd, struct guild_storage* sto
/*==========================================
* Attempt to delete an item in guild storage, then refresh it
* return
-* 0 : success
-* 1 : fail
+* 0 : success
+* 1 : fail
*------------------------------------------*/
int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* stor, int n, int amount)
{
@@ -503,28 +498,28 @@ int guild_storage_delitem(struct map_session_data* sd, struct guild_storage* sto
* Attempt to add an item in guild storage from inventory, then refresh it
* @index : inventory idx
* return
-* 0 : fail
-* 1 : succes
+* 0 : fail
+* 1 : succes
*------------------------------------------*/
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;
-
+
if( index<0 || index>=MAX_INVENTORY )
return 0;
if( sd->status.inventory[index].nameid <= 0 )
return 0;
-
+
if( amount < 1 || amount > sd->status.inventory[index].amount )
return 0;
-
+
if( stor->lock ) {
gstorage->close(sd);
return 0;
@@ -542,8 +537,8 @@ int storage_guild_storageadd(struct map_session_data* sd, int index, int amount)
* Attempt to retrieve an item from guild storage to inventory, then refresh it
* @index : storage idx
* return
-* 0 : fail
-* 1 : success
+* 0 : fail
+* 1 : success
*------------------------------------------*/
int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
{
@@ -551,20 +546,20 @@ 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;
-
+ return 0;
+
if(index<0 || index>=MAX_GUILD_STORAGE)
return 0;
if(stor->items[index].nameid <= 0)
return 0;
-
+
if(amount < 1 || amount > stor->items[index].amount)
- return 0;
-
+ return 0;
+
if( stor->lock ) {
gstorage->close(sd);
return 0;
@@ -574,7 +569,7 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
gstorage->delitem(sd,stor,index,amount);
else //inform fail
clif->additem(sd,0,0,flag);
-// log_fromstorage(sd, index, 1);
+ //log_fromstorage(sd, index, 1);
return 0;
}
@@ -583,15 +578,15 @@ int storage_guild_storageget(struct map_session_data* sd, int index, int amount)
* Attempt to add an item in guild storage from cart, then refresh it
* @index : cart inventory idx
* return
-* 0 : fail
-* 1 : success
+* 0 : fail
+* 1 : success
*------------------------------------------*/
int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int amount)
{
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;
@@ -601,7 +596,7 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
if( sd->status.cart[index].nameid <= 0 )
return 0;
-
+
if( amount < 1 || amount > sd->status.cart[index].amount )
return 0;
@@ -615,25 +610,25 @@ int storage_guild_storageaddfromcart(struct map_session_data* sd, int index, int
* Attempt to retrieve an item from guild storage to cart, then refresh it
* @index : storage idx
* return
-* 0 : fail
-* 1 : success
+* 0 : fail
+* 1 : success
*------------------------------------------*/
int storage_guild_storagegettocart(struct map_session_data* sd, int index, int amount)
{
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;
+ return 0;
if(index<0 || index>=MAX_GUILD_STORAGE)
- return 0;
-
+ return 0;
+
if(stor->items[index].nameid<=0)
return 0;
-
+
if(amount < 1 || amount > stor->items[index].amount)
return 0;
@@ -646,18 +641,18 @@ int storage_guild_storagegettocart(struct map_session_data* sd, int index, int a
/*==========================================
* Request to save guild storage
* return
-* 0 : fail (no storage)
-* 1 : success
+* 0 : fail (no storage)
+* 1 : success
*------------------------------------------*/
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)
{
if (flag) //Char quitting, close it.
stor->storage_status = 0;
- if (stor->dirty)
+ if (stor->dirty)
intif->send_guild_storage(account_id,stor);
return 1;
}
@@ -667,16 +662,16 @@ int storage_guild_storagesave(int account_id, int guild_id, int flag)
/*==========================================
* ACK save of guild storage
* return
-* 0 : fail (no storage)
-* 1 : success
+* 0 : fail (no storage)
+* 1 : success
*------------------------------------------*/
int storage_guild_storagesaved(int guild_id)
{
struct guild_storage *stor;
- if((stor=gstorage->id2storage2(guild_id)) != NULL) {
- if (stor->dirty && stor->storage_status == 0)
- { //Storage has been correctly saved.
+ if((stor=idb_get(gstorage->db,guild_id)) != NULL) {
+ if (stor->dirty && stor->storage_status == 0) {
+ //Storage has been correctly saved.
stor->dirty = 0;
}
return 1;
@@ -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,8 +703,8 @@ 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)
sd->state.storage_flag = 0;
@@ -760,13 +755,12 @@ void storage_defaults(void) {
}
void gstorage_defaults(void) {
gstorage = &gstorage_s;
-
+
/* */
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/trade.c b/src/map/trade.c
index 3bbb73568..4d6909957 100644
--- a/src/map/trade.c
+++ b/src/map/trade.c
@@ -43,8 +43,8 @@ void trade_traderequest(struct map_session_data *sd, struct map_session_data *ta
return;
}
- if (target_sd->npc_id)
- { //Trade fails if you are using an NPC.
+ if (target_sd->npc_id) {
+ //Trade fails if you are using an NPC.
clif->tradestart(sd, 2);
return;
}
@@ -145,9 +145,10 @@ void trade_tradeack(struct map_session_data *sd, int type) {
}
//Check if you can start trade.
- if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag ||
- tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag)
- { //Fail
+ if (sd->npc_id || sd->state.vending || sd->state.buyingstore || sd->state.storage_flag
+ || tsd->npc_id || tsd->state.vending || tsd->state.buyingstore || tsd->state.storage_flag
+ ) {
+ //Fail
clif->tradestart(sd, 2);
clif->tradestart(tsd, 2);
sd->state.deal_locked = 0;
@@ -335,8 +336,8 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
return;
}
- if( amount == 0 )
- { //Why do this.. ~.~ just send an ack, the item won't display on the trade window.
+ if (amount == 0) {
+ //Why do this.. ~.~ just send an ack, the item won't display on the trade window.
clif->tradeitemok(sd, index, TIO_SUCCESS);
return;
}
@@ -375,7 +376,7 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
clif->tradeitemok(sd, index+2, TIO_INDROCKS);
return;
}
-
+
//Locate a trade position
ARR_FIND( 0, 10, trade_i, sd->deal.item[trade_i].index == index || sd->deal.item[trade_i].amount == 0 );
if( trade_i == 10 ) //No space left
@@ -385,23 +386,22 @@ void trade_tradeadditem(struct map_session_data *sd, short index, short amount)
}
trade_weight = sd->inventory_data[index]->weight * amount;
- if( target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight )
- { //fail to add item -- the player was over weighted.
+ if (target_sd->weight + sd->deal.weight + trade_weight > target_sd->max_weight) {
+ //fail to add item -- the player was over weighted.
clif->tradeitemok(sd, index+2, TIO_OVERWEIGHT);
return;
}
- if( sd->deal.item[trade_i].index == index )
- { //The same item as before is being readjusted.
- if( sd->deal.item[trade_i].amount + amount > sd->status.inventory[index].amount )
- { //packet deal exploit check
+ if (sd->deal.item[trade_i].index == index) {
+ //The same item as before is being readjusted.
+ if (sd->deal.item[trade_i].amount + amount > sd->status.inventory[index].amount) {
+ //packet deal exploit check
amount = sd->status.inventory[index].amount - sd->deal.item[trade_i].amount;
trade_weight = sd->inventory_data[index]->weight * amount;
}
sd->deal.item[trade_i].amount += amount;
- }
- else
- { //New deal item
+ } else {
+ //New deal item
sd->deal.item[trade_i].index = index;
sd->deal.item[trade_i].amount = amount;
}
@@ -427,8 +427,8 @@ void trade_tradeaddzeny(struct map_session_data* sd, int amount)
return;
}
- if( amount < 0 || amount > sd->status.zeny || amount > MAX_ZENY - target_sd->status.zeny )
- { // invalid values, no appropriate packet for it => abort
+ if (amount < 0 || amount > sd->status.zeny || amount > MAX_ZENY - target_sd->status.zeny) {
+ // invalid values, no appropriate packet for it => abort
trade->cancel(sd);
return;
}
@@ -606,8 +606,7 @@ void trade_tradecommit(struct map_session_data *sd) {
clif->tradecompleted(tsd, 0);
// save both player to avoid crash: they always have no advantage/disadvantage between the 2 players
- if (map->save_settings&1)
- {
+ if (map->save_settings&1) {
chrif->save(sd,0);
chrif->save(tsd,0);
}
@@ -616,7 +615,7 @@ void trade_tradecommit(struct map_session_data *sd) {
void trade_defaults(void)
{
trade = &trade_s;
-
+
trade->request = trade_traderequest;
trade->ack = trade_tradeack;
trade->check_impossible = impossible_trade_check;
diff --git a/src/map/unit.c b/src/map/unit.c
index af0c0a948..a5bd282a9 100644
--- a/src/map/unit.c
+++ b/src/map/unit.c
@@ -95,9 +95,18 @@ 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;
+#ifdef OFFICIAL_WALKPATH
+ if( !path->search_long(NULL, bl->m, bl->x, bl->y, ud->to_x, ud->to_y, CELL_CHKNOPASS) // Check if there is an obstacle between
+ && wpd.path_len > 14 // Official number of walkable cells is 14 if and only if there is an obstacle between. [malufett]
+ && (bl->type != BL_NPC) ) // If type is a NPC, please disregard.
+ return 0;
+#endif
+
memcpy(&ud->walkpath,&wpd,sizeof(wpd));
if (ud->target_to && ud->chaserange>1) {
@@ -106,11 +115,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 +146,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 +257,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);
@@ -205,7 +309,7 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
if (bl->prev == NULL) //Script could have warped char, abort remaining of the function.
return 0;
} else
- sd->areanpc_id=0;
+ npc->untouch_areanpc(sd, bl->m, x, y);
if( sd->md ) { // mercenary should be warped after being 3 seconds too far from the master [greenbox]
if( !check_distance_bl(&sd->bl, &sd->md->bl, MAX_MER_DISTANCE) ) {
@@ -217,7 +321,6 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
}
} else // reset the tick, he is not far anymore
sd->md->masterteleport_timer = 0;
-
}
if( sd->hd ) {
if( homun_alive(sd->hd) && !check_distance_bl(&sd->bl, &sd->hd->bl, MAX_MER_DISTANCE) ) {
@@ -231,6 +334,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
@@ -238,12 +343,15 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
if (md->min_chase > md->db->range3) md->min_chase--;
//Walk skills are triggered regardless of target due to the idle-walk mob state.
//But avoid triggering on stop-walk calls.
- if(tid != INVALID_TIMER &&
- !(ud->walk_count%WALK_SKILL_INTERVAL) &&
- mob->skill_use(md, tick, -1))
- {
- if (!(ud->skill_id == NPC_SELFDESTRUCTION && ud->skilltimer != INVALID_TIMER))
- { //Skill used, abort walking
+ 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)
+ && 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,8 +383,29 @@ 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(ud->state.change_walk_target)
- return unit->walktoxy_sub(bl);
+ //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) {
+ if(unit->walktoxy_sub(bl)) {
+ return 1;
+ } else {
+ clif->fixpos(bl);
+ return 0;
+ }
+ }
ud->walkpath.path_pos++;
if(ud->walkpath.path_pos>=ud->walkpath.path_len)
@@ -294,7 +423,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)) {
@@ -308,21 +437,31 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) {
}
if (tbl->m == bl->m && check_distance_bl(bl, tbl, ud->chaserange)) {
//Reached destination.
- if (ud->state.attack_continue)
- { //Aegis uses one before every attack, we should
+ if (ud->state.attack_continue) {
+ //Aegis uses one before every attack, we should
//only need this one for syncing purposes. [Skotlex]
ud->target_to = 0;
clif->fixpos(bl);
unit->attack(bl, tbl->id, ud->state.attack_continue);
}
} else { //Update chase-path
- unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue?2:0));
+ unit->walktobl(bl, tbl, ud->chaserange, ud->state.walk_easy|(ud->state.attack_continue? 1 : 0));
return 0;
}
} else {
//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 +479,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 +492,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 +520,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 +537,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);
}
@@ -430,8 +568,8 @@ int unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) {
// if flag&2, start attacking upon arrival within range, otherwise just walk to that character.
int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int flag)
{
- struct unit_data *ud = NULL;
- struct status_change *sc = NULL;
+ struct unit_data *ud = NULL;
+ struct status_change *sc = NULL;
nullpo_ret(bl);
nullpo_ret(tbl);
@@ -447,13 +585,17 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
ud->to_y = bl->y;
ud->target_to = 0;
return 0;
+ } else if (range == 0) {
+ //Should walk on the same cell as target (for looters)
+ ud->to_x = tbl->x;
+ ud->to_y = tbl->y;
}
ud->state.walk_easy = flag&1;
ud->target_to = tbl->id;
ud->chaserange = range; //Note that if flag&2, this SHOULD be attack-range
ud->state.attack_continue = flag&2?1:0; //Chase to attack.
- unit->set_target(ud, 0);
+ 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
@@ -465,8 +607,8 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int
return 1;
}
- if(DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0)
- { //Can't move, wait a bit before invoking the movement.
+ if (DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0) {
+ //Can't move, wait a bit before invoking the movement.
timer->add(ud->canmove_tick+1, unit->walktobl_sub, bl->id, ud->target);
return 1;
}
@@ -474,11 +616,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 +685,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, 0x2) )
break;
to_x += dir_x;
@@ -630,7 +767,7 @@ int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool
if (bl->prev == NULL) //Script could have warped char, abort remaining of the function.
return 0;
} else
- sd->areanpc_id=0;
+ npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);
if( sd->status.pet_id > 0 && sd->pd && sd->pd->pet.intimate > 0 )
{ // Check if pet needs to be teleported. [Skotlex]
@@ -666,7 +803,7 @@ int unit_setdir(struct block_list *bl,unsigned char dir)
uint8 unit_getdir(struct block_list *bl) {
struct unit_data *ud;
nullpo_ret(bl);
-
+
if( bl->type == BL_NPC )
return ((TBL_NPC*)bl)->dir;
ud = unit->bl2ud(bl);
@@ -700,6 +837,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;
}
@@ -729,7 +867,7 @@ int unit_blown(struct block_list* bl, int dx, int dy, int count, int flag)
if(map->getcell(bl->m, bl->x, bl->y, CELL_CHKNPC)) {
npc->touch_areanpc(sd, bl->m, bl->x, bl->y);
} else {
- sd->areanpc_id = 0;
+ npc->untouch_areanpc(sd, bl->m, bl->x, bl->y);;
}
}
}
@@ -930,7 +1068,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 +1077,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)
@@ -956,7 +1093,6 @@ int unit_can_move(struct block_list *bl) {
)
)
return 0;
-
if (sc->opt1 > 0 && sc->opt1 != OPT1_STONEWAIT && sc->opt1 != OPT1_BURNING && !(sc->opt1 == OPT1_CRYSTALIZE && bl->type == BL_MOB))
return 0;
@@ -965,6 +1101,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,25 +1147,26 @@ 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) {
+ //Bosses can ignore skill induced walkdelay (but not damage induced)
+ if(bl->type == BL_MOB && (((TBL_MOB*)bl)->status.mode&MD_BOSS))
+ return 0;
+ //Make sure walk delay is not decreased
if (DIFF_TICK(ud->canmove_tick, tick+delay) > 0)
return 0;
} else {
//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)
- { //Stop walking, if chasing, readjust timers.
- if (delay == 1)
- { //Minimal delay (walk-delay) disabled. Just stop walking.
+ if (ud->walktimer != INVALID_TIMER) {
+ //Stop walking, if chasing, readjust timers.
+ if (delay == 1) {
+ //Minimal delay (walk-delay) disabled. Just stop walking.
unit->stop_walking(bl,4);
} else {
//Resume running after can move again [Kevin]
@@ -1028,7 +1176,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);
}
@@ -1086,7 +1234,8 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if(skill->not_ok(skill_id, sd)) // [MouseJstr]
return 0;
- switch(skill_id) { //Check for skills that auto-select target
+ switch (skill_id) {
+ //Check for skills that auto-select target
case MO_CHAINCOMBO:
if (sc && sc->data[SC_BLADESTOP]) {
if ((target=map->id2bl(sc->data[SC_BLADESTOP]->val4)) == NULL)
@@ -1103,6 +1252,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;
@@ -1138,33 +1298,48 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if(!status->check_skilluse(src, target, skill_id, 0))
return 0;
+ if( src != target && status->isdead(target) ) {
+ /**
+ * Skills that may be cast on dead targets
+ **/
+ switch( skill_id ) {
+ case NPC_WIDESOULDRAIN:
+ case PR_REDEMPTIO:
+ case ALL_RESURRECTION:
+ case WM_DEADHILLHERE:
+ break;
+ default:
+ return 1;
+ }
+ }
+
tstatus = status->get_status_data(target);
// Record the status of the previous skill)
- if(sd) {
+ if (sd) {
- if( (skill->get_inf2(skill_id)&INF2_ENSEMBLE_SKILL) && skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1 ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if ((skill->get_inf2(skill_id)&INF2_ENSEMBLE_SKILL) && skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
return 0;
}
-
- switch(skill_id){
+
+ switch (skill_id){
case SA_CASTCANCEL:
- if(ud->skill_id != skill_id){
+ if (ud->skill_id != skill_id){
sd->skill_id_old = ud->skill_id;
sd->skill_lv_old = ud->skill_lv;
}
break;
case BD_ENCORE:
//Prevent using the dance skill if you no longer have the skill in your tree.
- if(!sd->skill_id_dance || pc->checkskill(sd,sd->skill_id_dance)<=0){
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ if (!sd->skill_id_dance || pc->checkskill(sd, sd->skill_id_dance) <= 0){
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
return 0;
}
sd->skill_id_old = skill_id;
break;
case WL_WHITEIMPRISON:
- if( battle->check_target(src,target,BCT_SELF|BCT_ENEMY) < 0 ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0);
+ if (battle->check_target(src, target, BCT_SELF | BCT_ENEMY) < 0) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0);
return 0;
}
break;
@@ -1175,13 +1350,20 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
sd->skill_lv_old = skill_lv;
break;
}
- /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
+ }
+
+ if (sd || src->type == BL_HOM){
+ if (!sd && (target = battle->get_master(src)))
+ sd = map->id2sd(target->id);
+ if (sd){
+ /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */
#if 0
- if ( sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv) )
+ if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv))
#else
- if ( !skill->check_condition_castbegin(sd, skill_id, skill_lv) )
+ if (!skill->check_condition_castbegin(sd, skill_id, skill_lv))
#endif
- return 0;
+ return 0;
+ }
}
if( src->type == BL_MOB )
@@ -1198,6 +1380,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) ) {
@@ -1241,6 +1435,25 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
casttime = -1;
temp = 1;
break;
+ case CR_DEVOTION:
+ if (sd) {
+ int i = 0, count = min(skill_lv, 5);
+ ARR_FIND(0, count, i, sd->devotion[i] == target_id);
+ if (i == count) {
+ ARR_FIND(0, count, i, sd->devotion[i] == 0);
+ if(i == count) {
+ clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0);
+ return 0; // Can't cast on other characters when limit is reached
+ }
+ }
+ }
+ 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] &&
@@ -1277,7 +1490,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
case RA_WUGDASH:
if (sc && sc->data[SC_WUGDASH])
casttime = -1;
- break;
+ break;
case EL_WIND_SLASH:
case EL_HURRICANE:
case EL_TYPOON_MIS:
@@ -1320,7 +1533,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
/**
* why the if else chain: these 3 status do not stack, so its efficient that way.
**/
- if( sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_id != AS_CLOAKING ) {
+ if( sc->data[SC_CLOAKING] && !(sc->data[SC_CLOAKING]->val4&4) && skill_id != AS_CLOAKING ) {
status_change_end(src, SC_CLOAKING, INVALID_TIMER);
if (!src->prev) return 0; //Warped away!
} else if( sc->data[SC_CLOAKINGEXCEED] && !(sc->data[SC_CLOAKINGEXCEED]->val4&4) && skill_id != GC_CLOAKINGEXCEED ) {
@@ -1328,10 +1541,10 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui
if (!src->prev) return 0;
}
}
-
+
if(!ud->state.running) //need TK_RUN or WUGDASH handler to be done before that, see bugreport:6026
unit->stop_walking(src,1);// even though this is not how official works but this will do the trick. bugreport:6829
-
+
// in official this is triggered even if no cast time.
clif->skillcasting(src, src->id, target_id, 0,0, skill_id, skill->get_ele(skill_id, skill_lv), casttime);
if( casttime > 0 || temp )
@@ -1434,13 +1647,11 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
if( skill->not_ok(skill_id, sd) || !skill->check_condition_castbegin(sd, skill_id, skill_lv) )
return 0;
/**
- * "WHY IS IT HEREE": pneuma cannot be canceled past this point, the client displays the animation even,
- * if we cancel it from nodamage_id, so it has to be here for it to not display the animation.
+ * "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 == AL_PNEUMA && map->getcell(src->m, skill_x, skill_y, CELL_CHKLANDPROTECTOR) ) {
- clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0);
+ 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))
@@ -1452,7 +1663,7 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
return 0;
}
- /* Check range and obstacle */
+ /* Check range and obstacle */
bl.type = BL_NUL;
bl.m = src->m;
bl.x = skill_x;
@@ -1463,10 +1674,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);
@@ -1486,14 +1711,14 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui
ud->state.skillcastcancel = castcancel&&casttime>0?1:0;
if( !sd || sd->skillitem != skill_id || skill->get_cast(skill_id,skill_lv) )
ud->canact_tick = tick + casttime + 100;
-// if( sd )
-// {
-// switch( skill_id )
-// {
-// case ????:
-// sd->canequip_tick = tick + casttime;
-// }
-// }
+#if 0
+ if (sd) {
+ switch (skill_id) {
+ case ????:
+ sd->canequip_tick = tick + casttime;
+ }
+ }
+#endif // 0
ud->skill_id = skill_id;
ud->skill_lv = skill_lv;
ud->skillx = skill_x;
@@ -1548,18 +1773,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);
+
+ if(ud->attacktimer == INVALID_TIMER)
+ return;
- timer->delete( ud->attacktimer, unit->attack_timer );
+ //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.
@@ -1568,6 +1826,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);
}
@@ -1585,6 +1844,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));
@@ -1613,19 +1873,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]
@@ -1710,7 +1981,7 @@ bool unit_can_reach_bl(struct block_list *bl,struct block_list *tbl, int range,
/*==========================================
* Calculates position of Pet/Mercenary/Homunculus/Elemental
*------------------------------------------*/
-int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
+int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir)
{
int dx, dy, x, y, i, k;
struct unit_data *ud = unit->bl2ud(bl);
@@ -1827,15 +2098,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) ) {
@@ -1857,10 +2132,17 @@ 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;
- if (sstatus->mode&MD_ASSIST && DIFF_TICK(md->last_linktime, tick) < MIN_MOBLINKTIME)
- { // Link monsters nearby [Skotlex]
+ //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;
map->foreachinrange(mob->linksearch, src, md->db->range2, BL_MOB, md->class_, target, tick);
}
@@ -1882,7 +2164,7 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) {
return 1;
ud->attackabletime = tick + sstatus->adelay;
-// You can't move if you can't attack neither.
+ // You can't move if you can't attack neither.
if (src->type&battle_config.attack_walk_delay)
unit->set_walkdelay(src, tick, sstatus->amotion, 1);
}
@@ -1927,8 +2209,8 @@ int unit_skillcastcancel(struct block_list *bl,int type)
if (!ud->state.skillcastcancel)
return 0;
- if (sd && (sd->special_state.no_castcancel2 ||
- ( sd->special_state.no_castcancel && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89]
+ if (sd && (sd->special_state.no_castcancel2
+ || (sd->special_state.no_castcancel && !map_flag_gvg(bl->m) && !map->list[bl->m].flag.battleground))) //fixed flags being read the wrong way around [blackhole89]
return 0;
}
@@ -1975,6 +2257,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();
@@ -2040,15 +2323,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.
@@ -2172,7 +2459,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;
}
@@ -2267,10 +2554,10 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i
void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype)
{
unit->remove_map(&sd->bl,clrtype,ALC_MARK);
-
+
//CLR_RESPAWN is the warp from logging out, CLR_TELEPORT is the warp from teleporting, but pets/homunc need to just 'vanish' instead of showing the warping animation.
if (clrtype == CLR_RESPAWN || clrtype == CLR_TELEPORT) clrtype = CLR_OUTSIGHT;
-
+
if(sd->pd)
unit->remove_map(&sd->pd->bl, clrtype, ALC_MARK);
if(homun_alive(sd->hd))
@@ -2299,7 +2586,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
nullpo_ret(ud);
map->freeblock_lock();
- if( bl->prev ) //Players are supposed to logout with a "warp" effect.
+ if( bl->prev ) //Players are supposed to logout with a "warp" effect.
unit->remove_map(bl, clrtype, ALC_MARK);
switch( bl->type ) {
@@ -2310,7 +2597,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
unsigned int k;
sd->state.loggingout = 1;
-
+
if( status->isdead(bl) )
pc->setrestartvalue(sd,2);
@@ -2332,8 +2619,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
pc->cleareventtimer(sd);
pc->inventory_rental_clear(sd);
pc->delspiritball(sd,sd->spiritball,1);
- for(i = 1; i < 5; i++)
- pc->del_charm(sd, sd->charm[i], i);
+ for(i = SPIRITS_TYPE_CHARM_WATER; i < SPIRITS_TYPE_SPHERE; i++)
+ pc->del_charm(sd, sd->spiritcharm[i], i);
if( sd->st && sd->st->state != RUN ) {// free attached scripts that are waiting
script->free_state(sd->st);
@@ -2369,7 +2656,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
sd->quest_log = NULL;
sd->num_quests = sd->avail_quests = 0;
}
-
+
for( k = 0; k < sd->hdatac; k++ ) {
if( sd->hdata[k]->flag.free ) {
aFree(sd->hdata[k]->data);
@@ -2393,10 +2680,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
if( pd->s_skill )
{
if (pd->s_skill->timer != INVALID_TIMER) {
- if (pd->s_skill->id)
- timer->delete(pd->s_skill->timer, pet->skill_support_timer);
- else
- timer->delete(pd->s_skill->timer, pet->heal_timer);
+ timer->delete(pd->s_skill->timer, pet->skill_support_timer);
}
aFree(pd->s_skill);
pd->s_skill = NULL;
@@ -2423,10 +2707,10 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
aFree (pd->loot);
pd->loot = NULL;
}
- if( pd->pet.intimate > 0 )
+ if (pd->pet.intimate > 0) {
intif->save_petdata(pd->pet.account_id,&pd->pet);
- else
- { //Remove pet.
+ } else {
+ //Remove pet.
intif->delete_petdata(pd->pet.pet_id);
if (sd) sd->status.pet_id = 0;
}
@@ -2436,6 +2720,7 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
}
case BL_MOB:
{
+ unsigned int k;
struct mob_data *md = (struct mob_data*)bl;
if( md->spawn_timer != INVALID_TIMER )
{
@@ -2490,6 +2775,15 @@ int unit_free(struct block_list *bl, clr_type clrtype) {
mob->clone_delete(md);
if( md->tomb_nid )
mob->mvptomb_destroy(md);
+
+ for (k = 0; k < md->hdatac; k++) {
+ if( md->hdata[k]->flag.free ) {
+ aFree(md->hdata[k]->data);
+ }
+ aFree(md->hdata[k]);
+ }
+ if (md->hdata)
+ aFree(md->hdata);
break;
}
case BL_HOM:
@@ -2561,6 +2855,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;
}
@@ -2571,7 +2866,7 @@ int do_final_unit(void) {
void unit_defaults(void) {
unit = &unit_s;
-
+
unit->init = do_init_unit;
unit->final = do_final_unit;
/* */
@@ -2594,6 +2889,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/map/vending.c b/src/map/vending.c
index 7e9393bf2..bd61d482f 100644
--- a/src/map/vending.c
+++ b/src/map/vending.c
@@ -134,11 +134,11 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
clif->buyvending(sd, idx, amount, 2); // you can not buy, because overweight
return;
}
-
+
//Check to see if cart/vend info is in sync.
if( vend[j].amount > vsd->status.cart[idx].amount )
vend[j].amount = vsd->status.cart[idx].amount;
-
+
// if they try to add packets (example: get twice or more 2 apples if marchand has only 3 apples).
// here, we check cumulative amounts
if( vend[j].amount < amount ) {
@@ -146,12 +146,12 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
clif->buyvending(sd, idx, vsd->vending[j].amount, 4); // not enough quantity
return;
}
-
+
vend[j].amount -= amount;
switch( pc->checkadditem(sd, vsd->status.cart[idx].nameid, amount) ) {
case ADDITEM_EXIST:
- break; //We'd add this item to the existing one (in buyers inventory)
+ break; //We'd add this item to the existing one (in buyers inventory)
case ADDITEM_NEW:
new_++;
if (new_ > blank)
@@ -190,7 +190,7 @@ void vending_purchasereq(struct map_session_data* sd, int aid, unsigned int uid,
for( i = 0, cursor = 0; i < vsd->vend_num; i++ ) {
if( vsd->vending[i].amount == 0 )
continue;
-
+
if( cursor != i ) { // speedup
vsd->vending[cursor].index = vsd->vending[i].index;
vsd->vending[cursor].amount = vsd->vending[i].amount;
@@ -245,7 +245,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
clif->skill_fail(sd, MC_VENDING, USESKILL_FAIL_LEVEL, 0);
return;
}
-
+
// filter out invalid items
i = 0;
for( j = 0; j < count; j++ ) {
@@ -256,13 +256,13 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
index -= 2; // offset adjustment (client says that the first cart position is 2)
if( index < 0 || index >= MAX_CART // invalid position
- || pc->cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
+ || pc->cartitem_amount(sd, index, amount) < 0 // invalid item or insufficient quantity
//NOTE: official server does not do any of the following checks!
- || !sd->status.cart[index].identify // unidentified item
- || sd->status.cart[index].attribute == 1 // broken item
- || sd->status.cart[index].expire_time // It should not be in the cart but just in case
- || (sd->status.cart[index].bound && !pc_can_give_bound_items(sd)) // can't trade bound items w/o permission
- || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
+ || !sd->status.cart[index].identify // unidentified item
+ || sd->status.cart[index].attribute == 1 // broken item
+ || sd->status.cart[index].expire_time // It should not be in the cart but just in case
+ || (sd->status.cart[index].bound && !pc_can_give_bound_items(sd)) // can't trade bound items w/o permission
+ || !itemdb_cantrade(&sd->status.cart[index], pc_get_group_level(sd), pc_get_group_level(sd)) ) // untradeable item
continue;
sd->vending[i].index = index;
@@ -287,7 +287,7 @@ void vending_openvending(struct map_session_data* sd, const char* message, const
clif->openvending(sd,sd->bl.id,sd->vending);
clif->showvendingboard(&sd->bl,message,0);
-
+
idb_put(vending->db, sd->status.char_id, sd);
}
@@ -372,10 +372,10 @@ void init(bool minimal) {
void vending_defaults(void) {
vending = &vending_s;
-
+
vending->init = init;
vending->final = final;
-
+
vending->close = vending_closevending;
vending->open = vending_openvending;
vending->list = vending_vendinglistreq;