diff options
Diffstat (limited to 'src/map/unit.c')
-rw-r--r-- | src/map/unit.c | 181 |
1 files changed, 127 insertions, 54 deletions
diff --git a/src/map/unit.c b/src/map/unit.c index bea0913d2..00c78054b 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -2,7 +2,7 @@ * This file is part of Hercules. * http://herc.ws - http://github.com/HerculesWS/Hercules * - * Copyright (C) 2012-2015 Hercules Dev Team + * Copyright (C) 2012-2016 Hercules Dev Team * Copyright (C) Athena Dev Teams * * Hercules is free software: you can redistribute it and/or modify @@ -235,8 +235,8 @@ int unit_step_timer(int tid, int64 tick, int id, intptr_t data) return 1; } - -int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { +int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) +{ int i; int x,y,dx,dy; unsigned char icewall_walk_block; @@ -487,7 +487,8 @@ int unit_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } -int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) { +int unit_delay_walktoxy_timer(int tid, int64 tick, int id, intptr_t data) +{ struct block_list *bl = map->id2bl(id); if (!bl || bl->prev == NULL) @@ -570,7 +571,8 @@ static inline void set_mobstate(struct block_list* bl, int flag) md->state.skillstate = md->state.aggressive ? MSS_FOLLOW : MSS_RUSH; } -int unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) { +int unit_walktobl_sub(int tid, int64 tick, int id, intptr_t data) +{ struct block_list *bl = map->id2bl(id); struct unit_data *ud = bl?unit->bl2ud(bl):NULL; @@ -649,22 +651,29 @@ int unit_walktobl(struct block_list *bl, struct block_list *tbl, int range, int * Called by unit_run when an object was hit * @param sd Required only when using SC_WUGDASH **/ -void unit_run_hit( struct block_list *bl, struct status_change *sc, struct map_session_data *sd, enum sc_type type ) { - int lv = sc->data[type]->val1; +void unit_run_hit(struct block_list *bl, struct status_change *sc, struct map_session_data *sd, enum sc_type type) +{ + int lv; + struct unit_data *ud; + Assert_retv(type >= 0 && type < SC_MAX); + lv = sc->data[type]->val1; //If you can't run forward, you must be next to a wall, so bounce back. [Skotlex] if( type == SC_RUN ) clif->sc_load(bl,bl->id,AREA,SI_TING,0,0,0); + ud = unit->bl2ud(bl); + nullpo_retv(ud); //Set running to 0 beforehand so status_change_end knows not to enable spurt [Kevin] - unit->bl2ud(bl)->state.running = 0; + ud->state.running = 0; status_change_end(bl, type, INVALID_TIMER); - if( type == SC_RUN ) { - skill->blown(bl,bl,skill->get_blewcount(TK_RUN,lv),unit->getdir(bl),0); + if (type == SC_RUN) { + if (lv > 0) + skill->blown(bl, bl, skill->get_blewcount(TK_RUN, lv), unit->getdir(bl), 0); clif->fixpos(bl); //Why is a clif->slide (skill->blown) AND a fixpos needed? Ask Aegis. - clif->sc_end(bl,bl->id,AREA,SI_TING); - } else if( sd ) { + clif->sc_end(bl, bl->id, AREA, SI_TING); + } else if (sd) { clif->fixpos(bl); skill->castend_damage_id(bl, &sd->bl, RA_WUGDASH, lv, timer->gettick(), SD_LEVEL); } @@ -677,7 +686,8 @@ void unit_run_hit( struct block_list *bl, struct status_change *sc, struct map_s * @retval true Finished running * @retval false Hit an object/Couldn't run **/ -bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type type ) { +bool unit_run(struct block_list *bl, struct map_session_data *sd, enum sc_type type) +{ struct status_change *sc; short to_x,to_y,dir_x,dir_y; int i; @@ -737,15 +747,19 @@ bool unit_run( struct block_list *bl, struct map_session_data *sd, enum sc_type } //Makes bl attempt to run dist cells away from target. Uses hard-paths. -int unit_escape(struct block_list *bl, struct block_list *target, short dist) { - uint8 dir = map->calc_dir(target, bl->x, bl->y); +int unit_escape(struct block_list *bl, struct block_list *target, short dist) +{ + uint8 dir; + nullpo_ret(bl); + dir = map->calc_dir(target, bl->x, bl->y); while (dist > 0 && map->getcell(bl->m, bl, bl->x + dist * dirx[dir], bl->y + dist * diry[dir], CELL_CHKNOREACH)) dist--; return ( dist > 0 && unit->walktoxy(bl, bl->x + dist*dirx[dir], bl->y + dist*diry[dir], 0) ); } //Instant warp function. -int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath) { +int unit_movepos(struct block_list *bl, short dst_x, short dst_y, int easy, bool checkpath) +{ short dx,dy; uint8 dir; struct unit_data *ud = NULL; @@ -821,7 +835,8 @@ int unit_setdir(struct block_list *bl,unsigned char dir) return 0; } -uint8 unit_getdir(struct block_list *bl) { +uint8 unit_getdir(struct block_list *bl) +{ struct unit_data *ud; nullpo_ret(bl); @@ -937,7 +952,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) if (x<0 || y<0) { //Random map position. if (!map->search_freecell(NULL, m, &x, &y, -1, -1, 1)) { - ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); + ShowWarning("unit_warp failed. Unit Id:%d/Type:%u, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); return 2; } @@ -947,7 +962,7 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) if (!map->search_freecell(NULL, m, &x, &y, 4, 4, 1)) { //Can't find a nearby cell - ShowWarning("unit_warp failed. Unit Id:%d/Type:%d, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); + ShowWarning("unit_warp failed. Unit Id:%d/Type:%u, target position map %d (%s) at [%d,%d]\n", bl->id, bl->type, m, map->list[m].name, x, y); return 2; } } @@ -978,7 +993,8 @@ int unit_warp(struct block_list *bl,short m,short x,short y,clr_type type) * Flag values: @see unit_stopwalking_flag. * Upper bytes may be used for other purposes depending on the unit type. *------------------------------------------*/ -int unit_stop_walking(struct block_list *bl, int flag) { +int unit_stop_walking(struct block_list *bl, int flag) +{ struct unit_data *ud; const struct TimerData* td; int64 tick; @@ -1040,7 +1056,8 @@ int unit_is_walking(struct block_list *bl) /*========================================== * Determines if the bl can move based on status changes. [Skotlex] *------------------------------------------*/ -int unit_can_move(struct block_list *bl) { +int unit_can_move(struct block_list *bl) +{ struct map_session_data *sd; struct unit_data *ud; struct status_change *sc; @@ -1053,8 +1070,18 @@ int unit_can_move(struct block_list *bl) { if (!ud) return 0; - if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK && (!sd || !pc->checkskill(sd, SA_FREECAST) || skill->get_inf2(ud->skill_id)&INF2_GUILD_SKILL)) - return 0; // prevent moving while casting + if (ud->skilltimer != INVALID_TIMER && ud->skill_id != LG_EXEEDBREAK) { + // Prevent moving while casting + if (sd == NULL) + return 0; // Only players are affected by SA_FREECAST and similar + if ((skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) == 0) { + // Skills with an explicit free cast setting always allow walking regardless of SA_FREECAST + if ((skill->get_inf2(ud->skill_id) & INF2_GUILD_SKILL) != 0) + return 0; // SA_FREECAST doesn't affect guild skills + if (pc->checkskill(sd, SA_FREECAST) == 0) + return 0; // SA_FREECAST not available + } + } if (DIFF_TICK(ud->canmove_tick, timer->gettick()) > 0) return 0; @@ -1101,6 +1128,7 @@ int unit_can_move(struct block_list *bl) { || sc->data[SC_VACUUM_EXTREME] || (sc->data[SC_FEAR] && sc->data[SC_FEAR]->val2 > 0) || sc->data[SC_NETHERWORLD] + || sc->data[SC_SUHIDE] || (sc->data[SC_SPIDERWEB] && sc->data[SC_SPIDERWEB]->val1) || (sc->data[SC_CLOAKING] && sc->data[SC_CLOAKING]->val1 < 3 && !(sc->data[SC_CLOAKING]->val4&1)) //Need wall at level 1-2 || ( @@ -1140,11 +1168,12 @@ int unit_can_move(struct block_list *bl) { * Resume running after a walk delay *------------------------------------------*/ -int unit_resume_running(int tid, int64 tick, int id, intptr_t data) { - +int unit_resume_running(int tid, int64 tick, int id, intptr_t data) +{ struct unit_data *ud = (struct unit_data *)data; struct map_session_data *sd = map->id2sd(id); + nullpo_ret(ud); if(sd && pc_isridingwug(sd)) clif->skill_nodamage(ud->bl,ud->bl,RA_WUGDASH,ud->skill_lv, sc_start4(ud->bl,ud->bl,status->skill2sc(RA_WUGDASH),100,ud->skill_lv,unit->getdir(ud->bl),0,0,1)); @@ -1164,10 +1193,12 @@ int unit_resume_running(int tid, int64 tick, int id, intptr_t data) { * if type is 0, this is a damage induced delay: if previous delay is active, do not change it. * if type is 1, this is a skill induced delay: walk-delay may only be increased, not decreased. *------------------------------------------*/ -int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) { +int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) +{ struct unit_data *ud = unit->bl2ud(bl); if (delay <= 0 || !ud) return 0; + nullpo_ret(bl); if (type) { //Bosses can ignore skill induced walkdelay (but not damage induced) if (bl->type == BL_MOB && (BL_UCCAST(BL_MOB, bl)->status.mode&MD_BOSS)) @@ -1203,7 +1234,9 @@ int unit_set_walkdelay(struct block_list *bl, int64 tick, int delay, int type) { return 1; } -int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) { +//-------------- stop here +int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, uint16 skill_lv, int casttime, int castcancel) +{ struct unit_data *ud; struct status_data *tstatus; struct status_change *sc; @@ -1220,6 +1253,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui ud = unit->bl2ud(src); if(ud == NULL) return 0; + sc = status->get_sc(src); if (sc && !sc->count) sc = NULL; //Unneeded @@ -1346,7 +1380,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui switch (skill_id){ case SA_CASTCANCEL: - if (ud->skill_id != skill_id){ + if (ud->skill_id != skill_id) { sd->skill_id_old = ud->skill_id; sd->skill_lv_old = ud->skill_lv; } @@ -1428,7 +1462,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } else if( src->type == BL_MER && skill_id == MA_REMOVETRAP ) { if( !battle->check_range(battle->get_master(src), target, range + 1) ) return 0; // Aegis calc remove trap based on Master position, ignoring mercenary O.O - } else if( !battle->check_range(src, target, range + (skill_id == RG_CLOSECONFINE?0:2)) ) { + } else if (!battle->check_range(src, target, range)) { return 0; // Arrow-path check failed. } } @@ -1476,7 +1510,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } break; case AB_CLEARANCE: - if( target->type != BL_MOB && battle->check_target(src,target,BCT_PARTY) <= 0 && sd ) { + if (target->type != BL_MOB && battle->check_target(src, target, BCT_PARTY) <= 0 && sd) { clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0); return 0; } @@ -1511,7 +1545,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } break; case GD_EMERGENCYCALL: //Emergency Call double cast when the user has learned Leap [Daegaladh] - if( sd && pc->checkskill(sd,TK_HIGHJUMP) ) + if (sd && (pc->checkskill(sd,TK_HIGHJUMP) || pc->checkskill(sd,SU_LOPE) >= 3)) casttime *= 2; break; case RA_WUGDASH: @@ -1536,7 +1570,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui } break; case NC_DISJOINT: - if( target->type == BL_PC ){ + if (target->type == BL_PC) { struct mob_data *md; if( (md = map->id2md(target->id)) && md->master_id != src->id ) casttime <<= 1; @@ -1573,7 +1607,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS);// even though this is not how official works but this will do the trick. bugreport:6829 // in official this is triggered even if no cast time. - clif->skillcasting(src, src->id, target_id, 0,0, skill_id, skill->get_ele(skill_id, skill_lv), casttime); + clif->useskill(src, src->id, target_id, 0,0, skill_id, skill_lv, casttime); if( casttime > 0 || temp ) { if (sd != NULL && target->type == BL_MOB) { @@ -1628,11 +1662,14 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui if (src->id != target->id) // self-targeted skills shouldn't show different direction unit->setdir(src, map->calc_dir(src, target->x, target->y)); ud->skilltimer = timer->add( tick+casttime, skill->castend_id, src->id, 0 ); - if( sd && (pc->checkskill(sd,SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK) ) + if (sd && (pc->checkskill(sd, SA_FREECAST) > 0 || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0)) status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); } else skill->castend_id(ud->skilltimer,tick,src->id,0); + if (sd != NULL && battle_config.prevent_logout_trigger & PLT_SKILL) + sd->canlog_tick = timer->gettick(); + return 1; } @@ -1768,17 +1805,21 @@ int unit_skilluse_pos2( struct block_list *src, short skill_x, short skill_y, ui unit->stop_walking(src, STOPWALKING_FLAG_FIXPOS); // in official this is triggered even if no cast time. - clif->skillcasting(src, src->id, 0, skill_x, skill_y, skill_id, skill->get_ele(skill_id, skill_lv), casttime); + clif->useskill(src, src->id, 0, skill_x, skill_y, skill_id, skill_lv, casttime); if( casttime > 0 ) { unit->setdir(src, map->calc_dir(src, skill_x, skill_y)); ud->skilltimer = timer->add( tick+casttime, skill->castend_pos, src->id, 0 ); - if ( (sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK ) { + if ((sd && pc->checkskill(sd, SA_FREECAST) > 0) || skill_id == LG_EXEEDBREAK || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0) { status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); } } else { ud->skilltimer = INVALID_TIMER; skill->castend_pos(ud->skilltimer,tick,src->id,0); } + + if (sd != NULL && battle_config.prevent_logout_trigger & PLT_SKILL) + sd->canlog_tick = timer->gettick(); + return 1; } @@ -1853,6 +1894,7 @@ void unit_stop_stepaction(struct block_list *bl) int unit_unattackable(struct block_list *bl) { struct unit_data *ud = unit->bl2ud(bl); + nullpo_ret(bl); if (ud) { ud->state.attack_continue = 0; ud->state.step_attack = 0; @@ -1870,11 +1912,13 @@ int unit_unattackable(struct block_list *bl) * Attack request * If type is an ongoing attack *------------------------------------------*/ -int unit_attack(struct block_list *src,int target_id,int continuous) { +int unit_attack(struct block_list *src, int target_id, int continuous) +{ struct block_list *target; struct unit_data *ud; int range; + nullpo_ret(src); nullpo_ret(ud = unit->bl2ud(src)); target = map->id2bl(target_id); @@ -1942,6 +1986,7 @@ int unit_cancel_combo(struct block_list *bl) { struct unit_data *ud; + nullpo_ret(bl); if (!status_change_end(bl, SC_COMBOATTACK, INVALID_TIMER)) return 0; //Combo wasn't active. @@ -2078,7 +2123,8 @@ int unit_calc_pos(struct block_list *bl, int tx, int ty, uint8 dir) /*========================================== * Continuous Attack (function timer) *------------------------------------------*/ -int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { +int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) +{ struct block_list *target; struct unit_data *ud; struct status_data *sstatus; @@ -2117,10 +2163,10 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { return 0; } - if( ud->skilltimer != INVALID_TIMER && !(sd && pc->checkskill(sd,SA_FREECAST) > 0) ) + if (ud->skilltimer != INVALID_TIMER && !(sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) != 0))) return 0; // can't attack while casting - if( !battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick,tick) > 0 && !(sd && pc->checkskill(sd,SA_FREECAST) > 0) ) + if (!battle_config.sdelay_attack_enable && DIFF_TICK(ud->canact_tick, tick) > 0 && !(sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & (INF2_FREE_CAST_REDUCED | INF2_FREE_CAST_NORMAL)) != 0))) { // attacking when under cast delay has restrictions: if( tid == INVALID_TIMER ) { //requested attack. if(sd) clif->skill_fail(sd,1,USESKILL_FAIL_SKILLINTERVAL,0); @@ -2214,10 +2260,14 @@ int unit_attack_timer_sub(struct block_list* src, int tid, int64 tick) { ud->attacktimer = timer->add(ud->attackabletime,unit->attack_timer,src->id,0); } + if (sd != NULL && battle_config.prevent_logout_trigger & PLT_ATTACK) + sd->canlog_tick = timer->gettick(); + return 1; } -int unit_attack_timer(int tid, int64 tick, int id, intptr_t data) { +int unit_attack_timer(int tid, int64 tick, int id, intptr_t data) +{ struct block_list *bl; bl = map->id2bl(id); if(bl && unit->attack_timer_sub(bl, tid, tick) == 0) @@ -2269,7 +2319,7 @@ int unit_skillcastcancel(struct block_list *bl,int type) ud->skilltimer = INVALID_TIMER; - if( sd && pc->checkskill(sd,SA_FREECAST) > 0 ) + if (sd && (pc->checkskill(sd, SA_FREECAST) > 0 || (skill->get_inf2(ud->skill_id) & INF2_FREE_CAST_REDUCED) != 0)) status_calc_bl(&sd->bl, SCB_SPEED|SCB_ASPD); if( sd ) { @@ -2288,12 +2338,20 @@ int unit_skillcastcancel(struct block_list *bl,int type) } // unit_data initialization process -void unit_dataset(struct block_list *bl) { - struct unit_data *ud; - nullpo_retv(ud = unit->bl2ud(bl)); +void unit_dataset(struct block_list *bl) +{ + struct unit_data *ud = unit->bl2ud(bl); + nullpo_retv(ud); - memset( ud, 0, sizeof( struct unit_data) ); - ud->bl = bl; + unit->init_ud(ud); + ud->bl = bl; +} + +void unit_init_ud(struct unit_data *ud) +{ + nullpo_retv(ud); + + memset (ud, 0, sizeof(struct unit_data)); ud->walktimer = INVALID_TIMER; ud->skilltimer = INVALID_TIMER; ud->attacktimer = INVALID_TIMER; @@ -2317,7 +2375,8 @@ int unit_counttargeted(struct block_list* bl) /*========================================== * *------------------------------------------*/ -int unit_fixdamage(struct block_list *src, struct block_list *target, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2) { +int unit_fixdamage(struct block_list *src, struct block_list *target, int sdelay, int ddelay, int64 damage, short div, unsigned char type, int64 damage2) +{ nullpo_ret(target); if(damage+damage2 <= 0) @@ -2353,9 +2412,11 @@ int unit_changeviewsize(struct block_list *bl,short size) * Otherwise it is assumed bl is being warped. * On-Kill specific stuff is not performed here, look at status->damage for that. *------------------------------------------*/ -int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func) { +int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, int line, const char* func) +{ struct unit_data *ud = unit->bl2ud(bl); struct status_change *sc = status->get_sc(bl); + nullpo_ret(bl); nullpo_ret(ud); if(bl->prev == NULL) @@ -2415,6 +2476,8 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i status_change_end(bl, SC_VACUUM_EXTREME, INVALID_TIMER); status_change_end(bl, SC_CURSEDCIRCLE_ATKER, INVALID_TIMER); //callme before warp status_change_end(bl, SC_NETHERWORLD, INVALID_TIMER); + status_change_end(bl, SC_SUHIDE, INVALID_TIMER); + status_change_end(bl, SC_SV_ROOTTWIST, INVALID_TIMER); } if (bl->type&(BL_CHAR|BL_PET)) { @@ -2433,7 +2496,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i status_change_end(d_bl,SC__SHADOWFORM,INVALID_TIMER); } //Leave/reject all invitations. - if(sd->chatID) + if (sd->chat_id != 0) chat->leave(sd, false); if(sd->trade_partner) trade->cancel(sd); @@ -2597,6 +2660,7 @@ int unit_remove_map(struct block_list *bl, clr_type clrtype, const char* file, i void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype) { + nullpo_retv(sd); unit->remove_map(&sd->bl,clrtype,ALC_MARK); //CLR_RESPAWN is the warp from logging out, CLR_TELEPORT is the warp from teleporting, but pets/homunc need to just 'vanish' instead of showing the warping animation. @@ -2614,6 +2678,7 @@ void unit_remove_map_pc(struct map_session_data *sd, clr_type clrtype) void unit_free_pc(struct map_session_data *sd) { + nullpo_retv(sd); if (sd->pd) unit->free(&sd->pd->bl,CLR_OUTSIGHT); if (sd->hd) unit->free(&sd->hd->bl,CLR_OUTSIGHT); if (sd->md) unit->free(&sd->md->bl,CLR_OUTSIGHT); @@ -2625,8 +2690,10 @@ void unit_free_pc(struct map_session_data *sd) * Function to free all related resources to the bl * if unit is on map, it is removed using the clrtype specified *------------------------------------------*/ -int unit_free(struct block_list *bl, clr_type clrtype) { +int unit_free(struct block_list *bl, clr_type clrtype) +{ struct unit_data *ud = unit->bl2ud( bl ); + nullpo_ret(bl); nullpo_ret(ud); map->freeblock_lock(); @@ -2690,6 +2757,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) { sd->instance = NULL; } VECTOR_CLEAR(sd->script_queues); + VECTOR_CLEAR(sd->storage.item); + sd->storage.received = false; if( sd->quest_log != NULL ) { aFree(sd->quest_log); sd->quest_log = NULL; @@ -2870,7 +2939,8 @@ int unit_free(struct block_list *bl, clr_type clrtype) { return 0; } -int do_init_unit(bool minimal) { +int do_init_unit(bool minimal) +{ if (minimal) return 0; @@ -2882,12 +2952,14 @@ int do_init_unit(bool minimal) { return 0; } -int do_final_unit(void) { +int do_final_unit(void) +{ // nothing to do return 0; } -void unit_defaults(void) { +void unit_defaults(void) +{ unit = &unit_s; unit->init = do_init_unit; @@ -2895,6 +2967,7 @@ void unit_defaults(void) { /* */ unit->bl2ud = unit_bl2ud; unit->bl2ud2 = unit_bl2ud2; + unit->init_ud = unit_init_ud; unit->attack_timer = unit_attack_timer; unit->walktoxy_timer = unit_walktoxy_timer; unit->walktoxy_sub = unit_walktoxy_sub; |