summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt4
-rw-r--r--src/map/status.c54
2 files changed, 35 insertions, 23 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index f62791274..691e1c114 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,6 +4,10 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK.
2008/01/12
+ * Another possible fix to ers/status_change crashing.
+ - same logic as r12058 but in status_change_timer.
+ - look out for this error: "[Error]: status_change_timer: Unexpected NULL status change id: ### data: ###"
+ getting it means that a crash was avoided and the culprit found.
* Modified npc_parsesrcfile to read the file as binary and let sv_parse handle LF/CRLF line endings.
* Possible fix to ers/status_change crashing. [FlavioJS]
- this patch is untested. Didn't find anyone willing to test it and I can't
diff --git a/src/map/status.c b/src/map/status.c
index 1e3fd7e3a..0b1312586 100644
--- a/src/map/status.c
+++ b/src/map/status.c
@@ -6709,13 +6709,20 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
BL_CAST(BL_PC, bl, sd);
+// 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)
+
switch(type)
{
case SC_MAXIMIZEPOWER:
case SC_CLOAKING:
if(!status_charge(bl, 0, 1))
break; //Not enough SP to continue.
- sce->timer = add_timer(sce->val2+tick, status_change_timer, bl->id, data);
+ sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data);
return 0;
case SC_CHASEWALK:
@@ -6727,14 +6734,14 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
(sc->data[SC_SPIRIT] && sc->data[SC_SPIRIT]->val2 == SL_ROGUE?10:1) //SL bonus -> x10 duration
*skill_get_time2(StatusSkillChangeTable[type],sce->val1));
}
- sce->timer = add_timer(sce->val2+tick, status_change_timer, bl->id, data);
+ sc_timer_next(sce->val2+tick, status_change_timer, bl->id, data);
return 0;
break;
case SC_SKA:
if(--(sce->val2)>0){
sce->val3 = rand()%100; //Random defense.
- sce->timer = add_timer(1000+tick, status_change_timer,bl->id, data);
+ sc_timer_next(1000+tick, status_change_timer,bl->id, data);
return 0;
}
break;
@@ -6745,7 +6752,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int 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.
- sce->timer = add_timer(1000+tick, status_change_timer,bl->id, data);
+ sc_timer_next(1000+tick, status_change_timer,bl->id, data);
return 0;
}
break;
@@ -6756,14 +6763,14 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
map_foreachinrange( status_change_timer_sub, bl, sce->val3, BL_CHAR, bl, sce, type, tick);
if( --(sce->val2)>0 ){
- sce->timer = add_timer(250+tick, status_change_timer, bl->id, data);
+ sc_timer_next(250+tick, status_change_timer, bl->id, data);
return 0;
}
break;
case SC_PROVOKE:
if(sce->val2) { //Auto-provoke (it is ended in status_heal)
- sce->timer = add_timer(1000*60+tick,status_change_timer, bl->id, data );
+ sc_timer_next(1000*60+tick,status_change_timer, bl->id, data );
return 0;
}
break;
@@ -6774,14 +6781,14 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
unit_stop_walking(bl,1);
sc->opt1 = OPT1_STONE;
clif_changeoption(bl);
- sce->timer = add_timer(1000+tick,status_change_timer, bl->id, data );
+ sc_timer_next(1000+tick,status_change_timer, bl->id, data );
status_calc_bl(bl, StatusChangeFlagTable[type]);
return 0;
}
if(--(sce->val3) > 0) {
if(++(sce->val4)%5 == 0 && status->hp > status->max_hp/4)
status_zap(bl, sce->val2, 0);
- sce->timer = add_timer(1000+tick,status_change_timer, bl->id, data );
+ sc_timer_next(1000+tick,status_change_timer, bl->id, data );
return 0;
}
break;
@@ -6796,14 +6803,14 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
if (status_isdead(bl))
break;
}
- sce->timer = add_timer(1000 + tick, status_change_timer, bl->id, data );
+ sc_timer_next(1000 + tick, status_change_timer, bl->id, data );
return 0;
}
break;
case SC_TENSIONRELAX:
if(status->max_hp > status->hp && --(sce->val3) > 0){
- sce->timer = add_timer(sce->val4+tick, status_change_timer, bl->id, data);
+ sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
return 0;
}
break;
@@ -6813,7 +6820,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
status_fix_damage(NULL, bl, rand()%600 + 200, 0);
if (status_isdead(bl))
break;
- sce->timer = add_timer(10000 + tick, status_change_timer, bl->id, data );
+ sc_timer_next(10000 + tick, status_change_timer, bl->id, data );
return 0;
}
break;
@@ -6825,7 +6832,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
int hp = (int)(sd->status.max_hp * sce->val1 / 100.);
status_heal(bl, hp, 0, 2);
}
- sce->timer = add_timer((sce->val2 * 1000) + tick, status_change_timer, bl->id, data );
+ sc_timer_next((sce->val2 * 1000) + tick, status_change_timer, bl->id, data );
return 0;
}
break;
@@ -6836,7 +6843,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
bl->m == sd->feel_map[1].m ||
bl->m == sd->feel_map[2].m)
{ //Timeout will be handled by pc_setpos
- sce->timer = -1;
+ sce->timer = INVALID_TIMER;
return 0;
}
break;
@@ -6891,7 +6898,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
if (!status_charge(bl, 0, sp))
break;
}
- sce->timer = add_timer(1000+tick, status_change_timer, bl->id, data);
+ sc_timer_next(1000+tick, status_change_timer, bl->id, data);
return 0;
}
break;
@@ -6902,7 +6909,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
struct map_session_data *md = map_id2sd(sce->val1);
if (md && check_distance_bl(bl, &md->bl, sce->val3) && (sce->val4-=1000)>0)
{
- sce->timer = add_timer(1000+tick, status_change_timer, bl->id, data);
+ sc_timer_next(1000+tick, status_change_timer, bl->id, data);
return 0;
}
}
@@ -6912,7 +6919,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
// 5% every 10 seconds [DracoRPG]
if(--(sce->val3)>0 && status_charge(bl, sce->val2, 0))
{
- sce->timer = add_timer(sce->val4+tick, status_change_timer, bl->id, data);
+ sc_timer_next(sce->val4+tick, status_change_timer, bl->id, data);
return 0;
}
break;
@@ -6923,7 +6930,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
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.
- sce->timer = add_timer(60000+tick, status_change_timer, bl->id, data);
+ sc_timer_next(60000+tick, status_change_timer, bl->id, data);
return 0;
}
}
@@ -6937,7 +6944,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
// clif_message(bl, timer);
//}
if((sce->val4 -= 500) > 0) {
- sce->timer = add_timer(500 + tick, status_change_timer, bl->id, data);
+ sc_timer_next(500 + tick, status_change_timer, bl->id, data);
return 0;
}
break;
@@ -6948,7 +6955,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
struct block_list *pbl = map_id2bl(sce->val1);
if (pbl && check_distance_bl(bl, pbl, 7) && (sce->val2)-->0)
{
- sce->timer = add_timer(1000 + tick, status_change_timer, bl->id, data);
+ sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
return 0;
}
}
@@ -6962,7 +6969,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
sp = (sce->val1 > 5) ? 35 : 20;
if(!status_charge(bl, hp, sp))
break;
- sce->timer = add_timer(10000+tick, status_change_timer, bl->id, data);
+ sc_timer_next(10000+tick, status_change_timer, bl->id, data);
return 0;
}
break;
@@ -6972,7 +6979,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
struct block_list *tbl = map_id2bl(sce->val2);
if (tbl && battle_check_range(bl, tbl, 2)){
- sce->timer = add_timer(1000 + tick, status_change_timer, bl->id, data);
+ sc_timer_next(1000 + tick, status_change_timer, bl->id, data);
return 0;
}
}
@@ -6981,7 +6988,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
case SC_JAILED:
if(sce->val1 == INT_MAX || --(sce->val1) > 0)
{
- sce->timer = add_timer(60000+tick, status_change_timer, bl->id,data);
+ sc_timer_next(60000+tick, status_change_timer, bl->id,data);
return 0;
}
break;
@@ -6989,7 +6996,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
case SC_BLIND:
if(sc->data[SC_FOGWALL])
{ //Blind lasts forever while you are standing on the fog.
- sce->timer = add_timer(5000+tick, status_change_timer, bl->id, data);
+ sc_timer_next(5000+tick, status_change_timer, bl->id, data);
return 0;
}
break;
@@ -6997,6 +7004,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
// default for all non-handled control paths is to end the status
return status_change_end( bl,type,tid );
+#undef sc_timer_next
}
/*==========================================