From 5a6f4e191743aca6fe6f4bbb3e371df4fe9a7100 Mon Sep 17 00:00:00 2001 From: skotlex Date: Mon, 14 Aug 2006 19:48:16 +0000 Subject: - Sacrifice no longer shows damage to self. - When Asura fails, the skill display will still come off. - Cleaned up AM_CALLHOMUN so that the required item is specified on skill_require_db - Cleaned up function merc_call_homun and added function merc_hom_vaporize to handle the respective cases. - Cleaned up a bit unit_remove_map/unit_free on regards to homun. it will display the /sob emotion when the homun dies due to low intimacy. Moved removal of timers and all that to unit_free - Cleaned up function merc_hom_dead - Simplified lots of code around by using the new merc functions. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@8279 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 1 - src/map/map.c | 3 +- src/map/mercenary.c | 157 ++++++++++++++++++++++++++-------------------------- src/map/mercenary.h | 2 +- src/map/pc.c | 12 +--- src/map/skill.c | 42 +++++--------- src/map/unit.c | 61 ++++++++++---------- 7 files changed, 128 insertions(+), 150 deletions(-) (limited to 'src') diff --git a/src/map/battle.c b/src/map/battle.c index bd9800ffa..4f2e03e5f 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1143,7 +1143,6 @@ static struct Damage battle_calc_weapon_attack( case PA_SACRIFICE: wd.damage = sstatus->max_hp* 9/100; status_zap(src, wd.damage, 0);//Damage to self is always 9% - clif_damage(src,src, gettick(), 0, 0, wd.damage, 0 , 0, 0); wd.damage2 = 0; if (sc && sc->data[SC_SACRIFICE].timer != -1) diff --git a/src/map/map.c b/src/map/map.c index 62570b913..93508d966 100644 --- a/src/map/map.c +++ b/src/map/map.c @@ -1670,8 +1670,7 @@ int map_quit(struct map_session_data *sd) { sd->state.waitingdisconnect = 1; if (sd->pd) unit_free(&sd->pd->bl); - if(sd->status.hom_id > 0 && sd->hd) //[orn] - merc_hom_delete(sd->hd, 2) ; + if (sd->hd) unit_free(&sd->hd->bl); unit_free(&sd->bl); chrif_save(sd,1); } else { //Try to free some data, without saving anything (this could be invoked on map server change. [Skotlex] diff --git a/src/map/mercenary.c b/src/map/mercenary.c index 6304f7f7d..13b15b029 100644 --- a/src/map/mercenary.c +++ b/src/map/mercenary.c @@ -113,44 +113,67 @@ void merc_damage(struct homun_data *hd,struct block_list *src,int hp,int sp) int merc_hom_dead(struct homun_data *hd, struct block_list *src) { - hd->battle_status.hp = hd->master->homunculus.hp = 0 ; - clif_hominfo(hd->master,hd,0); // Send dead flag + struct map_session_data *sd = hd->master; + if (!sd) + { + clif_emotion(&hd->bl, 16) ; //wah + return 7; + } + + sd->homunculus.hp = 0 ; + clif_hominfo(sd,hd,0); // Send dead flag + if(!merc_hom_decrease_intimacy(hd, 100)) { // Intimacy was < 100 - merc_stop_walking(hd, 1); - merc_stop_attack(hd); - clif_emotion(&hd->master->bl, 23) ; //omg - merc_hom_delete(hd,1) ; - return 1 ; + clif_emotion(&sd->bl, 23) ; //omg + return 7; //Delete from memory. } + clif_send_homdata(hd->master,SP_INTIMATE,hd->master->homunculus.intimacy / 100); clif_emotion(&hd->bl, 16) ; //wah - clif_emotion(&hd->master->bl, 28) ; //sob - merc_hom_delete(hd, 0); + clif_emotion(&sd->bl, 28) ; //sob + return 3; //Remove from map. +} + +//Vaporize a character's homun. If flag, HP needs to be 80% or above. +int merc_hom_vaporize(struct map_session_data *sd, int flag) +{ + struct homun_data *hd; - return 1; // Removing is handled by merc_hom_delete + nullpo_retr(0, sd); + + hd = sd->hd; + if (!hd || sd->homunculus.vaporize) + return 0; + + if (flag && hd->battle_status.hp < (hd->battle_status.max_hp*80/100)) + return 0; + + sd->homunculus.vaporize = 1; + clif_hominfo(sd, sd->hd, 0); + merc_save(hd); + return unit_remove_map(&hd->bl, 0); } -int merc_hom_delete(struct homun_data *hd, int flag) +//delete a homunculus, completely "killing it". +//Emote is the emotion the master should use, send negative to disable. +int merc_hom_delete(struct homun_data *hd, int emote) { + struct map_session_data *sd; nullpo_retr(0, hd); + sd = hd->master; - if ((flag & 2) && hd->bl.prev == NULL) - { - // Homunc was already removed from map, so just free the bl + if (!sd) return unit_free(&hd->bl); - } - // Delete homunculus - if ( flag&1 ) { //sabbath - intif_homunculus_requestdelete(hd->master->homunculus.hom_id) ; - clif_emotion(&hd->bl, 28) ; //sob - hd->master->status.hom_id = 0; - hd->master->homunculus.hom_id = 0; - chrif_save(hd->master,0); - } else - merc_save(hd); + if (emote >= 0) + clif_emotion(&sd->bl, emote); - return unit_remove_map(&hd->bl, 0); + //This makes it be deleted right away. + sd->homunculus.intimacy = 0; + // Send homunculus_dead to client + sd->homunculus.hp = 0; + clif_hominfo(sd, hd, 0); + return unit_free(&hd->bl); } int merc_hom_calc_skilltree(struct map_session_data *sd) @@ -314,7 +337,7 @@ int merc_hom_evolution(struct homun_data *hd) hd->master->homunculus.vaporize = 1; merc_stop_walking(hd, 1); merc_stop_attack(hd); - merc_hom_delete(hd, 0) ; + merc_hom_delete(hd, -1) ; merc_call_homunculus(hd->master); clif_emotion(&hd->master->bl, 21) ; //no1 clif_misceffect2(&hd->bl,568); @@ -442,10 +465,10 @@ static int merc_natural_heal_sub(struct homun_data *hd,int tick) { // tick = va_arg(ap,int); // -- moonsoul (if conditions below altered to disallow natural healing if under berserk status) - if ( hd && ( status_isdead(&hd->bl) || + if ( status_isdead(&hd->bl) || ( ( hd->sc.count ) && ( (hd->sc.data[SC_POISON].timer != -1 ) || ( hd->sc.data[SC_BLEEDING].timer != -1 ) ) - ) ) + ) ) { //Cannot heal neither natural or special. hd->hp_sub = hd->inchealhptick = 0; hd->sp_sub = hd->inchealsptick = 0; @@ -578,7 +601,7 @@ int merc_menu(struct map_session_data *sd,int menunum) merc_hom_food(sd, sd->hd); break; case 2: - merc_hom_delete(sd->hd, 1); + merc_hom_delete(sd->hd, -1); break; default: ShowError("merc_menu : unknown menu choice : %d\n", menunum) ; @@ -629,15 +652,9 @@ int merc_hom_food(struct map_session_data *sd, struct homun_data *hd) clif_hom_food(sd,hd->homunculusDB->foodID,1); // Too much food :/ - if(sd->homunculus.intimacy == 0) { - merc_stop_walking(hd, 1); - merc_stop_attack(hd); - // Send homunculus_dead to client - sd->homunculus.hp = 0; - clif_hominfo(sd, hd, 0); - merc_hom_delete(hd,1); - clif_emotion(&sd->bl, 23); //omg - } + if(sd->homunculus.intimacy == 0) + return merc_hom_delete(sd->hd, 23); //omg + return 0; } @@ -674,18 +691,9 @@ static int merc_hom_hungry(int tid,unsigned int tick,int id,int data) if(sd->homunculus.hunger < 0) { sd->homunculus.hunger = 0; // Delete the homunculus if intimacy <= 100 - if ( !merc_hom_decrease_intimacy(hd, 100) ) { - merc_stop_walking(hd, 1); - merc_stop_attack(hd); - // Send homunculus_dead to client - sd->homunculus.hp = 0; - clif_hominfo(sd, hd, 0); - merc_hom_delete(hd,1); - clif_emotion(&sd->bl, 23) ; //omg - return 0 ; - } else { - clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100); - } + if ( !merc_hom_decrease_intimacy(hd, 100) ) + return merc_hom_delete(sd->hd, 23); //omg + clif_send_homdata(sd,SP_INTIMATE,sd->homunculus.intimacy / 100); } clif_send_homdata(sd,SP_HUNGRY,sd->homunculus.hunger); @@ -812,45 +820,34 @@ int merc_hom_data_init(struct map_session_data *sd) return 0; } -// FIX call_homunculus [albator] int merc_call_homunculus(struct map_session_data *sd) { - int class_ = 0 ; - nullpo_retr(0, sd); + struct homun_data *hd; - if (!sd->status.hom_id) - { - class_ = 6000 + rand(1, 8) ; - return merc_create_homunculus(sd, class_) ; - } + if (!sd->status.hom_id) //Create a new homun. + return merc_create_homunculus(sd, 6000 + rand(1, 8)) ; - // If homunc not yet loaded, load it, else just activate it + //Recall homunculus to you. + if (sd->homunculus.vaporize) + return 0; //Can't use this when homun was vaporized. + + // If homunc not yet loaded, load it if (!sd->hd) merc_hom_create(sd); - else - merc_hom_data_init(sd); - // call vaporized homunculus [albator] - if(sd->homunculus.vaporize == 1) - { - sd->homunculus.vaporize = 0; - } - else - { - // Homunc was dead, set hp to 1 - sd->homunculus.hp = 1 ; - } - - if ( sd->homunculus.hp && sd->hd && sd->bl.prev != NULL) { - map_addblock(&sd->hd->bl); - clif_spawn(&sd->hd->bl); + hd = sd->hd; + if (hd->bl.prev == NULL) + { //Spawn him + map_addblock(&hd->bl); + clif_spawn(&hd->bl); clif_send_homdata(sd,SP_ACK,0); - clif_hominfo(sd,sd->hd,1); - clif_hominfo(sd,sd->hd,0); // send this x2. dunno why, but kRO does that [blackhole89] + clif_hominfo(sd,hd,1); + clif_hominfo(sd,hd,0); // send this x2. dunno why, but kRO does that [blackhole89] clif_homskillinfoblock(sd); - } - // save - merc_save(sd->hd); + merc_save(hd); + } else + //Warp him to master. + unit_warp(&hd->bl,sd->bl.m,sd->bl.x,sd->bl.y,0); return 1; } diff --git a/src/map/mercenary.h b/src/map/mercenary.h index aa07538ff..851abd4ee 100644 --- a/src/map/mercenary.h +++ b/src/map/mercenary.h @@ -62,7 +62,7 @@ int merc_hom_gainexp(struct homun_data *hd,int exp) ; int merc_hom_levelup(struct homun_data *hd) ; int merc_hom_evolution(struct homun_data *hd) ; void merc_hom_heal(struct homun_data *hd,int hp,int sp); -int merc_hom_delete(struct homun_data *hd, int flag) ; +int merc_hom_vaporize(struct map_session_data *sd, int flag); int merc_hom_revive(struct map_session_data *sd, int per); void merc_save(struct homun_data *hd); int merc_call_homunculus(struct map_session_data *sd); diff --git a/src/map/pc.c b/src/map/pc.c index 05eb21ee7..59d65aa0d 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -671,7 +671,7 @@ int pc_authok(struct map_session_data *sd, int login_id2, time_t connect_until_t // Homunculus [albator] if (sd->status.hom_id > 0) - intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); + intif_homunculus_requestload(sd->status.account_id, sd->status.hom_id); // パ?ティ、ギルドデ?タの要求 if (sd->status.party_id > 0 && party_search(sd->status.party_id) == NULL) @@ -4783,14 +4783,8 @@ int pc_dead(struct map_session_data *sd,struct block_list *src) pet_unlocktarget(sd->pd); } - if(sd->status.hom_id > 0 && sd->hd) //orn - { - sd->homunculus.vaporize = 1; - clif_hominfo(sd,sd->hd,0); - merc_stop_walking(sd->hd, 1) ; - merc_stop_attack(sd->hd) ; - merc_hom_delete(sd->hd,0); - } + if(sd->status.hom_id > 0) //orn + merc_hom_vaporize(sd, 0); // Leave duel if you die [LuzZza] if(battle_config.duel_autoleave_when_die) { diff --git a/src/map/skill.c b/src/map/skill.c index 7b87845bc..cdd6a90ce 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -5487,37 +5487,15 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in break; case AM_CALLHOMUN: //[orn] - if (sd) - { - if (sd->status.hom_id == 0 || sd->homunculus.vaporize == 1) { - if (sd->status.hom_id == 0) { - i = pc_search_inventory(sd,7142); - if(i < 0) { - clif_skill_fail(sd,skillid,0,0); - break ; - } - pc_delitem(sd,i,1,0); - } - if (merc_call_homunculus(sd)) - break; - } + if (sd && !merc_call_homunculus(sd)) clif_skill_fail(sd,skillid,0,0); - } break; case AM_REST: //[orn] - { - if (sd) - { - if (sd->hd && !sd->homunculus.vaporize && ( sd->hd->battle_status.hp >= (sd->hd->battle_status.max_hp * 80 / 100 ) ) ) { - sd->homunculus.vaporize = 1; - clif_hominfo(sd, sd->hd, 0); - merc_hom_delete(sd->hd, 0) ; - } else - clif_skill_fail(sd,skillid,0,0); - } + if (sd && !merc_hom_vaporize(sd,1)) + clif_skill_fail(sd,skillid,0,0); break; - } + case AM_RESURRECTHOMUN: //[orn] { if (sd) @@ -5821,8 +5799,10 @@ int skill_castend_id (int tid, unsigned int tick, int id, int data) else if(dy < 0) dy--; if (unit_movepos(src, src->x+dx, src->y+dy, 1, 1)) + { //Display movement + animation. clif_slide(src,src->x,src->y); - + clif_skill_damage(src,target,tick,sd->battle_status.amotion,0,0,1,ud->skillid, ud->skilllv, 5); + } clif_skill_fail(sd,ud->skillid,0,0); } } @@ -8320,6 +8300,14 @@ int skill_check_condition (struct map_session_data *sd, int skill, int lv, int t } zeny = 0; //Zeny is reduced on skill_attack. break; + case AM_CALLHOMUN: //Can't summon if a hom is already out (vaporized also counts). + if (sd->status.hom_id || sd->homunculus.vaporize) { + clif_skill_fail(sd,skill,0,0); + return 0; + } + if (sd->status.hom_id) //Don't delete items when hom is already out. + delitem_flag = 0; + break; } if(!(type&2)){ diff --git a/src/map/unit.c b/src/map/unit.c index d7c512714..90095d13a 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1497,7 +1497,6 @@ int unit_remove_map(struct block_list *bl, int clrtype) { unit_skillcastcancel(bl,0); // Do not reset can-act delay. [Skotlex] ud->attackabletime = ud->canmove_tick /*= ud->canact_tick*/ = gettick(); - clif_clearchar_area(bl,clrtype); if(sc && sc->count ) { //map-change/warp dispells. if(sc->data[SC_BLADESTOP].timer!=-1) @@ -1588,18 +1587,8 @@ int unit_remove_map(struct block_list *bl, int clrtype) { struct pet_data *pd = (struct pet_data*)bl; struct map_session_data *sd = pd->msd; - if(!sd) { - map_delblock(bl); - unit_free(bl); - map_freeblock_unlock(); - return 0; - } - if (sd->pet.intimate <= 0) - { //Remove pet. - intif_delete_petdata(sd->status.pet_id); - sd->status.pet_id = 0; - sd->pd = NULL; - pd->msd = NULL; + if(!sd || sd->pet.intimate <= 0) { + clif_clearchar_area(bl,clrtype); map_delblock(bl); unit_free(bl); map_freeblock_unlock(); @@ -1608,28 +1597,17 @@ int unit_remove_map(struct block_list *bl, int clrtype) { } else if (bl->type == BL_HOM) { struct homun_data *hd = (struct homun_data *) bl; struct map_session_data *sd = hd->master; - - // Desactive timers - merc_hom_hungry_timer_delete(hd); - merc_natural_heal_timer_delete(hd); - - if(!sd) { + if(!sd || !sd->homunculus.intimacy) + { //He's going to be deleted. + clif_emotion(bl, 28) ; //sob + clif_clearchar_area(bl,clrtype); map_delblock(bl); unit_free(bl); map_freeblock_unlock(); return 0; } - - // Homunc was deleted or player is leaving the server, remove it from memory - if (sd->homunculus.hom_id == 0 || sd->state.waitingdisconnect) - { //Remove pet. - map_delblock(bl); - unit_free(bl); - sd->hd = NULL; - map_freeblock_unlock(); - return 1; - } } + clif_clearchar_area(bl,clrtype); map_delblock(bl); map_freeblock_unlock(); return 1; @@ -1761,9 +1739,14 @@ int unit_free(struct block_list *bl) { pd->loot = NULL; } if (sd) { + sd->pd = NULL; if(sd->pet.intimate > 0) intif_save_petdata(sd->status.account_id,&sd->pet); - sd->pd = NULL; + else + { //Remove pet. + intif_delete_petdata(sd->status.pet_id); + sd->status.pet_id = 0; + } } } else if(bl->type == BL_MOB) { struct mob_data *md = (struct mob_data*)bl; @@ -1794,6 +1777,24 @@ int unit_free(struct block_list *bl) { } if(mob_is_clone(md->class_)) mob_clone_delete(md->class_); + } else if(bl->type == BL_HOM) { + struct homun_data *hd = (TBL_HOM*)bl; + struct map_session_data *sd = hd->master; + // Desactive timers + merc_hom_hungry_timer_delete(hd); + merc_natural_heal_timer_delete(hd); + if(sd) { + sd->hd = NULL; + hd->master = NULL; + if (sd->homunculus.intimacy > 0) + merc_save(hd); + else + { + intif_homunculus_requestdelete(sd->homunculus.hom_id) ; + sd->status.hom_id = 0; + sd->homunculus.hom_id = 0; + } + } } skill_clear_unitgroup(bl); -- cgit v1.2.3-70-g09d2