Преглед изворни кода

Fixes potential map server crashes. (#2695)

* status_change_timer refactorization
* Changes some pointers to const pointers to prevent unwanted behavoir.
* Changes sc_timer_next to a lambda function with only the tick as a
  paramter.
* sce is not reassigned in sc_timer_next anymore, therefore it should be
  crash safe (see #2414 and #2539)
* Fixes #2539
* Thanks to @whupdo, @MuzTank and @admkakaroto!
Jeybla пре 7 година
родитељ
комит
5a80f29b65
1 измењених фајлова са 88 додато и 89 уклоњено
  1. 88 89
      src/map/status.cpp

+ 88 - 89
src/map/status.cpp

@@ -6,6 +6,7 @@
 #include <stdlib.h>
 #include <math.h>
 #include <string>
+#include <functional>
 #include <yaml-cpp/yaml.h>
 
 #include "../common/cbasetypes.h"
@@ -12626,9 +12627,6 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	enum sc_type type = (sc_type)data;
 	struct block_list *bl;
 	struct map_session_data *sd;
-	struct status_data *status;
-	struct status_change *sc;
-	struct status_change_entry *sce;
 	int interval = status_get_sc_interval(type);
 	bool dounlock = false;
 
@@ -12637,14 +12635,19 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		ShowDebug("status_change_timer: Null pointer id: %d data: %d\n", id, data);
 		return 0;
 	}
-	sc = status_get_sc(bl);
-	status = status_get_status_data(bl);
 
-	if(!(sc && (sce = sc->data[type]))) {
+	struct status_change * const sc = status_get_sc(bl);
+	struct status_data * const status = status_get_status_data(bl);
+	if(!sc) {
+		ShowDebug("status_change_timer: Null pointer id: %d data: %d bl-type: %d\n", id, data, bl->type);
+		return 0;
+	}
+	
+	struct status_change_entry * const sce = sc->data[type];
+	if(!sce) {
 		ShowDebug("status_change_timer: Null pointer id: %d data: %d bl-type: %d\n", id, data, bl->type);
 		return 0;
 	}
-
 	if( sce->timer != tid ) {
 		ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id);
 		return 0;
@@ -12652,19 +12655,16 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 	sd = BL_CAST(BL_PC, bl);
 
-// Set the next timer of the sce (don't assume the status still exists)
-#define sc_timer_next(t,f,i,d) \
-	if( (sce=sc->data[type]) ) \
-		sce->timer = add_timer(t,f,i,d); \
-	else \
-		ShowError("status_change_timer: Unexpected NULL status change id: %d data: %d\n", id, data)
-
+	std::function<void (unsigned int)> sc_timer_next = [&sce, &bl, &data](unsigned int t) {
+		sce->timer = add_timer(t, status_change_timer, bl->id, data);
+	};
+	
 	switch(type) {
 	case SC_MAXIMIZEPOWER:
 	case SC_CLOAKING:
 		if(!status_charge(bl, 0, 1))
 			break; // Not enough SP to continue.
-		sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data);
+		sc_timer_next(sce->val2+tick);
 		return 0;
 
 	case SC_CHASEWALK:
@@ -12676,7 +12676,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) // SL bonus -> x10 duration
 				*skill_get_time2(status_sc2skill(type),sce->val1));
 		}
-		sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data);
+		sc_timer_next(sce->val2+tick);
 		return 0;
 	break;
 
@@ -12686,7 +12686,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			if(sce->val2 % sce->val4 == 0 && !status_charge(bl, 0, 1))
 				break; // Fail if it's time to substract SP and there isn't.
 
-			sc_timer_next(1000+tick, status_change_timer,bl->id, data);
+			sc_timer_next(1000+tick);
 			return 0;
 		}
 	break;
@@ -12706,14 +12706,14 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 		if( --(sce->val2)>0 ) {
 			sce->val4 += 20; // Use for Shadow Form 2 seconds checking.
-			sc_timer_next(20+tick, status_change_timer, bl->id, data);
+			sc_timer_next(20+tick);
 			return 0;
 		}
 		break;
 
 	case SC_PROVOKE:
 		if(sce->val2) { // Auto-provoke (it is ended in status_heal)
-			sc_timer_next(1000*60+tick,status_change_timer, bl->id, data );
+			sc_timer_next(1000*60+tick);
 			return 0;
 		}
 		break;
@@ -12729,7 +12729,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			status_change_end(bl, SC_AETERNA, INVALID_TIMER);
 			sc->opt1 = OPT1_STONE;
 			clif_changeoption(bl);
-			sc_timer_next(min(sce->val4, interval) + tick, status_change_timer, bl->id, data);
+			sc_timer_next(min(sce->val4, interval) + tick);
 			sce->val4 -= interval; //Remaining time
 			status_calc_bl(bl, StatusChangeFlagTable[type]);
 			return 0;
@@ -12844,7 +12844,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 	case SC_TENSIONRELAX:
 		if(status->max_hp > status->hp && --(sce->val3) >= 0) {
-			sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(10000 + tick);
 			return 0;
 		}
 		break;
@@ -12868,7 +12868,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			if( status->hp < status->max_hp )
 				hp = (sce->val1 < 0) ? (int)(sd->status.max_hp * -1 * sce->val1 / 100.) : sce->val1 ;
 			status_heal(bl, hp, 0, 2);
-			sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data);
+			sc_timer_next((sce->val2 * 1000) + tick);
 			return 0;
 		}
 		break;
@@ -12888,7 +12888,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 					clif_bossmapinfo(sd, boss_md, BOSS_INFO_DEAD);
 				}
 			}
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -12944,14 +12944,14 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				if (!status_charge(bl, 0, sp))
 					break;
 			}
-			sc_timer_next(1000+tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000+tick);
 			return 0;
 		}
 		break;
 	case SC_BERSERK:
 		// 5% every 10 seconds [DracoRPG]
 		if( --( sce->val3 ) > 0 && status_charge(bl, sce->val2, 0) && status->hp > 100 ) {
-			sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
+			sc_timer_next(sce->val4+tick);
 			return 0;
 		}
 		break;
@@ -12962,7 +12962,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			clif_changestatus(sd,SP_MANNER,sd->status.manner);
 			clif_updatestatus(sd,SP_MANNER);
 			if (sd->status.manner < 0) { // Every 60 seconds your manner goes up by 1 until it gets back to 0.
-				sc_timer_next(60000+tick, status_change_timer, bl->id, data);
+				sc_timer_next(60000+tick);
 				return 0;
 			}
 		}
@@ -12976,7 +12976,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		// 	clif_message(bl, timer);
 		// }
 		if((sce->val4 -= 500) > 0) {
-			sc_timer_next(500 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(500 + tick);
 			return 0;
 		}
 		break;
@@ -12986,7 +12986,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		{
 			struct block_list *pbl = map_id2bl(sce->val1);
 			if( pbl && check_distance_bl(bl, pbl, 7) ) {
-				sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+				sc_timer_next(1000 + tick);
 				return 0;
 			}
 		}
@@ -12999,35 +12999,35 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			sp = (sce->val1 > 5) ? 35 : 20;
 			if(!status_charge(bl, hp, sp))
 				break;
-			sc_timer_next(10000+tick, status_change_timer, bl->id, data);
+			sc_timer_next(10000+tick);
 			return 0;
 		}
 		break;
 
 	case SC_JAILED:
 		if(sce->val1 == INT_MAX || --(sce->val1) > 0) {
-			sc_timer_next(60000+tick, status_change_timer, bl->id,data);
+			sc_timer_next(60000+tick);
 			return 0;
 		}
 		break;
 
 	case SC_BLIND:
 		if(sc->data[SC_FOGWALL]) { // Blind lasts forever while you are standing on the fog.
-			sc_timer_next(5000+tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000+tick);
 			return 0;
 		}
 		break;
 	case SC_ABUNDANCE:
 		if(--(sce->val4) > 0) {
 			status_heal(bl,0,60,0);
-			sc_timer_next(10000+tick, status_change_timer, bl->id, data);
+			sc_timer_next(10000+tick);
 		}
 		break;
 
 	case SC_OBLIVIONCURSE:
 		if( --(sce->val4) >= 0 ) {
 			clif_emotion(bl,ET_QUESTION);
-			sc_timer_next(3000 + tick, status_change_timer, bl->id, data );
+			sc_timer_next(3000 + tick);
 			return 0;
 		}
 		break;
@@ -13036,7 +13036,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( --(sce->val4) >= 0 ) {
 			if( !status_charge(bl,0,3) )
 				break;
-			sc_timer_next(5000+tick,status_change_timer,bl->id,data);
+			sc_timer_next(5000+tick);
 			return 0;
 		}
 		break;
@@ -13044,7 +13044,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_CLOAKINGEXCEED:
 		if(!status_charge(bl,0,10-sce->val1))
 			break;
-		sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+		sc_timer_next(1000 + tick);
 		return 0;
 
 	case SC_RENOVATIO:
@@ -13053,7 +13053,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			if( sc && sc->data[SC_AKAITSUKI] && heal )
 				heal = ~heal + 1;
 			status_heal(bl, heal, 0, 3);
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
@@ -13066,7 +13066,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( --(sce->val4) >= 0 ) {
 			if( !status_charge(bl, 0, 1) )
 				break;
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -13078,13 +13078,13 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				status_change_end(bl, (sc_type)i, INVALID_TIMER);
 			break;
 		}
-		sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+		sc_timer_next(10000 + tick);
 		return 0;
 
 	case SC_ELECTRICSHOCKER:
 		if( --(sce->val4) >= 0 ) {
 			status_charge(bl, 0, 5 * sce->val1 * status->max_sp / 100);
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -13094,20 +13094,20 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			break;
 		if (--sce->val4 >= 0)
 			sce->val3++;
-		sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+		sc_timer_next(1000 + tick);
 		return 0;
 
 	case SC__REPRODUCE:
 		if(!status_charge(bl, 0, 1))
 			break;
-		sc_timer_next(1000+tick, status_change_timer, bl->id, data);
+		sc_timer_next(1000+tick);
 		return 0;
 
 	case SC__SHADOWFORM:
 		if( --(sce->val4) >= 0 ) {
 			if( !status_charge(bl, 0, 11 - sce->val1) )
 				break;
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -13115,14 +13115,14 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC__INVISIBILITY:
 		if( !status_charge(bl, 0, (12 - 2 * sce->val1) * status->max_sp / 100) ) // 6% - skill_lv.
 			break;
-		sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+		sc_timer_next(1000 + tick);
 		return 0;
 
 	case SC_STRIKING:
 		if( --(sce->val4) >= 0 ) {
 			if( !status_charge(bl,0, sce->val3 ) )
 				break;
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -13135,7 +13135,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				dounlock = true;
 				skill_attack(skill_get_type(status_sc2skill(type)), src, unit_bl, bl, SO_CLOUD_KILL, sce->val1, tick, 0);
 				if (!status_isdead(bl)) {
-					sc_timer_next(500 + tick, status_change_timer, bl->id, data);
+					sc_timer_next(500 + tick);
 				}
 			}
 		}
@@ -13153,7 +13153,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				hp = ~hp + 1;
 			if (status->hp != status->max_hp)
 				status_heal(bl, hp, 0, 0);
-			sc_timer_next(3000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(3000 + tick);
 			return 0;
 		}
 
@@ -13171,7 +13171,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			status_damage(src, bl, damage, 0, clif_damage(bl,bl,tick,status->amotion,status->dmotion+200,damage,1,DMG_NORMAL,0,false), 0);
 			unit_skillcastcancel(bl,1);
 			if ( sc->data[type] ) {
-				sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+				sc_timer_next(1000 + tick);
 			}
 			map_freeblock_unlock();
 			status_heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level
@@ -13182,7 +13182,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_VOICEOFSIREN:
 		if( --(sce->val4) >= 0 ) {
 			clif_emotion(bl,ET_THROB);
-			sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(2000 + tick);
 			return 0;
 		}
 		break;
@@ -13190,7 +13190,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_DEEPSLEEP:
 		if( --(sce->val4) >= 0 ) { // Recovers 3% HP/SP every 2 seconds.
 			status_heal(bl, status->max_hp * 3 / 100, status->max_sp * 3 / 100, 2);
-			sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(2000 + tick);
 			return 0;
 		}
 		break;
@@ -13200,7 +13200,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			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);
 			return 0;
 		}
 		break;
@@ -13208,7 +13208,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_SONGOFMANA:
 		if( --(sce->val4) >= 0 ) {
 			status_heal(bl,0,sce->val3,3);
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
@@ -13219,7 +13219,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( --(sce->val3) >= 0 ) {
 			if( !status_charge(bl, status->hp / 100, status->sp / 100) )
 				break;
-			sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
+			sc_timer_next(sce->val4+tick);
 			return 0;
 		}
 		break;
@@ -13227,7 +13227,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_MELODYOFSINK:
 		if( --(sce->val4) >= 0 ) {
 			status_charge(bl, 0, status->max_sp * ( 2 * sce->val1 + 2 * sce->val2 ) / 100);
-			sc_timer_next(1000+tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000+tick);
 			return 0;
 		}
 		break;
@@ -13236,7 +13236,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( --(sce->val4) >= 0 ) { // Drains 2% of HP and 1% of SP every seconds.
 			if (!status_charge(bl, status->max_hp * 2 / 100, status->max_sp / 100))
 				break;
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -13244,13 +13244,13 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_FORCEOFVANGUARD:
 		if( !status_charge(bl,0,24 - 4 * sce->val1) )
 			break;
-		sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+		sc_timer_next(10000 + tick);
 		return 0;
 
 	case SC_BANDING:
 		if( status_charge(bl, 0, 7 - sce->val1) ) {
 			if( sd ) pc_banding(sd, sce->val1);
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
@@ -13259,14 +13259,14 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( --(sce->val4) > 0 ) {
 			if( !status_charge(bl,0,10) )
  				break;
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
 
 	case SC_OVERHEAT_LIMITPOINT:
 		if( --(sce->val1) > 0 ) { // Cooling
-			sc_timer_next(30000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(30000 + tick);
 		}
 		break;
 
@@ -13277,7 +13277,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			map_freeblock_lock();
 			status_fix_damage(NULL,bl,damage,clif_damage(bl,bl,tick,0,0,damage,0,DMG_NORMAL,0,false));
 			if( sc->data[type] ) {
-				sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+				sc_timer_next(1000 + tick);
 			}
 			map_freeblock_unlock();
 		}
@@ -13291,7 +13291,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				break;
 			if (!status_charge(bl, 0, 50))
 				status_zap(bl, 0, status->sp);
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -13303,7 +13303,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 			if( !status_charge(bl,hp,sp) ) break;
 
-			sc_timer_next(5000+tick,status_change_timer,bl->id, data);
+			sc_timer_next(5000+tick);
 			return 0;
 		}
 		break;
@@ -13312,7 +13312,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		// 1% every 5 seconds [Jobbie]
 		if( --(sce->val3)>0 && status_charge(bl, sce->val2, 0) ) {
 			if( !sc->data[type] ) return 0;
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
@@ -13346,12 +13346,12 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			status_change_end(bl,type,INVALID_TIMER);
 			break;
 		}
-		sc_timer_next(sce->val3 + tick, status_change_timer, bl->id, data);
+		sc_timer_next(sce->val3 + tick);
 		return 0;
 
 	case SC_WATER_SCREEN_OPTION:
 		status_heal(bl,1000,0,2);
-		sc_timer_next(10000 + tick,status_change_timer,bl->id,data);
+		sc_timer_next(10000 + tick);
 		return 0;
 
 	case SC_TEARGAS:
@@ -13363,7 +13363,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			clif_damage(bl, bl, tick, 0, 0, damage, 1, DMG_MULTI_HIT_ENDURE, 0, false);
 			status_damage(src, bl, damage,0, 0, 1);
 			if( sc->data[type] ) {
-				sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
+				sc_timer_next(2000 + tick);
 			}
 			map_freeblock_unlock();
 			return 0;
@@ -13372,7 +13372,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_TEARGAS_SOB:
 		if( --(sce->val4) >= 0 ) {
 			clif_emotion(bl, ET_CRY);
-			sc_timer_next(3000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(3000 + tick);
 			return 0;
 		}
 		break;
@@ -13384,7 +13384,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				skill_sit(sd, 1);
 				clif_sitting(bl);
 			}
-			sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(10000 + tick);
 			return 0;
 		}
 		break;
@@ -13393,26 +13393,26 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 	case SC_SOULCOLD:
 	case SC_HAWKEYES:
 		// They only end by status_change_end
-		sc_timer_next(600000 + tick, status_change_timer, bl->id, data);
+		sc_timer_next(600000 + tick);
 		return 0;
 	case SC_MEIKYOUSISUI:
 		if( --(sce->val4) >= 0 ) {
 			status_heal(bl, status->max_hp * sce->val2 / 100, status->max_sp * sce->val3 / 100, 0);
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
 	case SC_KAGEMUSYA:
 		if( --(sce->val2) >= 0 ) {
 			if(!status_charge(bl, 0, 1)) break;
-			sc_timer_next(1000+tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000+tick);
 			return 0;
 		}
 		break;
 	case SC_ANGRIFFS_MODUS:
 		if(--(sce->val4) >= 0) { // Drain hp/sp
 			if( !status_charge(bl,100,20) ) break;
-			sc_timer_next(1000+tick,status_change_timer,bl->id, data);
+			sc_timer_next(1000+tick);
 			return 0;
 		}
 		break;
@@ -13422,35 +13422,35 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			int sp = (status->max_sp * sce->val3) / 100;
 			if(bl->type == BL_MOB) hp = sp*10;
 			if( !status_charge(bl,hp,sp) )break;
-			sc_timer_next(1000+tick,status_change_timer,bl->id, data);
+			sc_timer_next(1000+tick);
 			return 0;
 		}
 		break;
 	case SC_FULL_THROTTLE:
 		if( --(sce->val4) >= 0 ) {
 			status_percent_damage(bl, bl, 0, sce->val2, false);
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
 	case SC_REBOUND:
 		if( --(sce->val4) >= 0 ) {
 			clif_emotion(bl, ET_SWEAT);
-			sc_timer_next(2000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(2000 + tick);
 			return 0;
 		}
 		break;
 	case SC_KINGS_GRACE:
 		if( --(sce->val4) >= 0 ) {
 			status_percent_heal(bl, sce->val2, 0);
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
 	case SC_FRIGG_SONG:
 		if( --(sce->val4) >= 0 ) {
 			status_heal(bl, sce->val3, 0, 0);
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
@@ -13459,7 +13459,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 			TBL_PC *caster = map_id2sd(sce->val2);
 			if (!caster || caster->bl.m != bl->m) //End the SC if caster isn't in same map
 				break;
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			clif_crimson_marker(caster, bl, false);
 			return 0;
 		}
@@ -13468,7 +13468,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if (--(sce->val4) >= 0) {
 			if (!status_charge(bl, 0, status->max_sp * 3 / 100))
 				break;
-			sc_timer_next(sce->val3 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(sce->val3 + tick);
 			return 0;
 		}
 		break;
@@ -13478,7 +13478,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				clif_slide(bl, sce->val3>>16, sce->val3&0xFFFF);
 				clif_fixpos(bl);
 			}
-			sc_timer_next(tick+sce->val4, status_change_timer, bl->id, data);
+			sc_timer_next(tick+sce->val4);
 			sce->val4 = 0;
 		}
 		break;
@@ -13488,7 +13488,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				status_heal(bl, status->max_hp / 100, 0, 1);
 			else if (status->def_ele == ELE_EARTH)
 				status_zap(bl, status->max_hp / 100, 0);
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
@@ -13499,7 +13499,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				status_heal(bl, status->max_hp / 100, 0, 1);
 			else if (status->def_ele == ELE_FIRE)
 				status_zap(bl, status->max_hp / 100, 0);
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
@@ -13510,7 +13510,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				status_heal(bl, status->max_hp / 100, 0, 1);
 			else if (status->def_ele == ELE_WATER)
 				status_zap(bl, status->max_hp / 100, 0);
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
@@ -13521,21 +13521,21 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 				status_heal(bl, status->max_hp / 100, 0, 1);
 			else if (status->def_ele == ELE_WIND)
 				status_zap(bl, status->max_hp / 100, 0);
-			sc_timer_next(5000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(5000 + tick);
 			return 0;
 		}
 		break;
 	case SC_BITESCAR:
 		if (--(sce->val4) >= 0) {
 			status_percent_damage(bl, bl, -(sce->val2), 0, 0);
-			sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(1000 + tick);
 			return 0;
 		}
 		break;
 	case SC_FRESHSHRIMP:
 		if (--(sce->val4) >= 0) {
 			status_heal(bl, sce->val2, 0, 3);
-			sc_timer_next((10000 - ((sce->val1 - 1) * 1000)) + tick, status_change_timer, bl->id, data);
+			sc_timer_next((10000 - ((sce->val1 - 1) * 1000)) + tick);
 			return 0;
 		}
 		break;
@@ -13543,7 +13543,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( sd && --(sce->val4) >= 0 ) {
 			if( status->hp < status->max_hp )
 				status_heal(bl, 10, 0, 2);
-			sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(10000 + tick);
 			return 0;
 		}
 		break;
@@ -13551,7 +13551,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 		if( sd && --(sce->val4) >= 0 ) {
 			if( status->sp < status->max_sp )
 				status_heal(bl, 0, 5, 2);
-			sc_timer_next(10000 + tick, status_change_timer, bl->id, data);
+			sc_timer_next(10000 + tick);
 			return 0;
 		}
 		break;
@@ -13559,7 +13559,7 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 	// If status has an interval and there is at least 100ms remaining time, wait for next interval
 	if(interval > 0 && sc->data[type] && sce->val4 >= 100) {
-		sc_timer_next(min(sce->val4,interval)+tick, status_change_timer, bl->id, data);
+		sc_timer_next(min(sce->val4,interval)+tick);
 		sce->val4 -= interval;
 		if (dounlock)
 			map_freeblock_unlock();
@@ -13571,7 +13571,6 @@ int status_change_timer(int tid, unsigned int tick, int id, intptr_t data)
 
 	// Default for all non-handled control paths is to end the status
 	return status_change_end( bl,type,tid );
-#undef sc_timer_next
 }
 
 /**