summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt9
-rw-r--r--src/map/atcommand.c5
-rw-r--r--src/map/mercenary.c8
-rw-r--r--src/map/mob.c37
-rw-r--r--src/map/pc.c46
-rw-r--r--src/map/script.c6
-rw-r--r--src/map/status.c66
-rw-r--r--src/map/unit.c28
8 files changed, 111 insertions, 94 deletions
diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt
index b71a20edf..169576f00 100644
--- a/Changelog-Trunk.txt
+++ b/Changelog-Trunk.txt
@@ -4,6 +4,15 @@ 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.
2006/05/30
+ * 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. [Skotlex]
+ * 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) [Skotlex]
+ * Cleaned up pc_dead to take advantage of the fact that status changes are
+ not ended until after the function. [Skotlex]
* Disabled ontouch npcs triggering on hidden/chase-walk characters.
[Skotlex]
* Updated/adapted current Homun code to use the status_data update.
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;