瀏覽代碼

Fixes statuses with tick intervals
* Adds a new storage location for these tick types.
* Reverts some of the tick_total variable assignments.
* Adjusts sc_start to account for 64 bit tick values.
Thanks to @eppc0330!

aleos 2 年之前
父節點
當前提交
50bd9cdfbe
共有 10 個文件被更改,包括 178 次插入162 次删除
  1. 2 1
      sql-files/main.sql
  2. 3 0
      sql-files/upgrades/upgrade_20200803.sql
  3. 1 1
      src/char/char.cpp
  4. 5 4
      src/char/char_mapif.cpp
  5. 1 0
      src/common/mmo.hpp
  6. 10 2
      src/map/chrif.cpp
  7. 4 5
      src/map/clif.cpp
  8. 3 2
      src/map/script.cpp
  9. 145 145
      src/map/status.cpp
  10. 4 2
      src/map/status.hpp

+ 2 - 1
sql-files/main.sql

@@ -939,8 +939,9 @@ CREATE TABLE IF NOT EXISTS `sc_data` (
   `account_id` int(11) unsigned NOT NULL,
   `char_id` int(11) unsigned NOT NULL,
   `type` smallint(11) unsigned NOT NULL,
-  `tick_total` 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',
   `val2` int(11) NOT NULL default '0',
   `val3` int(11) NOT NULL default '0',

+ 3 - 0
sql-files/upgrades/upgrade_20200803.sql

@@ -1,2 +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`;

+ 1 - 1
src/char/char.cpp

@@ -2380,7 +2380,7 @@ bool char_checkdb(void){
 		return false;
 	}
 	//checking scdata_db
-	if( SQL_ERROR == Sql_Query(sql_handle, "SELECT  `account_id`,`char_id`,`type`,`tick`,`tick_total`,`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) ){
 		Sql_ShowDebug(sql_handle);
 		return false;

+ 5 - 4
src/char/char_mapif.cpp

@@ -279,7 +279,7 @@ int chmapif_parse_askscdata(int fd){
 		int aid, cid;
 		aid = RFIFOL(fd,2);
 		cid = RFIFOL(fd,6);
-		if( SQL_ERROR == Sql_Query(sql_handle, "SELECT type, tick, val1, val2, val3, val4, tick_total 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) )
 		{
 			Sql_ShowDebug(sql_handle);
@@ -304,6 +304,7 @@ int chmapif_parse_askscdata(int fd){
 				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, 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));
 			}
 			if (count >= 50)
@@ -943,14 +944,14 @@ int chmapif_parse_save_scdata(int fd){
 			int i;
 
 			StringBuf_Init(&buf);
-			StringBuf_Printf(&buf, "INSERT INTO `%s` (`account_id`, `char_id`, `type`, `tick`, `tick_total`, `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 )
 			{
 				memcpy (&data, RFIFOP(fd, 14+i*sizeof(struct status_change_data)), sizeof(struct status_change_data));
 				if( i > 0 )
 					StringBuf_AppendStr(&buf, ", ");
-				StringBuf_Printf(&buf, "('%d','%d','%hu','%" PRtf "','%" PRtf "','%ld','%ld','%ld','%ld')", aid, cid,
-					data.type, data.tick, data.tick_total, data.val1, data.val2, data.val3, data.val4);
+				StringBuf_Printf(&buf, "('%d','%d','%hu','%" PRtf "','%" PRtf "','%" PRtf "','%ld','%ld','%ld','%ld')", aid, cid,
+					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)) )
 				Sql_ShowDebug(sql_handle);

+ 1 - 0
src/common/mmo.hpp

@@ -403,6 +403,7 @@ struct status_change_data {
 	long val1, val2, val3, val4;
 	t_tick tick; //Remaining duration.
 	t_tick tick_total; // Total duration
+	t_tick tick_time; // Interval duration
 };
 
 #define MAX_BONUS_SCRIPT_LENGTH 512

+ 10 - 2
src/map/chrif.cpp

@@ -1339,7 +1339,15 @@ int chrif_save_scdata(struct map_session_data *sd) { //parses the sc_data of the
 				data.tick = 0; //Negative tick does not necessarily mean that sc has expired
 		} else
 			data.tick = INFINITE_TICK; //Infinite duration
-		data.tick_total = sc->getSCE(i)->tick_total;
+		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.val1 = sce->val1;
 		data.val2 = sce->val2;
@@ -1423,7 +1431,7 @@ int chrif_load_scdata(int fd) {
 	for (i = 0; i < count; i++) {
 		struct status_change_data *data = (struct status_change_data*)RFIFOP(fd,14 + i*sizeof(struct status_change_data));
 
-		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, 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);

+ 4 - 5
src/map/clif.cpp

@@ -6382,9 +6382,9 @@ void clif_status_change_sub(struct block_list *bl, int id, int type, int flag, t
 #if PACKETVER >= 20090121
 	if (battle_config.display_status_timers > 0) {
 #if PACKETVER >= 20120618
-		p.Total = client_tick(tick_total);
+		p.Total = client_tick(tick);
 #endif
-		p.Left = client_tick(tick);
+		p.Left = client_tick(tick_total);
 		p.val1 = val1;
 		p.val2 = val2;
 		p.val3 = val3;
@@ -6445,8 +6445,7 @@ void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl,
 		enum sc_type type = sc_display[i]->type;
 		struct status_change *sc = status_get_sc(bl);
 		const TimerData *td = (sc && sc->getSCE(type) ? get_timer(sc->getSCE(type)->timer) : nullptr);
-		t_tick tick_total = 0, tick = 0, cur_tick = gettick();
-		tick_total = DIFF_TICK(sc->getSCE(type)->tick_total, cur_tick);
+		t_tick tick = 0, cur_tick = gettick();
 
 		if (td != nullptr)
 			tick = DIFF_TICK(td->tick, cur_tick);
@@ -6470,7 +6469,7 @@ void clif_efst_status_change_sub(struct block_list *tbl, struct block_list *bl,
 		}
 
 #if PACKETVER > 20120418
-		clif_efst_status_change(tbl, bl->id, target, status_db.getIcon(type), tick_total, 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
 		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

+ 3 - 2
src/map/script.cpp

@@ -12233,7 +12233,8 @@ BUILDIN_FUNC(sc_start)
 	TBL_NPC * nd = map_id2nd(st->oid);
 	struct block_list* bl;
 	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;
 	const char* command = script_getfuncname(st);
 
@@ -12245,7 +12246,7 @@ BUILDIN_FUNC(sc_start)
 		start_type = 1;
 
 	type = (sc_type)script_getnum(st,2);
-	tick = script_getnum(st,3);
+	tick = script_getnum64(st,3);
 	val1 = script_getnum(st,4);
 
 	//If from NPC we make default flag 1 to be unavoidable

File diff suppressed because it is too large
+ 145 - 145
src/map/status.cpp


+ 4 - 2
src/map/status.hpp

@@ -3130,7 +3130,8 @@ struct sc_display_entry {
 struct status_change_entry {
 	int timer;
 	int val1,val2,val3,val4;
-	t_tick tick_total;
+	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
@@ -3314,7 +3315,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);
 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, 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.
 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);
@@ -3327,6 +3328,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);
 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_clear(struct block_list* bl, int type);
 void status_change_clear_buffs(struct block_list* bl, uint8 type);

Some files were not shown because too many files changed in this diff