From 4ef11952653e142f8a6f28194fa56eb615860339 Mon Sep 17 00:00:00 2001 From: skotlex Date: Tue, 30 May 2006 17:06:55 +0000 Subject: - Removed the on-die specific code from unit_remove_map and placed it on the corresponding *_dead functions. unit_remove_map should never assume the char died, it is just a "remove from map" function. - Updated status_damage to handle the general death code (clearing status changes, clearing skill related data, sending death packet, etc). The return value from the *_dead functions will tell it what to do or not with the object (death aborted, clear it from map/memory, etc) - Cleaned up pc_dead to take advantage of the fact that status changes are not ended until after the function. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@6852 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/atcommand.c | 5 ++-- src/map/mercenary.c | 8 +------ src/map/mob.c | 37 ++++++++++++++++-------------- src/map/pc.c | 46 ++++++++++++++----------------------- src/map/script.c | 6 ++--- src/map/status.c | 66 +++++++++++++++++++++++++++++++++++++++++++++-------- src/map/unit.c | 28 +++-------------------- 7 files changed, 102 insertions(+), 94 deletions(-) (limited to 'src/map') diff --git a/src/map/atcommand.c b/src/map/atcommand.c index 4b61c5f74..bf0d3e2da 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -3690,9 +3690,8 @@ static int atkillmonster_sub(struct block_list *bl, va_list ap) { if (flag) status_kill(bl); - else - unit_remove_map(&md->bl,1); - + else //FIXME: Eh.. what exactly is the difference here? + status_kill(bl); return 1; } void atcommand_killmonster_sub( diff --git a/src/map/mercenary.c b/src/map/mercenary.c index d6e2c06be..335bd54fa 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -102,14 +102,8 @@ void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp) int merc_dead(struct homun_data *hd, struct block_list *src) { //dead lol - clif_clearchar((struct block_list*)hd,1); - hd->bl.m = 0; - hd->bl.x = 0; - hd->bl.y = 0; //send it somewhere where it doesn't bother us merc_save(hd); - clif_clearchar_area(&hd->bl,0); - map_delblock(&hd->bl); - return 1; + return 3; //Remove it from map. } void merc_skillup(struct map_session_data *sd,short skillnum) diff --git a/src/map/mob.c b/src/map/mob.c index d7442dcdf..929565511 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -883,10 +883,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) bl=map_id2bl(md->master_id); if (!bl || status_isdead(bl)) { //主が死亡しているか見つからない - if(md->special_state.ai) - unit_remove_map(&md->bl, 1); - else - status_kill(&md->bl); + status_kill(&md->bl); return 0; } @@ -921,10 +918,7 @@ static int mob_ai_sub_hard_slavemob(struct mob_data *md,unsigned int tick) } } else if (bl->m != md->bl.m && map_flag_gvg(md->bl.m)) { //Delete the summoned mob if it's in a gvg ground and the master is elsewhere. [Skotlex] - if(md->special_state.ai) - unit_remove_map(&md->bl, 1); - else - status_kill(&md->bl); + status_kill(&md->bl); return 0; } @@ -1695,19 +1689,13 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) } md->state.skillstate = MSS_DEAD; - md->status.hp = 1; //Otherwise skill will be blocked due to being dead! [Skotlex] mobskill_use(md,tick,-1); //On Dead skill. - md->status.hp = 0; if (md->sc.data[SC_KAIZEL].timer != -1) { //Revive in a bit. - mob_unlocktarget(md,tick); - mob_stop_walking(md, 0); - clif_clearchar_area(&md->bl,1); add_timer(gettick()+3000, mob_respawn, md->bl.id, 10*md->sc.data[SC_KAIZEL].val1); //% of life to rebirth with - status_change_end(&md->bl, SC_KAIZEL, -1); map_delblock(&md->bl); - return 0; + return 1; //Return 1 to only clear the object. } map_freeblock_lock(); @@ -2134,9 +2122,24 @@ int mob_dead(struct mob_data *md, struct block_list *src, int type) npc_script_event(mvp_sd, NPCE_KILLNPC); // PCKillNPC [Lance] } if(md->level) md->level=0; + + if(md->deletetimer!=-1) { + delete_timer(md->deletetimer,mob_timer_delete); + md->deletetimer=-1; + } + if(pcdb_checkid(md->vd->class_)) //Player mobs are not removed automatically by the client. + clif_clearchar_delay(tick+3000,&md->bl,0); + + mob_deleteslave(md); + md->last_deadtime=tick; + map_freeblock_unlock(); - unit_remove_map(&md->bl,1); - return 1; + + if(!md->spawn) //Tell status_damage to remove it from memory. + return 5; + + mob_setdelayspawn(md); //Set respawning. + return 3; //Remove from map. } void mob_revive(struct mob_data *md, unsigned int hp) diff --git a/src/map/pc.c b/src/map/pc.c index 2040b5ebf..8f8e6749c 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -4432,9 +4432,8 @@ void pc_damage(struct map_session_data *sd,struct block_list *src,unsigned int h int pc_dead(struct map_session_data *sd,struct block_list *src) { - int i=0,j=0,resurrect_flag=0,baby_flag=0; + int i=0,j=0; unsigned int tick = gettick(); - struct status_data *status = &sd->battle_status; if(sd->vender_id) vending_closevending(sd); @@ -4458,20 +4457,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if(sd->duel_invite > 0) duel_reject(sd->duel_invite, sd); } - - //SC data that will be needed later on. - resurrect_flag = (sd->sc.data[SC_KAIZEL].timer != -1)?sd->sc.data[SC_KAIZEL].val1:0; - baby_flag = (sd->sc.data[SC_BABY].timer != -1)?1:0; - pc_stop_attack(sd); - pc_stop_walking(sd,0); - unit_skillcastcancel(&sd->bl,0); - clif_clearchar_area(&sd->bl,1); pc_setdead(sd); - skill_unit_move(&sd->bl,tick,4); - if (battle_config.clear_unit_ondeath) - skill_clear_unitgroup(&sd->bl); //orn - status_change_clear(&sd->bl,0); sd->canregen_tick = tick; pc_setglobalreg(sd,"PC_DIE_COUNTER",++sd->die_counter); @@ -4599,7 +4586,7 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) if(battle_config.death_penalty_type && sd->state.snovice_flag != 4 && (sd->class_&MAPID_UPPERMASK) != MAPID_NOVICE // only novices will receive no penalty && !map[sd->bl.m].flag.nopenalty && !map_flag_gvg(sd->bl.m) - && !baby_flag) + && sd->sc.data[SC_BABY].timer == -1) { unsigned int base_penalty =0; if (battle_config.death_penalty_base > 0) { @@ -4715,27 +4702,28 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) return 1; } - if (sd->state.snovice_flag == 4 || resurrect_flag) + if (sd->sc.count && sd->sc.data[SC_KAIZEL].timer != -1) { clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,1,1); - pc_setstand(sd); - status->hp = 1; - if (sd->state.snovice_flag == 4 || - sd->special_state.restart_full_recover) { + if(sd->special_state.restart_full_recover) status_percent_heal(&sd->bl, 100, 100); - } else { //10% life per each level in Kaizel - status_percent_heal(&sd->bl, 10*resurrect_flag, 0); - } - clif_updatestatus(sd, SP_HP); - clif_updatestatus(sd, SP_SP); + else + status_percent_heal(&sd->bl, 10*sd->sc.data[SC_KAIZEL].val1, 0); + if(battle_config.pc_invincible_time) + pc_setinvincibletimer(sd, battle_config.pc_invincible_time); + sc_start(&sd->bl,SkillStatusChangeTable[PR_KYRIE],100,10,skill_get_time2(SL_KAIZEL,sd->sc.data[SC_KAIZEL].val1)); + status_change_end(&sd->bl,SC_KAIZEL,-1); + return 0; + } + if (sd->state.snovice_flag == 4) + { + clif_skill_nodamage(&sd->bl,&sd->bl,ALL_RESURRECTION,1,1); + status_percent_heal(&sd->bl, 100, 100); clif_resurrection(&sd->bl, 1); sd->state.snovice_flag = 0; if(battle_config.pc_invincible_time) pc_setinvincibletimer(sd, battle_config.pc_invincible_time); - if (resurrect_flag) - sc_start(&sd->bl,SkillStatusChangeTable[PR_KYRIE],100,10,skill_get_time2(SL_KAIZEL, resurrect_flag)); - else - sc_start(&sd->bl,SkillStatusChangeTable[MO_STEELBODY],100,1,skill_get_time(MO_STEELBODY,1)); + sc_start(&sd->bl,SkillStatusChangeTable[MO_STEELBODY],100,1,skill_get_time(MO_STEELBODY,1)); return 0; } diff --git a/src/map/script.c b/src/map/script.c index f0ce4f200..41d84a92a 100644 --- a/src/map/script.c +++ b/src/map/script.c @@ -5732,11 +5732,11 @@ int buildin_killmonster_sub(struct block_list *bl,va_list ap) if(!allflag){ if(strcmp(event,md->npc_event)==0) - unit_remove_map(bl,1); + status_kill(bl); return 0; }else{ if(!md->spawn) - unit_remove_map(bl,1); + status_kill(bl); return 0; } return 0; @@ -5760,7 +5760,7 @@ int buildin_killmonster(struct script_state *st) int buildin_killmonsterall_sub(struct block_list *bl,va_list ap) { - unit_remove_map(bl,1); + status_kill(bl); return 0; } int buildin_killmonsterall(struct script_state *st) diff --git a/src/map/status.c b/src/map/status.c index 7b95364b8..0ef6c3904 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -584,23 +584,69 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s { case BL_MOB: mob_damage((TBL_MOB*)target, src, hp); - if (!status->hp) - mob_dead((TBL_MOB*)target, src, flag&4?3:0); break; case BL_PC: pc_damage((TBL_PC*)target,src,hp,sp); - if (!status->hp) - pc_dead((TBL_PC*)target,src); break; case BL_HOMUNCULUS: merc_damage((TBL_HOMUNCULUS*)target,src,hp,sp); - if (!status->hp) - merc_dead((TBL_HOMUNCULUS*)target,src); } - - if (walkdelay && status->hp) - unit_set_walkdelay(target, gettick(), walkdelay, 0); - + + if (status->hp) + { //Still lives! + if (walkdelay) + unit_set_walkdelay(target, gettick(), walkdelay, 0); + return hp+sp; + } + + status->hp = 1; //To let the dead function cast skills and all that. + //NOTE: These dead functions should return: [Skotlex] + //0: Death cancelled, auto-revived. + //Non-zero: Standard death. Clear status, cancel move/attack, etc + //&2: Also remove object from map. + //&4: Also delete object from memory. + switch (target->type) + { + case BL_MOB: + flag = mob_dead((TBL_MOB*)target, src, flag&4?3:0); + break; + case BL_PC: + flag = pc_dead((TBL_PC*)target,src); + break; + case BL_HOMUNCULUS: + flag = merc_dead((TBL_HOMUNCULUS*)target,src); + break; + default: //Unhandled case, do nothing to object. + flag = 0; + break; + } + + if(!flag) //Death cancelled. + return hp+sp; + + //Normal death + if (battle_config.clear_unit_ondeath && + battle_config.clear_unit_ondeath&target->type) + skill_clear_unitgroup(target); + status_change_clear(target,0); + + if(flag&2) //remove the unit from the map. + unit_remove_map(target,1); + else { //These are handled by unit_remove_map. + unit_stop_attack(target); + unit_stop_walking(target,0); + unit_skillcastcancel(target,0); + clif_clearchar_area(target,1); + skill_unit_move(target,gettick(),4); + skill_cleartimerskill(target); + } + + if(flag&4) { //Delete from memory. + map_delblock(target); + unit_free(target); + } + + return hp+sp; } diff --git a/src/map/unit.c b/src/map/unit.c index 02a95fd34..78e403aea 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1433,6 +1433,7 @@ int unit_changeviewsize(struct block_list *bl,short size) * Returns 1 on success. 0 if it couldn't be removed or the bl was free'd * if clrtype is 1 (death), appropiate cleanup is performed. * 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, int clrtype) { @@ -1455,9 +1456,7 @@ int unit_remove_map(struct block_list *bl, int clrtype) { ud->attackabletime = ud->canmove_tick = ud->canact_tick = gettick(); clif_clearchar_area(bl,clrtype); - if (clrtype == 1) //Death. Remove all status changes. - status_change_clear(bl,0); - else if(sc && sc->count ) { //map-change/warp dispells. + if(sc && sc->count ) { //map-change/warp dispells. if(sc->data[SC_BLADESTOP].timer!=-1) status_change_end(bl,SC_BLADESTOP,-1); if(sc->data[SC_BASILICA].timer!=-1) @@ -1488,9 +1487,6 @@ int unit_remove_map(struct block_list *bl, int clrtype) { status_change_end(bl, SC_GOSPEL, -1); } - if (clrtype == 1 && battle_config.clear_unit_ondeath && //Clrtype 1 = died. - battle_config.clear_unit_ondeath&bl->type) - skill_clear_unitgroup(bl); // スキルユニットグループの削除 if (bl->type&BL_CHAR) { skill_unit_move(bl,gettick(),4); skill_cleartimerskill(bl); // タイマースキルクリア @@ -1537,25 +1533,7 @@ int unit_remove_map(struct block_list *bl, int clrtype) { struct mob_data *md = (struct mob_data*)bl; md->target_id=0; md->attacked_id=0; - md->state.skillstate= clrtype==1?MSS_DEAD:MSS_IDLE; - if (md->master_id) md->master_dist = 0; - if (clrtype == 1) { //Death. - md->last_deadtime=gettick(); - if(md->deletetimer!=-1) - delete_timer(md->deletetimer,mob_timer_delete); - md->deletetimer=-1; - if(pcdb_checkid(md->vd->class_)) //Player mobs are not removed automatically by the client. - clif_clearchar_delay(gettick()+3000,bl,0); - mob_deleteslave(md); - - if(!md->spawn) { - map_delblock(bl); - unit_free(bl); //Mob does not respawn. - map_freeblock_unlock(); - return 0; - } - mob_setdelayspawn(md); //Set respawning. - } + md->state.skillstate= MSS_IDLE; } else if (bl->type == BL_PET) { struct pet_data *pd = (struct pet_data*)bl; struct map_session_data *sd = pd->msd; -- cgit v1.2.3-70-g09d2