From aff8dade6593463301abee054981a4ea21fff273 Mon Sep 17 00:00:00 2001 From: skotlex Date: Fri, 18 Aug 2006 16:43:20 +0000 Subject: - Made HLIF_HEAL a self skill that auto-selects target to caster's master. - Implemented SC_BLOODLUST and SC_CHANGE, cleaned up HLIF_CHANGE - Applied a correction to HVAN_EXPLOSION - Fixed Homun ASPD calculation being able to underflow and give you min speed. - Added monster_ai&128 to make aggressive mobs ignore that behaviour of always picking Homun targets above player targets regardless of who is closer. - Fixed homun info packet being unable to display HP/SP correctly once the values are above 32k. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@8349 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 15 +++++++++++---- src/map/clif.c | 22 ++++++++++++++++------ src/map/mob.c | 2 +- src/map/skill.c | 18 ++++++++---------- src/map/status.c | 39 +++++++++++++++++++++++++++++++-------- src/map/unit.c | 1 + 6 files changed, 68 insertions(+), 29 deletions(-) (limited to 'src') diff --git a/src/map/battle.c b/src/map/battle.c index f16a58314..fbe9fcfba 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -404,6 +404,13 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i } if (!damage) return 0; + + //Probably not the most correct place, but it'll do here + //(since battle_drain is strictly for players currently) + if (sc->data[SC_BLOODLUST].timer != -1 && flag&BF_WEAPON && damage > 0 && + rand()%100 < sc->data[SC_BLOODLUST].val3) + status_heal(src, damage*sc->data[SC_BLOODLUST].val4/100, 0, 3); + } //SC effects from caster side. Currently none. /* @@ -1030,7 +1037,6 @@ static struct Damage battle_calc_weapon_attack( case GS_GROUNDDRIFT: case NJ_TATAMIGAESHI: case NJ_ISSEN: - case HVAN_EXPLOSION: //[orn] flag.hit = 1; break; case CR_SHIELDBOOMERANG: @@ -1195,6 +1201,7 @@ static struct Damage battle_calc_weapon_attack( i = (flag.cri?1:0)| (flag.arrow?2:0)| (skill_num == HW_MAGICCRASHER?4:0)| + (!skill_num && sc && sc->data[SC_CHANGE].timer!=-1?4:0)| (skill_num == MO_EXTREMITYFIST?8:0)| (sc && sc->data[SC_WEAPONPERFECTION].timer!=-1?8:0); if (flag.arrow && sd) @@ -2504,7 +2511,7 @@ struct Damage battle_calc_misc_attack( case CR_ACIDDEMONSTRATION: md.flag = (md.flag&~BF_RANGEMASK)|BF_LONG; break; - case HVAN_EXPLOSION: //[orn] + case HVAN_EXPLOSION: case NPC_SELFDESTRUCTION: case NPC_SMOKING: flag.elefix = flag.cardfix = 0; @@ -2726,8 +2733,8 @@ int battle_calc_return_damage(struct block_list *bl, int *damage, int flag) { struct map_session_data *sd=NULL; struct status_change *sc; int rdamage = 0; - - if (bl->type == BL_PC) sd = (struct map_session_data*)bl; + + BL_CAST(BL_PC, bl, sd); sc = status_get_sc(bl); if(flag&BF_WEAPON) { diff --git a/src/map/clif.c b/src/map/clif.c index 0a2b995b9..4537deb26 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1466,14 +1466,14 @@ int clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) memset(buf,0,packet_len_table[0x22e]); WBUFW(buf,0)=0x22e; memcpy(WBUFP(buf,2),sd->homunculus.name,NAME_LENGTH); - WBUFB(buf,26)=sd->homunculus.rename_flag * 2; +// WBUFB(buf,26)=sd->homunculus.rename_flag * 2; // Bit field, bit 0 : rename_flag (1 = already renamed), bit 1 : homunc vaporized (1 = true), bit 2 : homunc dead (1 = true) WBUFB(buf,26)=sd->homunculus.rename_flag | (sd->homunculus.vaporize << 1) | (sd->homunculus.hp?0:4); WBUFW(buf,27)=sd->homunculus.level; WBUFW(buf,29)=sd->homunculus.hunger; WBUFW(buf,31)=(unsigned short) (sd->homunculus.intimacy / 100) ; WBUFW(buf,33)=0; // equip id - WBUFW(buf,35)=status->rhw.atk2; + WBUFW(buf,35)=status->rhw.atk2+status->batk; WBUFW(buf,37)=status->matk_max; WBUFW(buf,39)=status->hit; WBUFW(buf,41)=status->cri/10; //crit is a +1 decimal value! @@ -1481,10 +1481,20 @@ int clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) WBUFW(buf,45)=status->mdef; WBUFW(buf,47)=status->flee; WBUFW(buf,49)=(flag)?0:status->amotion; - WBUFW(buf,51)=status->hp; - WBUFW(buf,53)=status->max_hp; - WBUFW(buf,55)=status->sp; - WBUFW(buf,57)=status->max_sp; + if (status->max_hp > SHRT_MAX) { + WBUFW(buf,51) = status->hp/(status->max_hp/100); + WBUFW(buf,53) = 100; + } else { + WBUFW(buf,51)=status->hp; + WBUFW(buf,53)=status->max_hp; + } + if (status->max_sp > SHRT_MAX) { + WBUFW(buf,55) = status->sp/(status->max_sp/100); + WBUFW(buf,57) = 100; + } else { + WBUFW(buf,55)=status->sp; + WBUFW(buf,57)=status->max_sp; + } WBUFL(buf,59)=sd->homunculus.exp; WBUFL(buf,63)=hd->exp_next; WBUFW(buf,67)=sd->homunculus.skillpts; diff --git a/src/map/mob.c b/src/map/mob.c index 84671a70d..e3bce2257 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -774,7 +774,7 @@ static int mob_ai_sub_hard_activesearch(struct block_list *bl,va_list ap) !(status_get_mode(&md->bl)&MD_BOSS)) return 0; //Gangster paradise protection. default: - if ((*target) && (*target)->type == BL_HOM && bl->type != BL_HOM) + if (!(battle_config.mob_ai&128) && (*target) && (*target)->type == BL_HOM && bl->type != BL_HOM) return 0; //For some reason Homun targets are never overriden. if((dist=distance_bl(&md->bl, bl)) < md->db->range2 && diff --git a/src/map/skill.c b/src/map/skill.c index b8fd82f3b..f8b946eb0 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -3091,12 +3091,12 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case CR_ACIDDEMONSTRATION: case TF_THROWSTONE: case NPC_SMOKING: - case HVAN_EXPLOSION: //[orn] case GS_FLING: case NJ_ZENYNAGE: skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); break; + case HVAN_EXPLOSION: case NPC_SELFDESTRUCTION: if (src != bl) skill_attack(BF_MISC,src,src,bl,skillid,skilllv,tick,flag); @@ -4063,7 +4063,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case NPC_SELFDESTRUCTION: //Self Destruction hits everyone in range (allies+enemies) //Except for Summoned Marine spheres on non-versus maps, where it's just enemy. - i = (md && md->special_state.ai == 2 && !map_flag_vs(src->m))? + i = ((hd || (md && md->special_state.ai == 2)) && !map_flag_vs(src->m))? BCT_ENEMY:BCT_ALL; clif_skill_nodamage(src, src, skillid, -1, 1); map_foreachinrange(skill_area_sub, bl, @@ -5554,14 +5554,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in clif_skill_fail(hd->master,skillid,0,0); break; case HLIF_CHANGE: //[orn] - if ( hd ) { - clif_skill_nodamage(src,bl,skillid,skilllv, - sc_start(&hd->bl,type,100,skilllv,skill_get_time(skillid,skilllv))) ; - status_heal(&hd->bl, hd->master->homunculus.max_hp, 0, 0); - skill_blockmerc_start(hd, skillid, skill_get_time2(skillid,skilllv)) ; - } - else - clif_skill_fail(hd->master,skillid,0,0); + clif_skill_nodamage(src,bl,skillid,skilllv, + sc_start(bl,type,100,skilllv,skill_get_time(skillid,skilllv))); + if (sd) + skill_blockpc_start(sd, skillid, skill_get_time2(skillid,skilllv)); + if (hd) + skill_blockmerc_start(hd, skillid, skill_get_time2(skillid,skilllv)); break; default: diff --git a/src/map/status.c b/src/map/status.c index 99449554b..f40e39c9b 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -376,7 +376,7 @@ void initChangeTables(void) { add_sc(SA_ELEMENTWIND, SC_ELEMENTALCHANGE); set_sc(HLIF_AVOID, SC_AVOID, SI_BLANK, SCB_SPEED); - set_sc(HLIF_CHANGE, SC_CHANGE, SI_BLANK, SCB_INT); + set_sc(HLIF_CHANGE, SC_CHANGE, SI_BLANK, SCB_MAXHP|SCB_MAXSP); set_sc(HFLI_FLEET, SC_FLEET, SI_BLANK, SCB_ASPD|SCB_BATK|SCB_WATK); set_sc(HFLI_SPEED, SC_SPEED, SI_BLANK, SCB_FLEE); //[orn] set_sc(HAMI_DEFENCE, SC_DEFENCE, SI_BLANK, SCB_DEF); //[orn] @@ -2255,6 +2255,14 @@ int status_calc_homunculus(struct homun_data *hd, int first) status->rhw.atk = status->dex; status->rhw.atk2 = status->str + hom->level; + status->aspd_rate = 1000; + + skill = (1000 -4*status->agi -status->dex) + *hd->homunculusDB->baseASPD/1000; + + status->amotion = cap_value(skill,battle_config.max_aspd,2000); + status->adelay = 2*status->amotion; + status_calc_misc(status, BL_HOM, hom->level); status_calc_bl(&hd->bl, SCB_ALL); //Status related changes. @@ -2725,14 +2733,15 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] if(flag&(SCB_ASPD|SCB_AGI|SCB_DEX)) { flag|=SCB_ASPD; - status->amotion = hd->homunculusDB->baseASPD - ((status->agi*4+status->dex)* hd->homunculusDB->baseASPD / 1000); + skill = (1000 -4*status->agi -status->dex) + *hd->homunculusDB->baseASPD/1000; + status->aspd_rate = status_calc_aspd_rate(&hd->bl, &hd->sc , b_status->aspd_rate); if(status->aspd_rate != 1000) - status->amotion = status->amotion *status->aspd_rate/1000; - - status->amotion = cap_value(status->amotion,battle_config.max_aspd,2000); + skill = skill*status->aspd_rate/1000; + status->amotion = cap_value(skill,battle_config.max_aspd,2000); status->adelay = 2*status->amotion; } @@ -3109,8 +3118,6 @@ static unsigned short status_calc_int(struct block_list *bl, struct status_chang int_ -= int_ * sc->data[SC_STRIPHELM].val2/100; if(sc->data[SC_NEN].timer!=-1) int_ += sc->data[SC_NEN].val1; - if(sc->data[SC_CHANGE].timer!=-1) - int_ += 60; if(sc->data[SC_MARIONETTE].timer!=-1) int_ -= (sc->data[SC_MARIONETTE].val4>>16)&0xFF; if(sc->data[SC_MARIONETTE2].timer!=-1) @@ -3686,6 +3693,8 @@ static unsigned int status_calc_maxhp(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(maxhp,1,UINT_MAX); + if(sc->data[SC_CHANGE].timer!=-1) + maxhp = sc->data[SC_CHANGE].val3; if(sc->data[SC_INCMHPRATE].timer!=-1) maxhp += maxhp * sc->data[SC_INCMHPRATE].val1/100; if(sc->data[SC_APPLEIDUN].timer!=-1) @@ -3703,6 +3712,8 @@ static unsigned int status_calc_maxsp(struct block_list *bl, struct status_chang if(!sc || !sc->count) return cap_value(maxsp,1,UINT_MAX); + if(sc->data[SC_CHANGE].timer!=-1) + maxsp = sc->data[SC_CHANGE].val2; if(sc->data[SC_INCMSPRATE].timer!=-1) maxsp += maxsp * sc->data[SC_INCMSPRATE].val1/100; if(sc->data[SC_SERVICE4U].timer!=-1) @@ -5459,6 +5470,8 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val break; case SC_BLOODLUST: val2 = 20+10*val1; //Atk rate change. + val3 = 3*val1; //Leech chance + val4 = 20; //Leech percent break; case SC_FLEET: val2 = 30*val1; //Aspd change @@ -5494,6 +5507,14 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val case SC_BUNSINJYUTSU: val2=(val1+1)/2; // number of hits blocked break; + case SC_CHANGE: + { + struct status_data *status = status_get_base_status(bl); + if (!status) return 0; + val2= status->max_hp; //Base Max HP + val3= status->max_sp; //Base Max SP + } + break; default: if (calc_flag == SCB_NONE && StatusSkillChangeTable[type]==0) { //Status change with no calc, and no skill associated...? unknown? @@ -5717,7 +5738,9 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val sc->data[type].val2 = 5*status->max_hp/100; status_heal(bl, status->max_hp, 0, 1); //Do not use percent_heal as this healing must override BERSERK's block. status_set_sp(bl, 0, 0); //Damage all SP - } + } else if (type==SC_CHANGE) //Heal all HP + status_percent_heal(bl, 100, 0); + if (type==SC_RUN) { struct unit_data *ud = unit_bl2ud(bl); diff --git a/src/map/unit.c b/src/map/unit.c index 52284d83d..bed5a93d2 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -784,6 +784,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int if (src->type==BL_HOM) switch(skill_num) { //Homun-auto-target skills. + case HLIF_HEAL: case HLIF_AVOID: case HAMI_DEFENCE: case HAMI_CASTLE: -- cgit v1.2.3-60-g2f50