summaryrefslogtreecommitdiff
path: root/src/map/unit.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/unit.c')
-rw-r--r--src/map/unit.c181
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;