Compare commits
10 Commits
master
...
hotfix/iss
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1e01f6448f | ||
![]() |
42eccbb1bf | ||
![]() |
50bd9cdfbe | ||
![]() |
5676a45908 | ||
![]() |
1c1bb9892c | ||
![]() |
c951f68250 | ||
![]() |
9440ba8929 | ||
![]() |
9ff252d2b1 | ||
![]() |
7a345b85cb | ||
![]() |
da8d77bfc1 |
@ -940,6 +940,8 @@ CREATE TABLE IF NOT EXISTS `sc_data` (
|
|||||||
`char_id` int(11) unsigned NOT NULL,
|
`char_id` int(11) unsigned NOT NULL,
|
||||||
`type` smallint(11) unsigned NOT NULL,
|
`type` smallint(11) unsigned NOT NULL,
|
||||||
`tick` bigint(20) NOT NULL,
|
`tick` bigint(20) NOT NULL,
|
||||||
|
`tick_total` bigint(20) NOT NULL,
|
||||||
|
`tick_time` bigint(20) NOT NULL,
|
||||||
`val1` int(11) NOT NULL default '0',
|
`val1` int(11) NOT NULL default '0',
|
||||||
`val2` int(11) NOT NULL default '0',
|
`val2` int(11) NOT NULL default '0',
|
||||||
`val3` int(11) NOT NULL default '0',
|
`val3` int(11) NOT NULL default '0',
|
||||||
|
5
sql-files/upgrades/upgrade_20200803.sql
Normal file
5
sql-files/upgrades/upgrade_20200803.sql
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
ALTER TABLE `sc_data` ADD COLUMN `tick_total` BIGINT(20) NOT NULL AFTER `tick`;
|
||||||
|
UPDATE `sc_data` SET `tick_total` = `tick`;
|
||||||
|
|
||||||
|
ALTER TABLE `sc_data` ADD COLUMN `tick_time` BIGINT(20) NOT NULL AFTER `tick_total`;
|
||||||
|
UPDATE `sc_data` SET `tick_time` = `tick`;
|
@ -2385,7 +2385,7 @@ bool char_checkdb(void){
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
//checking scdata_db
|
//checking scdata_db
|
||||||
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`type`,`tick`,`val1`,`val2`,`val3`,`val4`"
|
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT `account_id`,`char_id`,`type`,`tick`,`tick_total`,`tick_time`,`val1`,`val2`,`val3`,`val4`"
|
||||||
" FROM `%s` LIMIT 1;", schema_config.scdata_db) ){
|
" FROM `%s` LIMIT 1;", schema_config.scdata_db) ){
|
||||||
Sql_ShowDebug(sql_handle);
|
Sql_ShowDebug(sql_handle);
|
||||||
return false;
|
return false;
|
||||||
|
@ -284,7 +284,7 @@ int chmapif_parse_askscdata(int fd){
|
|||||||
int aid, cid;
|
int aid, cid;
|
||||||
aid = RFIFOL(fd,2);
|
aid = RFIFOL(fd,2);
|
||||||
cid = RFIFOL(fd,6);
|
cid = RFIFOL(fd,6);
|
||||||
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4 from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
|
if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4, tick_total, tick_time from `%s` WHERE `account_id` = '%d' AND `char_id`='%d'",
|
||||||
schema_config.scdata_db, aid, cid) )
|
schema_config.scdata_db, aid, cid) )
|
||||||
{
|
{
|
||||||
Sql_ShowDebug(sql_handle);
|
Sql_ShowDebug(sql_handle);
|
||||||
@ -308,6 +308,8 @@ int chmapif_parse_askscdata(int fd){
|
|||||||
Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data);
|
Sql_GetData(sql_handle, 3, &data, NULL); scdata.val2 = atoi(data);
|
||||||
Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data);
|
Sql_GetData(sql_handle, 4, &data, NULL); scdata.val3 = atoi(data);
|
||||||
Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data);
|
Sql_GetData(sql_handle, 5, &data, NULL); scdata.val4 = atoi(data);
|
||||||
|
Sql_GetData(sql_handle, 6, &data, NULL); scdata.tick_total = strtoll(data, nullptr, 10);
|
||||||
|
Sql_GetData(sql_handle, 7, &data, NULL); scdata.tick_time = strtoll(data, nullptr, 10);
|
||||||
memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data));
|
memcpy(WFIFOP(fd, 14+count*sizeof(struct status_change_data)), &scdata, sizeof(struct status_change_data));
|
||||||
}
|
}
|
||||||
if (count >= 50)
|
if (count >= 50)
|
||||||
@ -958,14 +960,14 @@ int chmapif_parse_save_scdata(int fd){
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
StringBuf_Init(&buf);
|
StringBuf_Init(&buf);
|
||||||
StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `val1`, `val2`, `val3`, `val4`) VALUES ", schema_config.scdata_db);
|
StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `tick_total`, `tick_time`, `val1`, `val2`, `val3`, `val4`) VALUES ", schema_config.scdata_db);
|
||||||
for( i = 0; i < count; ++i )
|
for( i = 0; i < count; ++i )
|
||||||
{
|
{
|
||||||
memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data));
|
memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data));
|
||||||
if( i > 0 )
|
if( i > 0 )
|
||||||
StringBuf_AppendStr(&buf, ", ");
|
StringBuf_AppendStr(&buf, ", ");
|
||||||
StringBuf_Printf(&buf, "('%d','%d','%hu','%" PRtf "','%ld','%ld','%ld','%ld')", aid, cid,
|
StringBuf_Printf(&buf, "('%d','%d','%hu','%" PRtf "','%" PRtf "','%" PRtf "','%ld','%ld','%ld','%ld')", aid, cid,
|
||||||
data.type, data.tick, data.val1, data.val2, data.val3, data.val4);
|
data.type, data.tick, data.tick_total, data.tick_time, data.val1, data.val2, data.val3, data.val4);
|
||||||
}
|
}
|
||||||
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
|
if( SQL_ERROR == Sql_QueryStr(sql_handle, StringBuf_Value(&buf)) )
|
||||||
Sql_ShowDebug(sql_handle);
|
Sql_ShowDebug(sql_handle);
|
||||||
|
@ -408,6 +408,8 @@ struct status_change_data {
|
|||||||
unsigned short type; //SC_type
|
unsigned short type; //SC_type
|
||||||
long val1, val2, val3, val4;
|
long val1, val2, val3, val4;
|
||||||
t_tick tick; //Remaining duration.
|
t_tick tick; //Remaining duration.
|
||||||
|
t_tick tick_total; // Total duration
|
||||||
|
t_tick tick_time; // Interval duration
|
||||||
};
|
};
|
||||||
|
|
||||||
#define MAX_BONUS_SCRIPT_LENGTH 512
|
#define MAX_BONUS_SCRIPT_LENGTH 512
|
||||||
|
@ -1318,6 +1318,15 @@ int chrif_save_scdata(map_session_data *sd) { //parses the sc_data of the player
|
|||||||
data.tick = 0; //Negative tick does not necessarily mean that sc has expired
|
data.tick = 0; //Negative tick does not necessarily mean that sc has expired
|
||||||
} else
|
} else
|
||||||
data.tick = INFINITE_TICK; //Infinite duration
|
data.tick = INFINITE_TICK; //Infinite duration
|
||||||
|
if (sce->tick_timer != INVALID_TIMER) {
|
||||||
|
timer = get_timer(sce->tick_timer);
|
||||||
|
if (timer == nullptr || timer->func != status_change_tick_timer)
|
||||||
|
continue;
|
||||||
|
if (DIFF_TICK(timer->tick, tick) >= 0)
|
||||||
|
data.tick_time = DIFF_TICK(timer->tick, tick);
|
||||||
|
} else
|
||||||
|
data.tick_time = 0;
|
||||||
|
data.tick_total = sce->tick_total;
|
||||||
data.type = i;
|
data.type = i;
|
||||||
data.val1 = sce->val1;
|
data.val1 = sce->val1;
|
||||||
data.val2 = sce->val2;
|
data.val2 = sce->val2;
|
||||||
@ -1401,7 +1410,7 @@ int chrif_load_scdata(int fd) {
|
|||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
struct status_change_data *data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
|
struct status_change_data *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, SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_LOADED|SCSTART_NORATEDEF);
|
status_change_start_sub(NULL,&sd->bl, (sc_type)data->type, 10000, data->val1, data->val2, data->val3, data->val4, data->tick, data->tick_total, data->tick_time, SCSTART_NOAVOID|SCSTART_NOTICKDEF|SCSTART_LOADED|SCSTART_NORATEDEF);
|
||||||
}
|
}
|
||||||
|
|
||||||
pc_scdata_received(sd);
|
pc_scdata_received(sd);
|
||||||
|
192
src/map/clif.cpp
192
src/map/clif.cpp
@ -6464,87 +6464,26 @@ void clif_cooking_list( map_session_data *sd, int trigger, uint16 skill_id, int
|
|||||||
/// 0196 <index>.W <id>.L <state>.B (ZC_MSG_STATE_CHANGE) [used for ending status changes and starting them on non-pc units (when needed)]
|
/// 0196 <index>.W <id>.L <state>.B (ZC_MSG_STATE_CHANGE) [used for ending status changes and starting them on non-pc units (when needed)]
|
||||||
/// 043f <index>.W <id>.L <state>.B <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE2) [used exclusively for starting statuses on pcs]
|
/// 043f <index>.W <id>.L <state>.B <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE2) [used exclusively for starting statuses on pcs]
|
||||||
/// 0983 <index>.W <id>.L <state>.B <total msec>.L <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE3) (PACKETVER >= 20120618)
|
/// 0983 <index>.W <id>.L <state>.B <total msec>.L <remain msec>.L { <val>.L }*3 (ZC_MSG_STATE_CHANGE3) (PACKETVER >= 20120618)
|
||||||
/// @param bl Sends packet to clients around this object
|
/// @param bl: Sends packet to clients around this object
|
||||||
/// @param id ID of object that has this effect
|
/// @param id: ID of object that has this effect
|
||||||
/// @param type Status icon see enum efst_type
|
/// @param type: Status icon (see efst_types)
|
||||||
/// @param flag 1:Active, 0:Deactive
|
/// @param flag: 1:Active, 0:Inactive
|
||||||
/// @param tick Duration in ms
|
/// @param tick_total: Total duration in ms
|
||||||
/// @param val1
|
/// @param tick: Remaining duration in ms
|
||||||
/// @param val2
|
/// @param val1: Value 1
|
||||||
/// @param val3
|
/// @param val2: Value 2
|
||||||
void clif_status_change_sub(struct block_list *bl, int id, int type, int flag, t_tick tick, int val1, int val2, int val3, enum send_target target_type)
|
/// @param val3: Value 3
|
||||||
|
void clif_status_change_sub(struct block_list *bl, int id, int type, int flag, t_tick tick_total, t_tick tick, int val1, int val2, int val3)
|
||||||
{
|
{
|
||||||
unsigned char buf[32];
|
|
||||||
|
|
||||||
if (type == EFST_BLANK) //It shows nothing on the client...
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (type == EFST_POSTDELAY && tick == 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
nullpo_retv(bl);
|
nullpo_retv(bl);
|
||||||
|
|
||||||
// Statuses with an infinite duration, but still needs a duration sent to display properly.
|
|
||||||
if (type == EFST_LUNARSTANCE || type == EFST_UNIVERSESTANCE || type == EFST_SUNSTANCE || type == EFST_STARSTANCE)
|
|
||||||
tick = 200;
|
|
||||||
|
|
||||||
#if PACKETVER >= 20120618
|
|
||||||
if (flag && battle_config.display_status_timers)
|
|
||||||
WBUFW(buf,0) = 0x983;
|
|
||||||
else
|
|
||||||
#elif PACKETVER >= 20090121
|
|
||||||
if (flag && battle_config.display_status_timers)
|
|
||||||
WBUFW(buf,0) = 0x43f;
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
WBUFW(buf,0) = 0x196;
|
|
||||||
WBUFW(buf,2) = type;
|
|
||||||
WBUFL(buf,4) = id;
|
|
||||||
WBUFB(buf,8) = flag;
|
|
||||||
#if PACKETVER >= 20120618
|
|
||||||
if (flag && battle_config.display_status_timers) {
|
|
||||||
if (tick <= 0)
|
|
||||||
tick = 9999; // this is indeed what official servers do
|
|
||||||
|
|
||||||
WBUFL(buf,9) = client_tick(tick);/* at this stage remain and total are the same value I believe */
|
|
||||||
WBUFL(buf,13) = client_tick(tick);
|
|
||||||
WBUFL(buf,17) = val1;
|
|
||||||
WBUFL(buf,21) = val2;
|
|
||||||
WBUFL(buf,25) = val3;
|
|
||||||
}
|
|
||||||
#elif PACKETVER >= 20090121
|
|
||||||
if (flag && battle_config.display_status_timers) {
|
|
||||||
if (tick <= 0)
|
|
||||||
tick = 9999; // this is indeed what official servers do
|
|
||||||
|
|
||||||
WBUFL(buf,9) = client_tick(tick);
|
|
||||||
WBUFL(buf,13) = val1;
|
|
||||||
WBUFL(buf,17) = val2;
|
|
||||||
WBUFL(buf,21) = val3;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
clif_send(buf, packet_len(WBUFW(buf,0)), bl, target_type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Sends status effect to clients around the bl
|
|
||||||
* @param bl Object that has the effect
|
|
||||||
* @param type Status icon see enum efst_type
|
|
||||||
* @param flag 1:Active, 0:Deactive
|
|
||||||
* @param tick Duration in ms
|
|
||||||
* @param val1
|
|
||||||
* @param val2
|
|
||||||
* @param val3
|
|
||||||
*/
|
|
||||||
void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick, int val1, int val2, int val3) {
|
|
||||||
map_session_data *sd = NULL;
|
|
||||||
|
|
||||||
if (type == EFST_BLANK) //It shows nothing on the client...
|
if (type == EFST_BLANK) //It shows nothing on the client...
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (type == EFST_POSTDELAY && tick == 0)
|
if (type == EFST_POSTDELAY && tick == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (type == EFST_ILLUSION && !battle_config.display_hallucination) // Disable Hallucination.
|
if (!(status_efst_get_bl_type((efst_type)type) & bl->type)) // only send status changes that actually matter to the client
|
||||||
return;
|
return;
|
||||||
|
|
||||||
#if !( PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 )
|
#if !( PACKETVER_MAIN_NUM >= 20191120 || PACKETVER_RE_NUM >= 20191106 )
|
||||||
@ -6553,14 +6492,56 @@ void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick,
|
|||||||
type = EFST_RIDING;
|
type = EFST_RIDING;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nullpo_retv(bl);
|
packet_status_change p = { 0 };
|
||||||
|
map_session_data *sd = BL_CAST(BL_PC, bl);
|
||||||
|
|
||||||
sd = BL_CAST(BL_PC, bl);
|
if (battle_config.display_status_timers > 0) {
|
||||||
|
// Statuses with an infinite duration, but still needs a duration sent to display properly.
|
||||||
|
switch (type) {
|
||||||
|
case EFST_LUNARSTANCE:
|
||||||
|
case EFST_UNIVERSESTANCE:
|
||||||
|
case EFST_SUNSTANCE:
|
||||||
|
case EFST_STARSTANCE:
|
||||||
|
tick = 200;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (tick < 0)
|
||||||
|
tick = 9999; // this is indeed what official servers do
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(status_efst_get_bl_type((efst_type)type)&bl->type)) // only send status changes that actually matter to the client
|
p.PacketType = status_changeType;
|
||||||
return;
|
p.index = type;
|
||||||
|
p.AID = id;
|
||||||
|
p.state = (uint8)flag;
|
||||||
|
|
||||||
clif_status_change_sub(bl, bl->id, type, flag, tick, val1, val2, val3, ((sd ? (pc_isinvisible(sd) ? SELF : AREA) : AREA_WOS)));
|
#if PACKETVER >= 20090121
|
||||||
|
if (battle_config.display_status_timers > 0) {
|
||||||
|
#if PACKETVER >= 20120618
|
||||||
|
p.Total = client_tick(tick);
|
||||||
|
#endif
|
||||||
|
p.Left = client_tick(tick_total);
|
||||||
|
p.val1 = val1;
|
||||||
|
p.val2 = val2;
|
||||||
|
p.val3 = val3;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
clif_send(&p, sizeof(p), bl, pc_isinvisible(sd) ? SELF : AREA);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Sends status effect to clients around the bl
|
||||||
|
* @param bl: Object that has the effect
|
||||||
|
* @param type: Status icon (see efst_types)
|
||||||
|
* @param flag: 1:Active, 0:Inactive
|
||||||
|
* @param tick_total: Total duration in ms
|
||||||
|
* @param val1: Value 1
|
||||||
|
* @param val2: Value 2
|
||||||
|
* @param val3: Value 3
|
||||||
|
*/
|
||||||
|
void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick_total, int val1, int val2, int val3) {
|
||||||
|
clif_status_change_sub(bl, bl->id, type, flag, tick_total, tick_total, val1, val2, val3);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -6570,13 +6551,12 @@ void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick,
|
|||||||
* @param target: Client send type
|
* @param target: Client send type
|
||||||
*/
|
*/
|
||||||
void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target) {
|
void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target) {
|
||||||
unsigned char i;
|
nullpo_retv(bl);
|
||||||
|
|
||||||
struct sc_display_entry **sc_display;
|
struct sc_display_entry **sc_display;
|
||||||
unsigned char sc_display_count;
|
unsigned char sc_display_count;
|
||||||
bool spheres_sent;
|
bool spheres_sent;
|
||||||
|
|
||||||
nullpo_retv(bl);
|
|
||||||
|
|
||||||
switch( bl->type ){
|
switch( bl->type ){
|
||||||
case BL_PC: {
|
case BL_PC: {
|
||||||
map_session_data* sd = (map_session_data*)bl;
|
map_session_data* sd = (map_session_data*)bl;
|
||||||
@ -6598,14 +6578,14 @@ void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < sc_display_count; i++) {
|
for (unsigned char i = 0; i < sc_display_count; i++) {
|
||||||
enum sc_type type = sc_display[i]->type;
|
enum sc_type type = sc_display[i]->type;
|
||||||
status_change *sc = status_get_sc(bl);
|
status_change *sc = status_get_sc(bl);
|
||||||
const struct TimerData *td = (sc && sc->getSCE(type) ? get_timer(sc->getSCE(type)->timer) : NULL);
|
const TimerData *td = (sc && sc->getSCE(type) ? get_timer(sc->getSCE(type)->timer) : nullptr);
|
||||||
t_tick tick = 0;
|
t_tick tick = 0, cur_tick = gettick();
|
||||||
|
|
||||||
if (td)
|
if (td != nullptr)
|
||||||
tick = DIFF_TICK(td->tick, gettick());
|
tick = DIFF_TICK(td->tick, cur_tick);
|
||||||
|
|
||||||
// Status changes that need special handling
|
// Status changes that need special handling
|
||||||
switch( type ){
|
switch( type ){
|
||||||
@ -6626,9 +6606,9 @@ void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl,
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if PACKETVER > 20120418
|
#if PACKETVER > 20120418
|
||||||
clif_efst_status_change(tbl, bl->id, target, status_db.getIcon(type), tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3);
|
clif_efst_status_change(tbl, bl->id, target, status_db.getIcon(type), sc->getSCE(type)->tick_total, tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3);
|
||||||
#else
|
#else
|
||||||
clif_status_change_sub(tbl, bl->id, status_db.getIcon(type), 1, tick, sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3, target);
|
clif_status_change_sub(tbl, bl->id, status_db.getIcon(type), 1, tick, tick sc_display[i]->val1, sc_display[i]->val2, sc_display[i]->val3, target);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6636,38 +6616,30 @@ void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl,
|
|||||||
/// Notifies the client when a player enters the screen with an active EFST.
|
/// Notifies the client when a player enters the screen with an active EFST.
|
||||||
/// 08ff <id>.L <index>.W <remain msec>.L { <val>.L }*3 (ZC_EFST_SET_ENTER) (PACKETVER >= 20111108)
|
/// 08ff <id>.L <index>.W <remain msec>.L { <val>.L }*3 (ZC_EFST_SET_ENTER) (PACKETVER >= 20111108)
|
||||||
/// 0984 <id>.L <index>.W <total msec>.L <remain msec>.L { <val>.L }*3 (ZC_EFST_SET_ENTER2) (PACKETVER >= 20120618)
|
/// 0984 <id>.L <index>.W <total msec>.L <remain msec>.L { <val>.L }*3 (ZC_EFST_SET_ENTER2) (PACKETVER >= 20120618)
|
||||||
void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, t_tick tick, int val1, int val2, int val3) {
|
void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, t_tick tick_total, t_tick tick, int val1, int val2, int val3) {
|
||||||
#if PACKETVER >= 20111108
|
#if PACKETVER >= 20111108
|
||||||
unsigned char buf[32];
|
nullpo_retv(bl);
|
||||||
#if PACKETVER >= 20120618
|
|
||||||
const int cmd = 0x984;
|
|
||||||
#elif PACKETVER >= 20111108
|
|
||||||
const int cmd = 0x8ff;
|
|
||||||
#endif
|
|
||||||
int offset = 0;
|
|
||||||
|
|
||||||
if (type == EFST_BLANK)
|
if (type == EFST_BLANK)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
nullpo_retv(bl);
|
if (tick < 0)
|
||||||
|
|
||||||
if (tick <= 0)
|
|
||||||
tick = 9999;
|
tick = 9999;
|
||||||
|
|
||||||
WBUFW(buf,offset + 0) = cmd;
|
PACKET_EFST_SET_ENTER p = { 0 };
|
||||||
WBUFL(buf,offset + 2) = tid;
|
|
||||||
WBUFW(buf,offset + 6) = type;
|
p.PacketType = HEADER_ZC_EFST_SET_ENTER;
|
||||||
#if PACKETVER >= 20111108
|
p.GID = tid;
|
||||||
WBUFL(buf,offset + 8) = client_tick(tick); // Set remaining status duration [exneval]
|
p.type = type;
|
||||||
|
p.remaining = client_tick(tick);
|
||||||
#if PACKETVER >= 20120618
|
#if PACKETVER >= 20120618
|
||||||
WBUFL(buf,offset + 12) = client_tick(tick);
|
p.total = client_tick(tick_total);
|
||||||
offset += 4;
|
|
||||||
#endif
|
#endif
|
||||||
WBUFL(buf,offset + 12) = val1;
|
p.val1 = val1;
|
||||||
WBUFL(buf,offset + 16) = val2;
|
p.val2 = val2;
|
||||||
WBUFL(buf,offset + 20) = val3;
|
p.val3 = val3;
|
||||||
#endif
|
|
||||||
clif_send(buf,packet_len(cmd),bl,target);
|
clif_send(&p, sizeof(p), bl, target);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -771,8 +771,9 @@ void clif_bladestop(struct block_list *src, int dst_id, int active);
|
|||||||
void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target);
|
void clif_changemapcell(int fd, int16 m, int x, int y, int type, enum send_target target);
|
||||||
|
|
||||||
#define clif_status_load(bl, type, flag) clif_status_change((bl), (type), (flag), 0, 0, 0, 0)
|
#define clif_status_load(bl, type, flag) clif_status_change((bl), (type), (flag), 0, 0, 0, 0)
|
||||||
void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick, int val1, int val2, int val3);
|
void clif_status_change(struct block_list *bl, int type, int flag, t_tick tick_total, int val1, int val2, int val3);
|
||||||
void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, t_tick tick, int val1, int val2, int val3);
|
void clif_status_change_sub(struct block_list *bl, int id, int type, int flag, t_tick tick_total, t_tick tick, int val1, int val2, int val3);
|
||||||
|
void clif_efst_status_change(struct block_list *bl, int tid, enum send_target target, int type, t_tick tick_total, t_tick tick, int val1, int val2, int val3);
|
||||||
void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target);
|
void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl, enum send_target target);
|
||||||
|
|
||||||
void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, int mes_len, int gmlvl);
|
void clif_wis_message(map_session_data* sd, const char* nick, const char* mes, int mes_len, int gmlvl);
|
||||||
|
@ -475,6 +475,19 @@ struct PACKET_ZC_ACK_SE_CASH_ITEM_LIST2{
|
|||||||
struct PACKET_ZC_ACK_SE_CASH_ITEM_LIST2_sub items[];
|
struct PACKET_ZC_ACK_SE_CASH_ITEM_LIST2_sub items[];
|
||||||
} __attribute__((packed));
|
} __attribute__((packed));
|
||||||
|
|
||||||
|
struct PACKET_EFST_SET_ENTER {
|
||||||
|
int16 PacketType;
|
||||||
|
uint32 GID;
|
||||||
|
uint16 type;
|
||||||
|
uint32 remaining;
|
||||||
|
#if PACKETVER >= 20120618
|
||||||
|
uint32 total;
|
||||||
|
#endif
|
||||||
|
int32 val1;
|
||||||
|
int32 val2;
|
||||||
|
int32 val3;
|
||||||
|
};
|
||||||
|
|
||||||
// NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
|
// NetBSD 5 and Solaris don't like pragma pack but accept the packed attribute
|
||||||
#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
|
#if !defined( sun ) && ( !defined( __NETBSD__ ) || __NetBSD_Version__ >= 600000000 )
|
||||||
#pragma pack( pop )
|
#pragma pack( pop )
|
||||||
@ -515,7 +528,13 @@ DEFINE_PACKET_HEADER(CZ_REQ_SE_CASH_TAB_CODE, 0x846)
|
|||||||
DEFINE_PACKET_HEADER(ZC_ACK_SE_CASH_ITEM_LIST2, 0x8c0)
|
DEFINE_PACKET_HEADER(ZC_ACK_SE_CASH_ITEM_LIST2, 0x8c0)
|
||||||
DEFINE_PACKET_HEADER(ZC_ACK_SCHEDULER_CASHITEM, 0x8ca)
|
DEFINE_PACKET_HEADER(ZC_ACK_SCHEDULER_CASHITEM, 0x8ca)
|
||||||
DEFINE_PACKET_HEADER(ZC_CLEAR_DIALOG, 0x8d6)
|
DEFINE_PACKET_HEADER(ZC_CLEAR_DIALOG, 0x8d6)
|
||||||
|
#if PACKETVER >= 20111108 && PACKETVER < 20120618
|
||||||
|
DEFINE_PACKET_HEADER(ZC_EFST_SET_ENTER, 0x8ff)
|
||||||
|
#endif
|
||||||
DEFINE_PACKET_HEADER(ZC_ENTRY_QUEUE_INIT, 0x90e);
|
DEFINE_PACKET_HEADER(ZC_ENTRY_QUEUE_INIT, 0x90e);
|
||||||
|
#if PACKETVER >= 20120618
|
||||||
|
DEFINE_PACKET_HEADER(ZC_EFST_SET_ENTER, 0x984)
|
||||||
|
#endif
|
||||||
DEFINE_PACKET_HEADER(ZC_BANKING_CHECK, 0x9a6)
|
DEFINE_PACKET_HEADER(ZC_BANKING_CHECK, 0x9a6)
|
||||||
DEFINE_PACKET_HEADER(ZC_ACK_BANKING_DEPOSIT, 0x9a8)
|
DEFINE_PACKET_HEADER(ZC_ACK_BANKING_DEPOSIT, 0x9a8)
|
||||||
DEFINE_PACKET_HEADER(ZC_ACK_BANKING_WITHDRAW, 0x9aa)
|
DEFINE_PACKET_HEADER(ZC_ACK_BANKING_WITHDRAW, 0x9aa)
|
||||||
|
@ -12246,7 +12246,8 @@ BUILDIN_FUNC(sc_start)
|
|||||||
TBL_NPC * nd = map_id2nd(st->oid);
|
TBL_NPC * nd = map_id2nd(st->oid);
|
||||||
struct block_list* bl;
|
struct block_list* bl;
|
||||||
enum sc_type type;
|
enum sc_type type;
|
||||||
int tick, val1, val2, val3, val4=0, rate, flag;
|
int val1, val2, val3, val4=0, rate, flag;
|
||||||
|
t_tick tick;
|
||||||
char start_type;
|
char start_type;
|
||||||
const char* command = script_getfuncname(st);
|
const char* command = script_getfuncname(st);
|
||||||
|
|
||||||
@ -12258,7 +12259,7 @@ BUILDIN_FUNC(sc_start)
|
|||||||
start_type = 1;
|
start_type = 1;
|
||||||
|
|
||||||
type = (sc_type)script_getnum(st,2);
|
type = (sc_type)script_getnum(st,2);
|
||||||
tick = script_getnum(st,3);
|
tick = script_getnum64(st,3);
|
||||||
val1 = script_getnum(st,4);
|
val1 = script_getnum(st,4);
|
||||||
|
|
||||||
//If from NPC we make default flag 1 to be unavoidable
|
//If from NPC we make default flag 1 to be unavoidable
|
||||||
|
@ -9846,19 +9846,22 @@ void status_display_remove(struct block_list *bl, enum sc_type type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies SC defense to a given status change
|
* Applies a Status Change for a given amount of time
|
||||||
* This function also determines whether or not the status change will be applied
|
|
||||||
* @param src: Source of the status change [PC|MOB|HOM|MER|ELEM|NPC]
|
* @param src: Source of the status change [PC|MOB|HOM|MER|ELEM|NPC]
|
||||||
* @param bl: Target of the status change (See: enum sc_type)
|
* @param bl: Target of the status change (See: enum sc_type)
|
||||||
* @param type: Status change (SC_*)
|
* @param type: Status change (SC_*)
|
||||||
* @param rate: Initial percentage rate of affecting bl (0~10000)
|
* @param rate: Initial percentage rate of affecting bl (0~10000)
|
||||||
* @param val1~4: Depends on type of status change
|
* @param val1: Depends on type of status change
|
||||||
* @param duration: Initial duration that the status change affects bl
|
* @param val2: Depends on type of status change
|
||||||
|
* @param val3: Depends on type of status change
|
||||||
|
* @param val4: Depends on type of status change
|
||||||
|
* @param duration: Remaining duration
|
||||||
|
* @param duration_total: Initial duration
|
||||||
* @param flag: Value which determines what parts to calculate. See e_status_change_start_flags
|
* @param flag: Value which determines what parts to calculate. See e_status_change_start_flags
|
||||||
* @param delay: Delay in milliseconds before the SC is applied
|
* @param delay: Delay in milliseconds before the SC is applied
|
||||||
* @return adjusted duration based on flag values
|
* @return adjusted duration based on flag values
|
||||||
*/
|
*/
|
||||||
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,t_tick duration,unsigned char flag, int32 delay) {
|
int status_change_start_sub(struct block_list* src, struct block_list* bl,enum sc_type type,int rate,int val1,int val2,int val3,int val4,t_tick duration,t_tick duration_total,t_tick duration_tick,unsigned char flag, int32 delay) {
|
||||||
map_session_data *sd = NULL;
|
map_session_data *sd = NULL;
|
||||||
status_change* sc;
|
status_change* sc;
|
||||||
struct status_change_entry* sce;
|
struct status_change_entry* sce;
|
||||||
@ -9932,14 +9935,14 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust tick according to status resistances
|
// Adjust duration_total according to status resistances
|
||||||
if( !(flag&(SCSTART_NOAVOID|SCSTART_LOADED)) ) {
|
if( !(flag&(SCSTART_NOAVOID|SCSTART_LOADED)) ) {
|
||||||
duration = status_get_sc_def(src, bl, type, rate, duration, flag);
|
duration_total = status_get_sc_def(src, bl, type, rate, duration_total, flag);
|
||||||
if( !duration )
|
if( duration_total == 0 )
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tick = (int)duration;
|
int tick = static_cast<int>(duration_total);
|
||||||
|
|
||||||
sd = BL_CAST(BL_PC, bl);
|
sd = BL_CAST(BL_PC, bl);
|
||||||
vd = status_get_viewdata(bl);
|
vd = status_get_viewdata(bl);
|
||||||
@ -12758,6 +12761,33 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
calc_flag.reset(SCB_BODY);
|
calc_flag.reset(SCB_BODY);
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
t_tick totaltick, subtick, subticktime = (intptr_t)nullptr;
|
||||||
|
bool has_tick_interval = false;
|
||||||
|
|
||||||
|
//if (tick_time)
|
||||||
|
// tick += 1;
|
||||||
|
|
||||||
|
if (duration_total > INT_MAX)
|
||||||
|
totaltick = duration_total;
|
||||||
|
else
|
||||||
|
totaltick = tick;
|
||||||
|
|
||||||
|
if (!(flag & SCSTART_LOADED)) {
|
||||||
|
subtick = totaltick; // When starting a new SC (not loading), its remaining duration is the same as the total
|
||||||
|
|
||||||
|
if (tick_time) {
|
||||||
|
subticktime = tick_time;
|
||||||
|
has_tick_interval = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
subtick = duration;
|
||||||
|
|
||||||
|
if (duration_tick > 0) {
|
||||||
|
subticktime = duration_tick;
|
||||||
|
has_tick_interval = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!(flag&SCSTART_NOICON) && !(flag&SCSTART_LOADED && scdb->flag[SCF_DISPLAYPC] || scdb->flag[SCF_DISPLAYNPC])) {
|
if (!(flag&SCSTART_NOICON) && !(flag&SCSTART_LOADED && scdb->flag[SCF_DISPLAYPC] || scdb->flag[SCF_DISPLAYNPC])) {
|
||||||
int status_icon = scdb->icon;
|
int status_icon = scdb->icon;
|
||||||
|
|
||||||
@ -12766,15 +12796,15 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
status_icon = EFST_ATTACK_PROPERTY_NOTHING + val1; // Assign status icon for older clients
|
status_icon = EFST_ATTACK_PROPERTY_NOTHING + val1; // Assign status icon for older clients
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
clif_status_change(bl, status_icon, 1, tick, scdb->flag[SCF_SENDVAL1] ? val1 : 1, scdb->flag[SCF_SENDVAL2] ? val2 : 0, scdb->flag[SCF_SENDVAL3] ? val3 : 0);
|
if (sc->getSCE(type))
|
||||||
|
clif_status_change(bl, status_icon, 0, 0, 0, 0, 0);
|
||||||
|
clif_status_change_sub(bl, bl->id, status_icon, 1, totaltick, subtick, scdb->flag[SCF_SENDVAL1] ? val1 : 1, scdb->flag[SCF_SENDVAL2] ? val2 : 0, scdb->flag[SCF_SENDVAL3] ? val3 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used as temporary storage for scs with interval ticks, so that the actual duration is sent to the client first.
|
|
||||||
if( tick_time )
|
|
||||||
tick = tick_time;
|
|
||||||
|
|
||||||
// Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
|
// Don't trust the previous sce assignment, in case the SC ended somewhere between there and here.
|
||||||
if((sce=sc->getSCE(type))) { // reuse old sc
|
if((sce=sc->getSCE(type))) { // reuse old sc
|
||||||
|
if (has_tick_interval && sce->tick_timer != INVALID_TIMER)
|
||||||
|
delete_timer(sce->tick_timer, status_change_tick_timer);
|
||||||
if( sce->timer != INVALID_TIMER )
|
if( sce->timer != INVALID_TIMER )
|
||||||
delete_timer(sce->timer, status_change_timer);
|
delete_timer(sce->timer, status_change_timer);
|
||||||
sc_isnew = false;
|
sc_isnew = false;
|
||||||
@ -12786,10 +12816,15 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
sce->val2 = val2;
|
sce->val2 = val2;
|
||||||
sce->val3 = val3;
|
sce->val3 = val3;
|
||||||
sce->val4 = val4;
|
sce->val4 = val4;
|
||||||
if (tick >= 0)
|
if (subtick >= 0)
|
||||||
sce->timer = add_timer(gettick() + tick, status_change_timer, bl->id, type);
|
sce->timer = add_timer(gettick() + subtick, status_change_timer, bl->id, type);
|
||||||
else
|
else
|
||||||
sce->timer = INVALID_TIMER; // Infinite duration
|
sce->timer = INVALID_TIMER; // Infinite duration
|
||||||
|
if (has_tick_interval && subticktime >= 0)
|
||||||
|
sce->tick_timer = add_timer(gettick() + subticktime, status_change_tick_timer, bl->id, type);
|
||||||
|
else
|
||||||
|
sce->tick_timer = INVALID_TIMER; // Infinite duration
|
||||||
|
sce->tick_total = totaltick;
|
||||||
|
|
||||||
if (calc_flag.any()) {
|
if (calc_flag.any()) {
|
||||||
if (sd != nullptr) {
|
if (sd != nullptr) {
|
||||||
@ -12905,6 +12940,24 @@ int status_change_start(struct block_list* src, struct block_list* bl,enum sc_ty
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a Status Change for its full time
|
||||||
|
* @param src: Source of the status change [PC|MOB|HOM|MER|ELEM|NPC]
|
||||||
|
* @param bl: Target of the status change (See: enum sc_type)
|
||||||
|
* @param type: Status change (SC_*)
|
||||||
|
* @param rate: Initial percentage rate of affecting bl (0~10000)
|
||||||
|
* @param val1: Depends on type of status change
|
||||||
|
* @param val2: Depends on type of status change
|
||||||
|
* @param val3: Depends on type of status change
|
||||||
|
* @param val4: Depends on type of status change
|
||||||
|
* @param tick: Remaining duration
|
||||||
|
* @param flag: Value which determines what parts to calculate. See e_status_change_start_flags
|
||||||
|
* @return adjusted duration based on flag values
|
||||||
|
*/
|
||||||
|
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, t_tick tick, unsigned char flag, int32 delay) {
|
||||||
|
return status_change_start_sub(src, bl, type, rate, val1, val2, val3, val4, 0, tick, flag, delay);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End all statuses except those listed
|
* End all statuses except those listed
|
||||||
* TODO: May be useful for dispel instead resetting a list there
|
* TODO: May be useful for dispel instead resetting a list there
|
||||||
@ -12958,6 +13011,8 @@ int status_change_clear(struct block_list* bl, int type)
|
|||||||
status_change_end(bl, status);
|
status_change_end(bl, status);
|
||||||
if( type == 1 && sc->getSCE(status) ) { // If for some reason status_change_end decides to still keep the status when quitting. [Skotlex]
|
if( type == 1 && sc->getSCE(status) ) { // If for some reason status_change_end decides to still keep the status when quitting. [Skotlex]
|
||||||
(sc->count)--;
|
(sc->count)--;
|
||||||
|
if (sc->getSCE(status)->tick_timer != INVALID_TIMER)
|
||||||
|
delete_timer(sc->getSCE(status)->tick_timer, status_change_tick_timer);
|
||||||
if (sc->getSCE(status)->timer != INVALID_TIMER)
|
if (sc->getSCE(status)->timer != INVALID_TIMER)
|
||||||
delete_timer(sc->getSCE(status)->timer, status_change_timer);
|
delete_timer(sc->getSCE(status)->timer, status_change_timer);
|
||||||
sc->deleteSCE(status);
|
sc->deleteSCE(status);
|
||||||
@ -13044,6 +13099,8 @@ int status_change_end(struct block_list* bl, enum sc_type type, int tid)
|
|||||||
if (!status_isdead(bl) && (sce->val2 || sce->val3 || sce->val4))
|
if (!status_isdead(bl) && (sce->val2 || sce->val3 || sce->val4))
|
||||||
return 0; //Don't end the status change yet as there are still unit groups associated with it
|
return 0; //Don't end the status change yet as there are still unit groups associated with it
|
||||||
}
|
}
|
||||||
|
if (sce->tick_timer != INVALID_TIMER)
|
||||||
|
delete_timer(sce->tick_timer, status_change_tick_timer);
|
||||||
if (sce->timer != INVALID_TIMER) // Could be a SC with infinite duration
|
if (sce->timer != INVALID_TIMER) // Could be a SC with infinite duration
|
||||||
delete_timer(sce->timer,status_change_timer);
|
delete_timer(sce->timer,status_change_timer);
|
||||||
}
|
}
|
||||||
@ -13690,7 +13747,68 @@ TIMER_FUNC(status_change_timer){
|
|||||||
std::function<void (t_tick)> sc_timer_next = [&sce, &bl, &data](t_tick t) {
|
std::function<void (t_tick)> sc_timer_next = [&sce, &bl, &data](t_tick t) {
|
||||||
sce->timer = add_timer(t, status_change_timer, bl->id, data);
|
sce->timer = add_timer(t, status_change_timer, bl->id, data);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If status has an interval and there is at least 100ms remaining time, wait for next interval
|
||||||
|
if (interval > 0 && sc->getSCE(type) && sce->val4 >= 100) {
|
||||||
|
sc_timer_next(min(sce->val4, interval) + tick);
|
||||||
|
sce->val4 -= interval;
|
||||||
|
if (dounlock)
|
||||||
|
map_freeblock_unlock();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dounlock)
|
||||||
|
map_freeblock_unlock();
|
||||||
|
|
||||||
|
// Default for all non-handled control paths is to end the status
|
||||||
|
return status_change_end(bl, type, tid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets timers for statuses that have an interval
|
||||||
|
* Used with reoccurring status effects, such as dropping SP every 5 seconds
|
||||||
|
* @param tid: Timer ID
|
||||||
|
* @param tick: How long before next call
|
||||||
|
* @param id: ID of character
|
||||||
|
* @param data: Information passed through the timer call
|
||||||
|
* @return 1: Success 0: Fail
|
||||||
|
*/
|
||||||
|
TIMER_FUNC(status_change_tick_timer) {
|
||||||
|
block_list *bl = map_id2bl(id);
|
||||||
|
|
||||||
|
if (!bl) {
|
||||||
|
ShowDebug("status_change_tick_timer: Null pointer id: %d data: %" PRIdPTR "\n", id, data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
status_change *const sc = status_get_sc(bl);
|
||||||
|
status_data *const status = status_get_status_data(bl);
|
||||||
|
|
||||||
|
if (!sc) {
|
||||||
|
ShowDebug("status_change_tick_timer: Null pointer id: %d data: %" PRIdPTR " bl-type: %d\n", id, data, bl->type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sc_type type = (sc_type)data;
|
||||||
|
status_change_entry *const sce = sc->getSCE(type);
|
||||||
|
|
||||||
|
if (!sce) {
|
||||||
|
ShowDebug("status_change_tick_timer: Null pointer id: %d data: %" PRIdPTR " bl-type: %d\n", id, data, bl->type);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (sce->tick_timer != tid) {
|
||||||
|
ShowError("status_change_tick_timer: Mismatch for type %d: %d != %d (bl id %d)\n", type, tid, sce->tick_timer, bl->id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int interval = status_get_sc_interval(type);
|
||||||
|
bool dounlock = false;
|
||||||
|
map_session_data *sd = BL_CAST(BL_PC, bl);
|
||||||
|
|
||||||
|
std::function<void(t_tick)> sc_timer_next = [&sce, &bl, &data](t_tick t) {
|
||||||
|
sce->tick_timer = add_timer(t, status_change_tick_timer, bl->id, data);
|
||||||
|
};
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case SC_MAXIMIZEPOWER:
|
case SC_MAXIMIZEPOWER:
|
||||||
case SC_CLOAKING:
|
case SC_CLOAKING:
|
||||||
@ -13887,7 +14005,7 @@ TIMER_FUNC(status_change_timer){
|
|||||||
bl->m == sd->feel_map[1].m ||
|
bl->m == sd->feel_map[1].m ||
|
||||||
bl->m == sd->feel_map[2].m)
|
bl->m == sd->feel_map[2].m)
|
||||||
{ // Timeout will be handled by pc_setpos
|
{ // Timeout will be handled by pc_setpos
|
||||||
sce->timer = INVALID_TIMER;
|
sce->tick_timer = INVALID_TIMER;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -14698,8 +14816,7 @@ TIMER_FUNC(status_change_timer){
|
|||||||
if (dounlock)
|
if (dounlock)
|
||||||
map_freeblock_unlock();
|
map_freeblock_unlock();
|
||||||
|
|
||||||
// Default for all non-handled control paths is to end the status
|
return 1;
|
||||||
return status_change_end( bl,type,tid );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15869,6 +15986,7 @@ void do_init_status(void) {
|
|||||||
memset(SCDisabled, 0, sizeof(SCDisabled));
|
memset(SCDisabled, 0, sizeof(SCDisabled));
|
||||||
|
|
||||||
add_timer_func_list(status_change_timer,"status_change_timer");
|
add_timer_func_list(status_change_timer,"status_change_timer");
|
||||||
|
add_timer_func_list(status_change_tick_timer, "status_change_tick_timer");
|
||||||
add_timer_func_list(status_natural_heal_timer,"status_natural_heal_timer");
|
add_timer_func_list(status_natural_heal_timer,"status_natural_heal_timer");
|
||||||
add_timer_func_list(status_clear_lastEffect_timer, "status_clear_lastEffect_timer");
|
add_timer_func_list(status_clear_lastEffect_timer, "status_clear_lastEffect_timer");
|
||||||
initDummyData();
|
initDummyData();
|
||||||
|
@ -3200,6 +3200,8 @@ struct sc_display_entry {
|
|||||||
struct status_change_entry {
|
struct status_change_entry {
|
||||||
int timer;
|
int timer;
|
||||||
int val1,val2,val3,val4;
|
int val1,val2,val3,val4;
|
||||||
|
int tick_timer; // Timer for the next interval based timer execution
|
||||||
|
t_tick tick_total; // Total amount of time the status is active for
|
||||||
};
|
};
|
||||||
|
|
||||||
///Status change
|
///Status change
|
||||||
@ -3383,6 +3385,7 @@ int status_isimmune(struct block_list *bl);
|
|||||||
|
|
||||||
t_tick status_get_sc_def(struct block_list *src,struct block_list *bl, enum sc_type type, int rate, t_tick tick, unsigned char flag);
|
t_tick status_get_sc_def(struct block_list *src,struct block_list *bl, enum sc_type type, int rate, t_tick tick, unsigned char flag);
|
||||||
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,t_tick duration,unsigned char flag, int32 delay = 0);
|
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,t_tick duration,unsigned char flag, int32 delay = 0);
|
||||||
|
int status_change_start_sub(struct block_list *src, struct block_list *bl, enum sc_type type, int rate, int val1, int val2, int val3, int val4, t_tick duration, t_tick duration_total, t_tick duration_tick, unsigned char flag, int32 delay = 0);
|
||||||
//Short version, receives rate in 1->100 range, and does not uses a flag setting.
|
//Short version, receives rate in 1->100 range, and does not uses a flag setting.
|
||||||
static int sc_start(block_list *src, block_list *bl, sc_type type, int32 rate, int32 val1, t_tick duration, int32 delay = 0) {
|
static int sc_start(block_list *src, block_list *bl, sc_type type, int32 rate, int32 val1, t_tick duration, int32 delay = 0) {
|
||||||
return status_change_start(src, bl, type, 100 * rate, val1, 0, 0, 0, duration, SCSTART_NONE, delay);
|
return status_change_start(src, bl, type, 100 * rate, val1, 0, 0, 0, duration, SCSTART_NONE, delay);
|
||||||
@ -3395,6 +3398,7 @@ static int sc_start4(block_list *src, block_list *bl, sc_type type, int32 rate,
|
|||||||
}
|
}
|
||||||
int status_change_end(struct block_list* bl, enum sc_type type, int tid = INVALID_TIMER);
|
int status_change_end(struct block_list* bl, enum sc_type type, int tid = INVALID_TIMER);
|
||||||
TIMER_FUNC(status_change_timer);
|
TIMER_FUNC(status_change_timer);
|
||||||
|
TIMER_FUNC(status_change_tick_timer);
|
||||||
int status_change_timer_sub(struct block_list* bl, va_list ap);
|
int status_change_timer_sub(struct block_list* bl, va_list ap);
|
||||||
int status_change_clear(struct block_list* bl, int type);
|
int status_change_clear(struct block_list* bl, int type);
|
||||||
void status_change_clear_buffs(struct block_list* bl, uint8 type);
|
void status_change_clear_buffs(struct block_list* bl, uint8 type);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user