diff options
author | shennetsind <ind@henn.et> | 2015-03-14 23:18:53 -0300 |
---|---|---|
committer | shennetsind <ind@henn.et> | 2015-03-14 23:18:53 -0300 |
commit | 8aee60e91807930e4d43965a20c8991b416d7f29 (patch) | |
tree | 9fcebc1a9017b7485859128bb29579456d607d18 /src/map/status.c | |
parent | 2b71c036298756d294d10141ce6196a48d783930 (diff) | |
download | hercules-8aee60e91807930e4d43965a20c8991b416d7f29.tar.gz hercules-8aee60e91807930e4d43965a20c8991b416d7f29.tar.bz2 hercules-8aee60e91807930e4d43965a20c8991b416d7f29.tar.xz hercules-8aee60e91807930e4d43965a20c8991b416d7f29.zip |
Multiple SC fixes
First and foremost an ancient status_change_timer issue which'd cause a timer deletion error when an status within status_change_timer kills the unit.
This commit also fixes some pointer/map-free-block logic which showed up while debugging status_change_timer.
Special Thanks to Haruna.
Signed-off-by: shennetsind <ind@henn.et>
Diffstat (limited to 'src/map/status.c')
-rw-r--r-- | src/map/status.c | 60 |
1 files changed, 44 insertions, 16 deletions
diff --git a/src/map/status.c b/src/map/status.c index b278324b0..c2b634665 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -9634,7 +9634,8 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t } break; case SC_CASH_BOSS_ALARM: - clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message + if( sd ) + clif->bossmapinfo(sd->fd, map->id2boss(sce->val1), 0); // First Message break; case SC_MER_HP: status_percent_heal(bl, 100, 0); // Recover Full HP @@ -9778,7 +9779,6 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const nullpo_ret(bl); sc = status->get_sc(bl); - st = status->get_status_data(bl); if(type < 0 || type >= SC_MAX || !sc || !(sce = sc->data[type])) return 0; @@ -9788,6 +9788,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (sce->timer != tid && tid != INVALID_TIMER) return 0; + st = status->get_status_data(bl); + if( sd && sce->timer == INVALID_TIMER && !sd->state.loggingout ) chrif->del_scdata_single(sd->status.account_id,sd->status.char_id,type); @@ -9969,7 +9971,9 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const } sce->val2 = 0; - skill->del_unitgroup(group,ALC_MARK); + + if( group ) + skill->del_unitgroup(group,ALC_MARK); } if ((sce->val1&0xFFFF) == CG_MOONLIT) @@ -10072,7 +10076,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const if (sce->val3) { //Clear the group. struct skill_unit_group* group = skill->id2group(sce->val3); sce->val3 = 0; - skill->del_unitgroup(group,ALC_MARK); + if( group ) + skill->del_unitgroup(group,ALC_MARK); } break; case SC_HERMODE: @@ -10118,10 +10123,12 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const break; // Note: vending/buying is closed by unit_remove_map, no // need to do it here. - map->quit(sd); - // Because map->quit calls status_change_end with tid -1 - // from here it's not neccesary to continue - return 1; + if( sd ) { + map->quit(sd); + // Because map->quit calls status_change_end with tid -1 + // from here it's not neccesary to continue + return 1; + } break; case SC_STOP: if( sce->val2 ) { @@ -10227,7 +10234,8 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const struct block_list *src = map->id2bl(sce->val2); if(src) { struct status_change *ssc = status->get_sc(src); - ssc->bs_counter--; + if( ssc ) + ssc->bs_counter--; } } break; @@ -10568,6 +10576,8 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { ShowError("status_change_timer: Mismatch for type %d: %d != %d (bl id %d)\n",type,tid,sce->timer, bl->id); return 0; } + + sce->timer = INVALID_TIMER; sd = BL_CAST(BL_PC, bl); @@ -10598,7 +10608,6 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } sc_timer_next(sce->val2+tick, status->change_timer, bl->id, data); return 0; - break; case SC_SKA: if(--(sce->val2)>0) { @@ -10927,6 +10936,8 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } if( !flag ) { // Random Skill Cast + map->freeblock_lock(); + if (sd && !pc_issit(sd)) { //can't cast if sit int mushroom_skill_id = 0; unit->stop_attack(bl); @@ -10950,7 +10961,10 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { } clif->emotion(bl,E_HEH); - sc_timer_next(4000+tick,status->change_timer,bl->id,data); + if( sc->data[type] ) + sc_timer_next(4000+tick,status->change_timer,bl->id,data); + + map->freeblock_unlock(); } return 0; } @@ -10998,8 +11012,15 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { int heal = st->max_hp * 3 / 100; if (sc->count && sc->data[SC_AKAITSUKI] && heal) heal = ~heal + 1; + + map->freeblock_lock(); + status->heal(bl, heal, 0, 2); - sc_timer_next(5000 + tick, status->change_timer, bl->id, data); + if( sc->data[type] ) { + sc_timer_next(5000 + tick, status->change_timer, bl->id, data); + } + map->freeblock_unlock(); + return 0; } break; @@ -11117,8 +11138,8 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { if ( sc->data[type] ) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } - map->freeblock_unlock(); status->heal(src, damage*(5 + 5 * sce->val1)/100, 0, 0); // 5 + 5% per level + map->freeblock_unlock(); return 0; } break; @@ -11225,6 +11246,7 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { sc_timer_next(1000 + tick, status->change_timer, bl->id, data); } map->freeblock_unlock(); + return 0; } break; @@ -11305,12 +11327,13 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { case SC_WATER_DROP: case SC_WIND_CURTAIN: case SC_STONE_SHIELD: - if(status->charge(bl, 0, sce->val2) && (sce->val4==-1 || (sce->val4-=sce->val3)>=0)) + if(status->charge(bl, 0, sce->val2) && (sce->val4==-1 || (sce->val4-=sce->val3)>=0)) { sc_timer_next(sce->val3 + tick, status->change_timer, bl->id, data); - else + return 0; + } else if (bl->type == BL_ELEM) elemental->change_mode(BL_CAST(BL_ELEM,bl),MAX_ELESKILLTREE); - return 0; + break; case SC_STOMACHACHE: if( --(sce->val4) > 0 ) { @@ -11696,6 +11719,8 @@ int status_change_clear_buffs (struct block_list* bl, int type) { if (!sc || !sc->count) return 0; + map->freeblock_lock(); + if (type&6) //Debuffs for (i = SC_COMMON_MIN; i <= SC_COMMON_MAX; i++) status_change_end(bl, (sc_type)i, INVALID_TIMER); @@ -11742,6 +11767,9 @@ int status_change_clear_buffs (struct block_list* bl, int type) { } status_change_end(bl, (sc_type)i, INVALID_TIMER); } + + map->freeblock_unlock(); + return 0; } |