From 8faef4ff7ef37f52f24ac6e1e026a418b19db1fe Mon Sep 17 00:00:00 2001 From: malufett Date: Wed, 10 Dec 2014 00:57:50 +0800 Subject: RENEWAL Updates: -Homunculus Official Statuses -Updated RE @mobinfo to show proper status data.(Follow up 28a8b0f7b06a6af86aff6ececf7d9541d457e297) -Some official behaviors. Signed-off-by: malufett --- conf/battle/homunc.conf | 2 +- conf/messages.conf | 5 +- src/common/mmo.h | 8 + src/config/const.h | 6 +- src/map/atcommand.c | 6 + src/map/battle.c | 83 +++-- src/map/clif.c | 44 ++- src/map/clif.h | 1 + src/map/homunculus.c | 2 + src/map/homunculus.h | 11 + src/map/pc.c | 16 + src/map/pc.h | 4 +- src/map/skill.c | 2 +- src/map/status.c | 928 +++++++++++++++++++++++++----------------------- src/map/status.h | 9 +- src/map/unit.c | 33 +- 16 files changed, 645 insertions(+), 515 deletions(-) diff --git a/conf/battle/homunc.conf b/conf/battle/homunc.conf index 92c4b5fe8..a33eab8ea 100644 --- a/conf/battle/homunc.conf +++ b/conf/battle/homunc.conf @@ -18,7 +18,7 @@ // stat window (by default they don't crit) // 0x020: Their Min-Matk is always the same as their max // 0x040: Skill re-use delay is reset when they are vaporized. -hom_setting: 0x3D +hom_setting: 0x1D // The rate a homunculus will get friendly by feeding it. (Note 2) homunculus_friendly_rate: 100 diff --git a/conf/messages.conf b/conf/messages.conf index d9d4e9411..3ec46eb92 100644 --- a/conf/messages.conf +++ b/conf/messages.conf @@ -1232,7 +1232,10 @@ 1289: %s spawns in: 1290: This monster does not spawn normally. -//1291-1294 FREE +// @mobinfo ... +1291: ATK:%d~%d MATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d) + +//1292-1294 FREE // @version 1295: %s revision '%s' (src) / '%s' (scripts) diff --git a/src/common/mmo.h b/src/common/mmo.h index fd054ba91..ef42e49c0 100644 --- a/src/common/mmo.h +++ b/src/common/mmo.h @@ -376,6 +376,14 @@ struct s_homunculus { //[orn] int int_; int dex; int luk; + + int str_value; + int agi_value; + int vit_value; + int int_value; + int dex_value; + int luk_value; + int8 spiritball; //for homun S [lighta] }; diff --git a/src/config/const.h b/src/config/const.h index 2b5b180c4..7b5ed5506 100644 --- a/src/config/const.h +++ b/src/config/const.h @@ -52,10 +52,14 @@ #define DEFTYPE_MAX CHAR_MAX #endif -/* ATCMD_FUNC(mobinfo) HIT and FLEE calculations */ +/* ATCMD_FUNC(mobinfo) HIT, FLEE, ATK, ATK2, MATK and MATK2 calculations */ #ifdef RENEWAL #define MOB_FLEE(mobdata) ( (mobdata)->lv + (mobdata)->status.agi + 100 ) #define MOB_HIT(mobdata) ( (mobdata)->lv + (mobdata)->status.dex + 150 ) + #define MOB_ATK1(mobdata) ( ((mobdata)->lv + (mobdata)->status.str) + (mobdata)->status.rhw.atk * 8 / 10 ) + #define MOB_ATK2(mobdata) ( ((mobdata)->lv + (mobdata)->status.str) + (mobdata)->status.rhw.atk * 12 / 10 ) + #define MOB_MATK1(mobdata)( ((mobdata)->lv + (mobdata)->status.int_) + (mobdata)->status.rhw.atk2 * 7 / 10 ) + #define MOB_MATK2(mobdata)( ((mobdata)->lv + (mobdata)->status.int_) + (mobdata)->status.rhw.atk2 * 13 / 10 ) #define RE_SKILL_REDUCTION() do { \ wd.damage = battle->calc_elefix(src, target, skill_id, skill_lv, battle->calc_cardfix(BF_WEAPON, src, target, nk, s_ele, s_ele_, wd.damage, 0, wd.flag), nk, n_ele, s_ele, s_ele_, false, flag.arrow); \ if( flag.lh ) \ diff --git a/src/map/atcommand.c b/src/map/atcommand.c index f9cb1a641..330fe6284 100644 --- a/src/map/atcommand.c +++ b/src/map/atcommand.c @@ -6564,8 +6564,14 @@ ACMD(mobinfo) monster->status.vit, monster->status.int_, monster->status.dex, monster->status.luk); clif->message(fd, atcmd_output); + +#ifdef RENEWAL + sprintf(atcmd_output, msg_txt(1291), // ATK : %d~%d MATK : %d~%d Range : %d~%d~%d Size : %s Race : %s Element : %s(Lv : %d) + MOB_ATK1(monster), MOB_ATK2(monster), MOB_MATK1(monster), MOB_MATK2(monster), monster->status.rhw.range, +#else sprintf(atcmd_output, msg_txt(1244), // ATK:%d~%d Range:%d~%d~%d Size:%s Race: %s Element: %s (Lv:%d) monster->status.rhw.atk, monster->status.rhw.atk2, monster->status.rhw.range, +#endif monster->range2 , monster->range3, msize[monster->status.size], mrace[monster->status.race], melement[monster->status.def_ele], monster->status.ele_lv); clif->message(fd, atcmd_output); diff --git a/src/map/battle.c b/src/map/battle.c index 58291a3d6..459af3a81 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -451,6 +451,9 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u eatk = sd->base_status.equip_atk; } + if ( skill_id == TF_POISON ) + eatk += 15 * skill_lv; + if( sc && sc->count ){ if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 ) eatk += 200; @@ -506,16 +509,20 @@ int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uin struct status_data *st = status->get_status_data(src); struct status_change *sc = status->get_sc(src); - // Property from mild wind bypasses it - if (sc && sc->data[SC_TK_SEVENWIND]) - batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, s_ele, s_ele_, false, flag); - else - batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag); - - if( type == EQI_HAND_L ) - damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4; - else - damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2); + if (src->type == BL_PC){ + // Property from mild wind bypasses it + if (sc && sc->data[SC_TK_SEVENWIND]) + batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, s_ele, s_ele_, false, flag); + else + batk = battle->calc_elefix(src, bl, skill_id, skill_lv, status->calc_batk(bl, sc, st->batk, false), nk, n_ele, ELE_NEUTRAL, ELE_NEUTRAL, false, flag); + if (type == EQI_HAND_L) + damage = batk + 3 * battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->lhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2) / 4; + else + damage = (batk << 1) + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2); + } + else{ + damage = st->batk + battle->calc_weapon_damage(src, bl, skill_id, skill_lv, &st->rhw, nk, n_ele, s_ele, s_ele_, status_get_size(bl), type, flag, flag2); + } return damage; } @@ -2824,7 +2831,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam //Now damage increasing effects if( sc->data[SC_LEXAETERNA] && skill_id != PF_SOULBURN #ifdef RENEWAL - && skill_id != CR_ACIDDEMONSTRATION && skill_id != ASC_BREAKER + && skill_id != CR_ACIDDEMONSTRATION #endif ) { @@ -3329,7 +3336,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list struct status_data *sstatus = status->get_status_data(src); struct status_data *tstatus = status->get_status_data(target); struct { - unsigned imdef : 1; + unsigned imdef : 2; unsigned infdef : 1; } flag; @@ -3413,7 +3420,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list case CR_ACIDDEMONSTRATION: case ASC_BREAKER: case HW_MAGICCRASHER: - flag.imdef = 1; + flag.imdef = 2; break; #endif } @@ -3572,7 +3579,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list flag.imdef = 1; } - ad.damage = battle->calc_defense(BF_MAGIC, src, target, skill_id, skill_lv, ad.damage, (flag.imdef?1:0), 0); + ad.damage = battle->calc_defense(BF_MAGIC, src, target, skill_id, skill_lv, ad.damage, flag.imdef, 0); if (skill_id == NPC_EARTHQUAKE) { //Adds atk2 to the damage, should be influenced by number of hits and skill-ratio, but not mdef reductions. [Skotlex] @@ -3627,8 +3634,8 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list if (flag.infdef && ad.damage) ad.damage = ad.damage>0?1:-1; - - ad.damage=battle->calc_damage(src,target,&ad,ad.damage,skill_id,skill_lv); + if (skill_id != ASC_BREAKER) + ad.damage = battle->calc_damage(src, target, &ad, ad.damage, skill_id, skill_lv); if( map_flag_gvg2(target->m) ) ad.damage=battle->calc_gvg_damage(src,target,ad.damage,ad.div_,skill_id,skill_lv,ad.flag); else if( map->list[target->m].flag.battleground ) @@ -3854,10 +3861,6 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * ratio >>= 1; md.damage = (matk + atk) * ratio / 100; md.damage -= totaldef; - if( tsc && tsc->data[SC_LEXAETERNA] ) { - md.damage <<= 1; - status_change_end(target, SC_LEXAETERNA, INVALID_TIMER); - } #endif } break; @@ -5076,8 +5079,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if(sd && (temp=pc->checkskill(sd,BS_WEAPONRESEARCH)) > 0) ATK_ADD(temp*2); #endif - if(skill_id==TF_POISON) - ATK_ADD(15*skill_lv); #ifndef RENEWAL wd.damage = battle->calc_elefix(src, target, skill_id, skill_lv, wd.damage, nk, n_ele, s_ele, s_ele_, false, flag.arrow); @@ -5245,22 +5246,31 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if( wd.damage + wd.damage2 ) { //There is a total damage value int64 damage = wd.damage + wd.damage2; - if(!wd.damage2) { - wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); + if (!wd.damage2) { +#ifdef RENEWAL + if (skill_id != ASC_BREAKER) +#endif + wd.damage = battle->calc_damage(src, target, &wd, wd.damage, skill_id, skill_lv); if( map_flag_gvg2(target->m) ) wd.damage=battle->calc_gvg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); else if( map->list[target->m].flag.battleground ) wd.damage=battle->calc_bg_damage(src,target,wd.damage,wd.div_,skill_id,skill_lv,wd.flag); - } else if(!wd.damage) { - wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); - if( map_flag_gvg2(target->m) ) - wd.damage2 = battle->calc_gvg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); - else if( map->list[target->m].flag.battleground ) - wd.damage = battle->calc_bg_damage(src,target,wd.damage2,wd.div_,skill_id,skill_lv,wd.flag); + } + else if (!wd.damage) { +#ifdef RENEWAL + if (skill_id != ASC_BREAKER) +#endif + wd.damage2 = battle->calc_damage(src, target, &wd, wd.damage2, skill_id, skill_lv); + if (map_flag_gvg2(target->m)) + wd.damage2 = battle->calc_gvg_damage(src, target, wd.damage2, wd.div_, skill_id, skill_lv, wd.flag); + else if (map->list[target->m].flag.battleground) + wd.damage = battle->calc_bg_damage(src, target, wd.damage2, wd.div_, skill_id, skill_lv, wd.flag); } else { #ifdef RENEWAL - wd.damage = battle->calc_damage(src,target,&wd,wd.damage,skill_id,skill_lv); - wd.damage2 = battle->calc_damage(src,target,&wd,wd.damage2,skill_id,skill_lv); + if( skill_id != ASC_BREAKER ){ + wd.damage = battle->calc_damage(src, target, &wd, wd.damage, skill_id, skill_lv); + wd.damage2 = battle->calc_damage(src, target, &wd, wd.damage2, skill_id, skill_lv); + } #else int64 d1 = wd.damage + wd.damage2,d2 = wd.damage2; wd.damage = battle->calc_damage(src,target,&wd,d1,skill_id,skill_lv); @@ -5688,7 +5698,10 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t { int index = sd->equip_index[EQI_AMMO]; if (index<0) { - clif->arrow_fail(sd,0); + if (sd->weapontype1 > W_KATAR || sd->weapontype1 < W_HUUMA) + clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0); + else + clif->arrow_fail(sd, 0); return ATK_NONE; } //Ammo check by Ishizu-chan @@ -5705,13 +5718,13 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t case W_GATLING: case W_SHOTGUN: if (sd->inventory_data[index]->look != A_BULLET) { - clif->arrow_fail(sd,0); + clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0); return ATK_NONE; } break; case W_GRENADE: if (sd->inventory_data[index]->look != A_GRENADE) { - clif->arrow_fail(sd,0); + clif->skill_fail(sd, 0, USESKILL_FAIL_NEED_MORE_BULLET, 0); return ATK_NONE; } break; diff --git a/src/map/clif.c b/src/map/clif.c index d3564f97d..5194a637a 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -1422,15 +1422,24 @@ void clif_hominfo(struct map_session_data *sd, struct homun_data *hd, int flag) WBUFW(buf,29)=hd->homunculus.hunger; WBUFW(buf,31)=(unsigned short) (hd->homunculus.intimacy / 100) ; WBUFW(buf,33)=0; // equip id +#ifdef RENEWAL + WBUFW(buf, 35) = cap_value(hstatus->rhw.atk2, 0, INT16_MAX); +#else WBUFW(buf,35)=cap_value(hstatus->rhw.atk2+hstatus->batk, 0, INT16_MAX); +#endif WBUFW(buf,37)=cap_value(hstatus->matk_max, 0, INT16_MAX); WBUFW(buf,39)=hstatus->hit; if (battle_config.hom_setting&0x10) WBUFW(buf,41)=hstatus->luk/3 + 1; //crit is a +1 decimal value! Just display purpose.[Vicious] else WBUFW(buf,41)=hstatus->cri/10; +#ifdef RENEWAL + WBUFW(buf, 43) = hstatus->def + hstatus->def2; + WBUFW(buf, 45) = hstatus->mdef + hstatus->mdef2; +#else WBUFW(buf,43)=hstatus->def + hstatus->vit ; - WBUFW(buf,45)=hstatus->mdef; + WBUFW(buf, 45) = hstatus->mdef; +#endif WBUFW(buf,47)=hstatus->flee; WBUFW(buf,49)=(flag)?0:hstatus->amotion; if (hstatus->max_hp > INT16_MAX) { @@ -11260,15 +11269,23 @@ void clif_parse_UseSkillToId_homun(struct homun_data *hd, struct map_session_dat if( !hd ) return; - if( skill->not_ok_hom(skill_id, hd) ) + if (skill->not_ok_hom(skill_id, hd)){ + clif->emotion(&hd->bl, E_DOTS); return; - if( hd->bl.id != target_id && skill->get_inf(skill_id)&INF_SELF_SKILL ) + } + if (hd->bl.id != target_id && skill->get_inf(skill_id)&INF_SELF_SKILL) target_id = hd->bl.id; - if( hd->ud.skilltimer != INVALID_TIMER ) { - if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return; - } else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) + if (hd->ud.skilltimer != INVALID_TIMER) { + if (skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST) return; + } + else if (DIFF_TICK(tick, hd->ud.canact_tick) < 0){ + clif->emotion(&hd->bl, E_DOTS); + if (hd->master) + clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return; + } + lv = homun->checkskill(hd, skill_id); if( skill_lv > lv ) skill_lv = lv; @@ -11280,12 +11297,19 @@ void clif_parse_UseSkillToPos_homun(struct homun_data *hd, struct map_session_da int lv; if( !hd ) return; - if( skill->not_ok_hom(skill_id, hd) ) + if (skill->not_ok_hom(skill_id, hd)){ + clif->emotion(&hd->bl, E_DOTS); return; - if( hd->ud.skilltimer != INVALID_TIMER ) { - if( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return; - } else if( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) + } + if ( hd->ud.skilltimer != INVALID_TIMER ) { + if ( skill_id != SA_CASTCANCEL && skill_id != SO_SPELLFIST ) return; + + } else if ( DIFF_TICK(tick, hd->ud.canact_tick) < 0 ) { + clif->emotion(&hd->bl, E_DOTS); + if ( hd->master ) + clif->skill_fail(hd->master, skill_id, USESKILL_FAIL_SKILLINTERVAL, 0); return; + } if( hd->sc.data[SC_BASILICA] ) return; diff --git a/src/map/clif.h b/src/map/clif.h index a8248bc8a..4d11fc281 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -340,6 +340,7 @@ typedef enum useskill_fail_cause { // clif_skill_fail USESKILL_FAIL_STYLE_CHANGE_FIGHTER = 81, USESKILL_FAIL_STYLE_CHANGE_GRAPPLER = 82, USESKILL_FAIL_THERE_ARE_NPC_AROUND = 83, + USESKILL_FAIL_NEED_MORE_BULLET = 84, }useskill_fail_cause; enum clif_messages { diff --git a/src/map/homunculus.c b/src/map/homunculus.c index e45f654ff..1d226749b 100644 --- a/src/map/homunculus.c +++ b/src/map/homunculus.c @@ -347,6 +347,8 @@ bool homunculus_levelup(struct homun_data *hd) { hom->int_+= growth_int; hom->luk += growth_luk; + APPLY_HOMUN_LEVEL_STATWEIGHT(); + if ( battle_config.homunculus_show_growth ) { char output[256] ; sprintf(output, diff --git a/src/map/homunculus.h b/src/map/homunculus.h index 263922e4e..5b1fd2031 100644 --- a/src/map/homunculus.h +++ b/src/map/homunculus.h @@ -14,6 +14,17 @@ #define homdb_checkid(id) ((id) >= HM_CLASS_BASE && (id) <= HM_CLASS_MAX) #define homun_alive(x) ((x) && (x)->homunculus.vaporize == HOM_ST_ACTIVE && (x)->battle_status.hp > 0) +#ifdef RENEWAL +#define HOMUN_LEVEL_STATWEIGHT_VALUE 0 +#define APPLY_HOMUN_LEVEL_STATWEIGHT()( \ + hom->str_value = hom->agi_value = \ + hom->vit_value = hom->int_value = \ + hom->dex_value = hom->luk_value = hom->level / 10 - HOMUN_LEVEL_STATWEIGHT_VALUE \ + ) +#else +#define APPLY_HOMUN_LEVEL_STATWEIGHT() +#endif + struct h_stats { unsigned int HP, SP; unsigned short str, agi, vit, int_, dex, luk; diff --git a/src/map/pc.c b/src/map/pc.c index 4def231bc..b22c0d74e 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -902,6 +902,16 @@ int pc_isequip(struct map_session_data *sd,int n) if(item->sex != 2 && sd->status.sex != item->sex) return 0; + if ( item->equip & EQP_AMMO ) { + if ( !pc_iscarton(sd) && (sd->status.class_ == JOB_GENETIC_T || sd->status.class_ == JOB_GENETIC) ) { + clif->msg(sd, 0x5EF); + return 0; + } + if ( !pc_ismadogear(sd) && (sd->status.class_ == JOB_MECHANIC_T || sd->status.class_ == JOB_MECHANIC) ) { + clif->msg(sd, 0x59B); + return 0; + } + } if (sd->sc.count) { if(item->equip & EQP_ARMS && item->type == IT_WEAPON && sd->sc.data[SC_NOEQUIPWEAPON]) // Also works with left-hand weapons [DracoRPG] @@ -8047,6 +8057,8 @@ int pc_setoption(struct map_session_data *sd,int type) clif->clearcart(sd->fd); if(pc->checkskill(sd, MC_PUSHCART) < 10) status_calc_pc(sd,SCO_NONE); //Remove speed penalty. + if ( sd->equip_index[EQI_AMMO] > 0 ) + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); } #endif @@ -8082,6 +8094,8 @@ int pc_setoption(struct map_session_data *sd,int type) } status_change_end(&sd->bl, (sc_type)i, INVALID_TIMER); } + if ( sd->equip_index[EQI_AMMO] > 0 ) + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); } if (type&OPTION_FLYING && !(p_type&OPTION_FLYING)) @@ -8134,6 +8148,8 @@ int pc_setcart(struct map_session_data *sd,int type) { status_change_end(&sd->bl,SC_PUSH_CART,INVALID_TIMER); clif->clearcart(sd->fd); clif->updatestatus(sd, SP_CARTINFO); + if ( sd->equip_index[EQI_AMMO] > 0 ) + pc->unequipitem(sd, sd->equip_index[EQI_AMMO], 2); break; default:/* everything else is an allowed ID so we can move on */ if( !sd->sc.data[SC_PUSH_CART] ) /* first time, so fill cart data */ diff --git a/src/map/pc.h b/src/map/pc.h index a17300701..0adb25a7b 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -640,8 +640,8 @@ struct map_session_data { #define pc_rightside_def(sd) ((sd)->battle_status.def) #define pc_leftside_mdef(sd) ((sd)->battle_status.mdef2) #define pc_rightside_mdef(sd) ((sd)->battle_status.mdef) -#define pc_leftside_matk(sd) (status->base_matk(status->get_status_data(&(sd)->bl), (sd)->status.base_level)) -#define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk) + #define pc_leftside_matk(sd) (status->base_matk(&(sd)->bl, status->get_status_data(&(sd)->bl), (sd)->status.base_level)) + #define pc_rightside_matk(sd) ((sd)->battle_status.rhw.matk+(sd)->battle_status.lhw.matk+(sd)->bonus.ematk) #else #define pc_leftside_atk(sd) ((sd)->battle_status.batk + (sd)->battle_status.rhw.atk + (sd)->battle_status.lhw.atk) #define pc_rightside_atk(sd) ((sd)->battle_status.rhw.atk2 + (sd)->battle_status.lhw.atk2) diff --git a/src/map/skill.c b/src/map/skill.c index 1d94e0b14..eb7394b9e 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -9599,7 +9599,7 @@ int skill_castend_nodamage_id(struct block_list *src, struct block_list *bl, uin if (tsc->data[scs[i]]) status_change_end(bl, scs[i], INVALID_TIMER); } } - heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->battle_status, status->get_lv(&hd->bl)); + heal = 5 * status->get_lv(&hd->bl) + status->base_matk(&hd->bl, &hd->battle_status, status->get_lv(&hd->bl)); status->heal(bl, heal, 0, 0); clif->skill_nodamage(src, src, skill_id, skill_lv, clif->skill_nodamage(src, bl, AL_HEAL, heal, 1)); status->change_start(src, src, type, 1000, skill_lv, 0, 0, 0, skill->get_time(skill_id,skill_lv), SCFLAG_NOAVOID|SCFLAG_FIXEDTICK|SCFLAG_FIXEDRATE); diff --git a/src/map/status.c b/src/map/status.c index d7146adf6..bad818b74 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -1851,237 +1851,6 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, uin return 1; } -//Checks whether the source can see and chase target. -int status_check_visibility(struct block_list *src, struct block_list *target) { - int view_range; - struct status_change *tsc = NULL; - - switch (src->type) { - case BL_MOB: - view_range = ((TBL_MOB*)src)->min_chase; - break; - case BL_PET: - view_range = ((TBL_PET*)src)->db->range2; - break; - default: - view_range = AREA_SIZE; - } - - if (src->m != target->m || !check_distance_bl(src, target, view_range)) - return 0; - - if( src->type == BL_NPC ) /* NPCs don't care for the rest */ - return 1; - - if( ( tsc = status->get_sc(target) ) ) { - struct status_data *st = status->get_status_data(src); - - switch (target->type) { //Check for chase-walk/hiding/cloaking opponents. - case BL_PC: - if ( tsc->data[SC_CLOAKINGEXCEED] && !(st->mode&MD_BOSS) ) - return 0; - if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_STEALTHFIELD] || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&MD_BOSS) && - ( ((TBL_PC*)target)->special_state.perfect_hiding || !(st->mode&MD_DETECTOR) ) ) - return 0; - break; - default: - if( (tsc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&(MD_BOSS|MD_DETECTOR)) ) - return 0; - - } - } - - return 1; -} - -// Basic ASPD value -int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) { - int amotion; -#ifdef RENEWAL_ASPD - short mod = -1; - - switch( sd->weapontype2 ){ // adjustment for dual wielding - case W_DAGGER: - mod = 0; - break; // 0, 1, 1 - case W_1HSWORD: - case W_1HAXE: - mod = 1; - if( (sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS ) // 0, 2, 3 - mod = sd->weapontype2 / W_1HSWORD + W_1HSWORD / sd->weapontype2; - } - - amotion = ( sd->status.weapon < MAX_WEAPON_TYPE && mod < 0 ) - ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : ((status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] // dual-wield - + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod - - status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] - + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]); - - if ( sd->status.shield ) - amotion += ( 2000 - status->aspd_base[pc->class2idx(sd->status.class_)][W_FIST] ) + - ( status->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000 ); - -#else - // base weapon delay - amotion = (sd->status.weapon < MAX_WEAPON_TYPE) - ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon - : (status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2])*7/10; // dual-wield - - // percentual delay reduction from stats - amotion -= amotion * (4*st->agi + st->dex)/1000; -#endif - // raw delay adjustment from bAspd bonus - amotion += sd->bonus.aspd_add; - - /* angra manyu disregards aspd_base and similar */ - if( sd->equip_index[EQI_HAND_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid == ITEMID_ANGRA_MANYU ) - return 0; - - return amotion; -} - -unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) { - int flag = 0, str, dex, -#ifdef RENEWAL - rstr, -#endif - dstr; - - - if(!(bl->type&battle_config.enable_baseatk)) - return 0; - - if (bl->type == BL_PC) - switch(((TBL_PC*)bl)->status.weapon){ - case W_BOW: - case W_MUSICAL: - case W_WHIP: - case W_REVOLVER: - case W_RIFLE: - case W_GATLING: - case W_SHOTGUN: - case W_GRENADE: - flag = 1; - } - if (flag) { -#ifdef RENEWAL - rstr = -#endif - str = st->dex; - dex = st->str; - } else { -#ifdef RENEWAL - rstr = -#endif - str = st->str; - dex = st->dex; - } - //Normally only players have base-atk, but homunc have a different batk - // equation, hinting that perhaps non-players should use this for batk. - // [Skotlex] -#ifdef RENEWAL - if (bl->type == BL_HOM) - str = (int)(floor((rstr + dex + st->luk) / 3) + floor(((TBL_HOM*)bl)->homunculus.level / 10)); -#endif - dstr = str/10; - str += dstr*dstr; - if (bl->type == BL_PC) -#ifdef RENEWAL - str = (int)(rstr + (float)dex/5 + (float)st->luk/3 + (float)((TBL_PC*)bl)->status.base_level/4); - else if(bl->type == BL_MOB) - str = rstr + ((TBL_MOB*)bl)->level; -#else - str+= dex/5 + st->luk/5; -#endif - return cap_value(str, 0, USHRT_MAX); -} - -#ifndef RENEWAL -static inline unsigned short status_base_matk_min(const struct status_data *st){ return st->int_+(st->int_/7)*(st->int_/7); } -#endif // not RENEWAL -static inline unsigned short status_base_matk_max(const struct status_data *st){ return st->int_+(st->int_/5)*(st->int_/5); } - -unsigned short status_base_matk(const struct status_data *st, int level) { -#ifdef RENEWAL - return st->int_+(st->int_/2)+(st->dex/5)+(st->luk/3)+(level/4); -#else - return 0; -#endif -} - -//Fills in the misc data that can be calculated from the other status info (except for level) -void status_calc_misc(struct block_list *bl, struct status_data *st, int level) { - //Non players get the value set, players need to stack with previous bonuses. - if( bl->type != BL_PC ) - st->batk = - st->hit = st->flee = - st->def2 = st->mdef2 = - st->cri = st->flee2 = 0; - -#ifdef RENEWAL // renewal formulas - if (bl->type == BL_HOM) { - st->hit = level + st->dex + 150; //base level + dex + 150 - st->flee = level + st->agi + level/10; //base level + agi + base level/10 - } else { - st->matk_min = st->matk_max = bl->type == BL_PC ? status->base_matk(st, level) : level + st->int_; - st->hit += level + st->dex + (bl->type == BL_PC ? st->luk/3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 - st->flee += level + st->agi + (bl->type == BL_PC ? st->luk/5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 - st->def2 += (int)(((float)level + st->vit)/2 + ( bl->type == BL_PC ? ((float)st->agi/5) : 0 )); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) - st->mdef2 += (int)( bl->type == BL_PC ?(st->int_ + ((float)level/4) + ((float)(st->dex+st->vit)/5)):((float)(st->int_ + level)/4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) - } -#else // not RENEWAL - st->matk_min = status_base_matk_min(st); - st->matk_max = status_base_matk_max(st); - st->hit += level + st->dex; - st->flee += level + st->agi; - st->def2 += st->vit; - st->mdef2 += st->int_ + (st->vit>>1); -#endif // RENEWAL - - if( bl->type&battle_config.enable_critical ) - st->cri += 10 + (st->luk*10/3); //(every 1 luk = +0.3 critical) - else - st->cri = 0; - - if (bl->type&battle_config.enable_perfect_flee) - st->flee2 += st->luk + 10; //(every 10 luk = +1 perfect flee) - else - st->flee2 = 0; - - if (st->batk) { - int temp = st->batk + status->base_atk(bl, st); - st->batk = cap_value(temp, 0, USHRT_MAX); - } else - st->batk = status->base_atk(bl, st); - if (st->cri) - switch (bl->type) { - case BL_MOB: - if(battle_config.mob_critical_rate != 100) - st->cri = st->cri*battle_config.mob_critical_rate/100; - if(!st->cri && battle_config.mob_critical_rate) - st->cri = 10; - break; - case BL_PC: - //Players don't have a critical adjustment setting as of yet. - break; - case BL_MER: -#ifdef RENEWAL - st->matk_min = st->matk_max = status_base_matk_max(st); - st->def2 = st->vit + level / 10 + st->vit / 5; - st->mdef2 = level / 10 + st->int_ / 5; -#endif - break; - default: - if(battle_config.critical_rate != 100) - st->cri = st->cri*battle_config.critical_rate/100; - if (!st->cri && battle_config.critical_rate) - st->cri = 10; - } - if(bl->type&BL_REGEN) - status->calc_regen(bl, st, status->get_regen_data(bl)); -} - //Skotlex: Calculates the initial status for the given mob //first will only be false when the mob leveled up or got a GuardUp level. int status_calc_mob_(struct mob_data* md, enum e_status_calc_opt opt) { @@ -3284,105 +3053,17 @@ int status_calc_mercenary_(struct mercenary_data *md, enum e_status_calc_opt opt return 0; } -int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { - struct status_data *hstatus = &hd->base_status; - struct s_homunculus *hom = &hd->homunculus; - int skill_lv; - int amotion; - - hstatus->str = hom->str / 10; - hstatus->agi = hom->agi / 10; - hstatus->vit = hom->vit / 10; - hstatus->dex = hom->dex / 10; - hstatus->int_ = hom->int_ / 10; - hstatus->luk = hom->luk / 10; - - if ( opt&SCO_FIRST ) { //[orn] - const struct s_homunculus_db *db = hd->homunculusDB; - hstatus->def_ele = db->element; - hstatus->ele_lv = 1; - hstatus->race = db->race; - hstatus->size = (hom->class_ == db->evo_class)?db->evo_size:db->base_size; - hstatus->rhw.range = 1 + hstatus->size; - hstatus->mode = MD_CANMOVE|MD_CANATTACK; - hstatus->speed = DEFAULT_WALK_SPEED; - if (battle_config.hom_setting&0x8 && hd->master) - hstatus->speed = status->get_speed(&hd->master->bl); - - hstatus->hp = 1; - hstatus->sp = 1; - } - - hstatus->aspd_rate = 1000; - -#ifdef RENEWAL - hstatus->def = (hstatus->vit + (hom->level / 10)) + ((hstatus->agi + (hom->level / 10)) / 2); - hstatus->mdef = hstatus->int_ + ((hstatus->int_ + hstatus->dex + hstatus->luk) / 3) + (hom->level / 10) * 2; - - amotion = (1000 -2*hstatus->agi -hstatus->dex) * hd->homunculusDB->baseASPD/1000; -#else - skill_lv = hom->level/10 + hstatus->vit/5; - hstatus->def = cap_value(skill_lv, 0, 99); - - skill_lv = hom->level/10 + hstatus->int_/5; - hstatus->mdef = cap_value(skill_lv, 0, 99); - amotion = (1000 -4*hstatus->agi - hstatus->dex) * hd->homunculusDB->baseASPD/1000; -#endif - - hstatus->amotion = cap_value(amotion,battle_config.max_aspd,2000); - hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus. - - - hstatus->max_hp = hom->max_hp; - hstatus->max_sp = hom->max_sp; - - homun->calc_skilltree(hd, 0); - - if((skill_lv=homun->checkskill(hd,HAMI_SKIN)) > 0) - hstatus->def += skill_lv * 4; - - if((skill_lv = homun->checkskill(hd,HVAN_INSTRUCT)) > 0) { - hstatus->int_ += 1 +skill_lv/2 +skill_lv/4 +skill_lv/5; - hstatus->str += 1 +skill_lv/3 +skill_lv/3 +skill_lv/4; - } - - if((skill_lv=homun->checkskill(hd,HAMI_SKIN)) > 0) - hstatus->max_hp += skill_lv * 2 * hstatus->max_hp / 100; - - if((skill_lv = homun->checkskill(hd,HLIF_BRAIN)) > 0) - hstatus->max_sp += (1 +skill_lv/2 -skill_lv/4 +skill_lv/5) * hstatus->max_sp / 100; - - if ( opt&SCO_FIRST ) { - hd->battle_status.hp = hom->hp; - hd->battle_status.sp = hom->sp; - } - -#ifndef RENEWAL - hstatus->rhw.atk = hstatus->dex; - hstatus->rhw.atk2 = hstatus->str + hom->level; -#endif - - status->calc_misc(&hd->bl, hstatus, hom->level); - -#ifdef RENEWAL - hstatus->matk_max = hstatus->matk_min; -#endif - - status_cpy(&hd->battle_status, hstatus); - return 1; -} - int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt) { struct status_data *estatus = &ed->base_status; struct s_elemental *ele = &ed->elemental; struct map_session_data *sd = ed->master; - if( !sd ) + if ( !sd ) return 0; - if( opt&SCO_FIRST ) { + if ( opt&SCO_FIRST ) { memcpy(estatus, &ed->db->status, sizeof(struct status_data)); - if( !ele->mode ) + if ( !ele->mode ) estatus->mode = EL_MODE_PASSIVE; else estatus->mode = ele->mode; @@ -3402,7 +3083,7 @@ int status_calc_elemental_(struct elemental_data *ed, enum e_status_calc_opt opt estatus->flee = ele->flee; estatus->hit = ele->hit; - memcpy(&ed->battle_status,estatus,sizeof(struct status_data)); + memcpy(&ed->battle_status, estatus, sizeof(struct status_data)); } else { status->calc_misc(&ed->bl, estatus, 0); status_cpy(&ed->battle_status, estatus); @@ -3445,6 +3126,89 @@ int status_calc_npc_(struct npc_data *nd, enum e_status_calc_opt opt) { return 0; } +int status_calc_homunculus_(struct homun_data *hd, enum e_status_calc_opt opt) { + struct status_data *hstatus = &hd->base_status; + struct s_homunculus *hom = &hd->homunculus; + int skill_lv; + int amotion; + + hstatus->str = hom->str / 10; + hstatus->agi = hom->agi / 10; + hstatus->vit = hom->vit / 10; + hstatus->dex = hom->dex / 10; + hstatus->int_ = hom->int_ / 10; + hstatus->luk = hom->luk / 10; + + APPLY_HOMUN_LEVEL_STATWEIGHT(); + + if ( opt&SCO_FIRST ) { //[orn] + const struct s_homunculus_db *db = hd->homunculusDB; + hstatus->def_ele = db->element; + hstatus->ele_lv = 1; + hstatus->race = db->race; + hstatus->size = (hom->class_ == db->evo_class) ? db->evo_size : db->base_size; + hstatus->rhw.range = 1 + hstatus->size; + hstatus->mode = MD_CANMOVE | MD_CANATTACK; + hstatus->speed = DEFAULT_WALK_SPEED; + if ( battle_config.hom_setting & 0x8 && hd->master ) + hstatus->speed = status->get_speed(&hd->master->bl); + + hstatus->hp = 1; + hstatus->sp = 1; + } + + hstatus->aspd_rate = 1000; + +#ifdef RENEWAL + amotion = hd->homunculusDB->baseASPD; + amotion = amotion - amotion * (hstatus->dex + hom->dex_value) / 1000 - (hstatus->agi + hom->agi_value) * amotion / 250; +#else + skill_lv = hom->level / 10 + hstatus->vit / 5; + hstatus->def = cap_value(skill_lv, 0, 99); + + skill_lv = hom->level / 10 + hstatus->int_ / 5; + hstatus->mdef = cap_value(skill_lv, 0, 99); + amotion = (1000 - 4 * hstatus->agi - hstatus->dex) * hd->homunculusDB->baseASPD / 1000; +#endif + + hstatus->amotion = cap_value(amotion, battle_config.max_aspd, 2000); + hstatus->adelay = hstatus->amotion; //It seems adelay = amotion for Homunculus. + + + hstatus->max_hp = hom->max_hp; + hstatus->max_sp = hom->max_sp; + + homun->calc_skilltree(hd, 0); + + if ( (skill_lv = homun->checkskill(hd, HAMI_SKIN)) > 0 ) + hstatus->def += skill_lv * 4; + + if ( (skill_lv = homun->checkskill(hd, HVAN_INSTRUCT)) > 0 ) { + hstatus->int_ += 1 + skill_lv / 2 + skill_lv / 4 + skill_lv / 5; + hstatus->str += 1 + skill_lv / 3 + skill_lv / 3 + skill_lv / 4; + } + + if ( (skill_lv = homun->checkskill(hd, HAMI_SKIN)) > 0 ) + hstatus->max_hp += skill_lv * 2 * hstatus->max_hp / 100; + + if ( (skill_lv = homun->checkskill(hd, HLIF_BRAIN)) > 0 ) + hstatus->max_sp += (1 + skill_lv / 2 - skill_lv / 4 + skill_lv / 5) * hstatus->max_sp / 100; + + if ( opt&SCO_FIRST ) { + hd->battle_status.hp = hom->hp; + hd->battle_status.sp = hom->sp; + } + +#ifndef RENEWAL + hstatus->rhw.atk = hstatus->dex; + hstatus->rhw.atk2 = hstatus->str + hom->level; +#endif + + status->calc_misc(&hd->bl, hstatus, hom->level); + + status_cpy(&hd->battle_status, hstatus); + return 1; +} //Calculates base regen values. void status_calc_regen(struct block_list *bl, struct status_data *st, struct regen_data *regen) { @@ -3742,13 +3506,6 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { st->lhw.atk2 = status->calc_watk(bl, sc, bst->lhw.atk2, true); } } - - /*if( bl->type&BL_HOM ) { - st->rhw.atk += (st->dex - bst->dex); - st->rhw.atk2 += (st->str - bst->str); - if( st->rhw.atk2 < st->rhw.atk ) - st->rhw.atk2 = st->rhw.atk; - }*/ } if(flag&SCB_HIT) { @@ -3928,80 +3685,82 @@ void status_calc_bl_main(struct block_list *bl, /*enum scb_flag*/int flag) { if(flag&SCB_MATK) { status->update_matk(bl); } + + if ( flag&SCB_DSPD ) { + int dmotion; + if ( bl->type&BL_PC ) { + if (bst->agi == st->agi) + st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion); + else { + dmotion = 800-st->agi*4; + st->dmotion = cap_value(dmotion, 400, 800); + if ( battle_config.pc_damage_delay_rate != 100 ) + st->dmotion = st->dmotion*battle_config.pc_damage_delay_rate / 100; + //It's safe to ignore bst->dmotion since no bonus affects it. + st->dmotion = status->calc_dmotion(bl, sc, st->dmotion); + } + } else if ( bl->type&BL_HOM ) { + dmotion = 800 - st->agi * 4; + st->dmotion = cap_value(dmotion, 400, 800); + st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion); + } else { // mercenary and mobs + st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion); + } + } if(flag&SCB_ASPD) { int amotion; - if( bl->type&BL_PC ) { - amotion = status->base_amotion_pc(sd,st); -#ifndef RENEWAL_ASPD - st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate); - - if(st->aspd_rate != 1000) - amotion = amotion*st->aspd_rate/1000; + if ( bl->type&BL_HOM ) { +#ifdef RENEWAL + amotion = ((TBL_HOM*)bl)->homunculusDB->baseASPD; + amotion = amotion - amotion * status_get_homdex(bl) / 1000 - status_get_homagi(bl) * amotion / 250; + amotion = (amotion * status->calc_aspd(bl, sc, 1) + status->calc_aspd(bl, sc, 2)) / -100 + amotion; #else - // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200)) - amotion -= (int)(sqrt( (pow(st->agi, 2) / 2) + (pow(st->dex, 2) / 5) ) / 4 + ((float)status->calc_aspd(bl, sc, 1) * st->agi / 200)) * 10; + amotion = (1000 - 4 * st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD / 1000; - if( (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) != 0 ) // RE ASPD percertage modifier - amotion -= (( amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd) ) - * (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) / 10 + 5) / 10; + amotion = status->calc_aspd_rate(bl, sc, bst->aspd_rate); - if(st->aspd_rate != 1000) // absolute percentage modifier - amotion = ( 200 - (200-amotion/10) * st->aspd_rate / 1000 ) * 10; + if ( st->aspd_rate != 1000 ) + amotion = amotion*st->aspd_rate / 1000; #endif amotion = status->calc_fix_aspd(bl, sc, amotion); - st->amotion = cap_value(amotion,((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd),2000); + st->amotion = cap_value(amotion, battle_config.max_aspd, 2000); - st->adelay = 2*st->amotion; - } else if( bl->type&BL_HOM ) { -#ifdef RENEWAL - amotion = (1000 - 2*st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000; -#else - amotion = (1000 - 4*st->agi - st->dex) * ((TBL_HOM*)bl)->homunculusDB->baseASPD/1000; -#endif + st->adelay = st->amotion; + } else if ( bl->type&BL_PC ) { + amotion = status->base_amotion_pc(sd, st); +#ifndef RENEWAL_ASPD st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate); if(st->aspd_rate != 1000) amotion = amotion*st->aspd_rate/1000; +#else + // aspd = baseaspd + floor(sqrt((agi^2/2) + (dex^2/5))/4 + (potskillbonus*agi/200)) + amotion -= (int)(sqrt((pow(st->agi, 2) / 2) + (pow(st->dex, 2) / 5)) / 4 + ((float)status->calc_aspd(bl, sc, 1) * st->agi / 200)) * 10; + + if ( (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) != 0 ) // RE ASPD percertage modifier + amotion -= ((amotion - ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd)) + * (status->calc_aspd(bl, sc, 2) + st->aspd_rate2) / 10 + 5) / 10; + if ( st->aspd_rate != 1000 ) // absolute percentage modifier + amotion = (200 - (200 - amotion / 10) * st->aspd_rate / 1000) * 10; +#endif amotion = status->calc_fix_aspd(bl, sc, amotion); - st->amotion = cap_value(amotion,battle_config.max_aspd,2000); + st->amotion = cap_value(amotion, ((sd->class_&JOBL_THIRD) ? battle_config.max_third_aspd : battle_config.max_aspd), 2000); - st->adelay = st->amotion; + st->adelay = 2 * st->amotion; } else { // mercenary and mobs amotion = bst->amotion; st->aspd_rate = status->calc_aspd_rate(bl, sc, bst->aspd_rate); - if(st->aspd_rate != 1000) - amotion = amotion*st->aspd_rate/1000; + if ( st->aspd_rate != 1000 ) + amotion = amotion*st->aspd_rate / 1000; amotion = status->calc_fix_aspd(bl, sc, amotion); st->amotion = cap_value(amotion, battle_config.monster_max_aspd, 2000); - temp = bst->adelay*st->aspd_rate/1000; - st->adelay = cap_value(temp, battle_config.monster_max_aspd*2, 4000); - } - } - - if(flag&SCB_DSPD) { - int dmotion; - if( bl->type&BL_PC ) { - if (bst->agi == st->agi) - st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion); - else { - dmotion = 800-st->agi*4; - st->dmotion = cap_value(dmotion, 400, 800); - if(battle_config.pc_damage_delay_rate != 100) - st->dmotion = st->dmotion*battle_config.pc_damage_delay_rate/100; - //It's safe to ignore bst->dmotion since no bonus affects it. - st->dmotion = status->calc_dmotion(bl, sc, st->dmotion); - } - } else if( bl->type&BL_HOM ) { - dmotion = 800-st->agi*4; - st->dmotion = cap_value(dmotion, 400, 800); - st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion); - } else { // mercenary and mobs - st->dmotion = status->calc_dmotion(bl, sc, bst->dmotion); + temp = bst->adelay*st->aspd_rate / 1000; + st->adelay = cap_value(temp, battle_config.monster_max_aspd * 2, 4000); } } @@ -4193,6 +3952,245 @@ void status_calc_bl_(struct block_list *bl, enum scb_flag flag, enum e_status_ca clif->mercenary_updatestatus(ed->master, SP_SP); } } +//Checks whether the source can see and chase target. +int status_check_visibility(struct block_list *src, struct block_list *target) { + int view_range; + struct status_change *tsc = NULL; + + switch ( src->type ) { + case BL_MOB: + view_range = ((TBL_MOB*)src)->min_chase; + break; + case BL_PET: + view_range = ((TBL_PET*)src)->db->range2; + break; + default: + view_range = AREA_SIZE; + } + + if ( src->m != target->m || !check_distance_bl(src, target, view_range) ) + return 0; + + if ( src->type == BL_NPC ) /* NPCs don't care for the rest */ + return 1; + + if ( (tsc = status->get_sc(target)) ) { + struct status_data *st = status->get_status_data(src); + + switch ( target->type ) { //Check for chase-walk/hiding/cloaking opponents. + case BL_PC: + if ( tsc->data[SC_CLOAKINGEXCEED] && !(st->mode&MD_BOSS) ) + return 0; + if ( (tsc->option&(OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || tsc->data[SC_STEALTHFIELD] || tsc->data[SC__INVISIBILITY] || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&MD_BOSS) && + (((TBL_PC*)target)->special_state.perfect_hiding || !(st->mode&MD_DETECTOR)) ) + return 0; + break; + default: + if ( (tsc->option&(OPTION_HIDE | OPTION_CLOAK | OPTION_CHASEWALK) || tsc->data[SC_CAMOUFLAGE]) && !(st->mode&(MD_BOSS | MD_DETECTOR)) ) + return 0; + + } + } + + return 1; +} + +// Basic ASPD value +int status_base_amotion_pc(struct map_session_data *sd, struct status_data *st) { + int amotion; +#ifdef RENEWAL_ASPD + short mod = -1; + + switch ( sd->weapontype2 ) { // adjustment for dual wielding + case W_DAGGER: + mod = 0; + break; // 0, 1, 1 + case W_1HSWORD: + case W_1HAXE: + mod = 1; + if ( (sd->class_&MAPID_THIRDMASK) == MAPID_GUILLOTINE_CROSS ) // 0, 2, 3 + mod = sd->weapontype2 / W_1HSWORD + W_1HSWORD / sd->weapontype2; + } + + amotion = (sd->status.weapon < MAX_WEAPON_TYPE && mod < 0) + ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon + : ((status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] // dual-wield + + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 6 / 10 + 10 * mod + - status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2] + + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1]); + + if ( sd->status.shield ) + amotion += (2000 - status->aspd_base[pc->class2idx(sd->status.class_)][W_FIST]) + + (status->aspd_base[pc->class2idx(sd->status.class_)][MAX_WEAPON_TYPE] - 2000); + +#else + // base weapon delay + amotion = (sd->status.weapon < MAX_WEAPON_TYPE) + ? (status->aspd_base[pc->class2idx(sd->status.class_)][sd->status.weapon]) // single weapon + : (status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype1] + status->aspd_base[pc->class2idx(sd->status.class_)][sd->weapontype2]) * 7 / 10; // dual-wield + + // percentual delay reduction from stats + amotion -= amotion * (4 * st->agi + st->dex) / 1000; +#endif + // raw delay adjustment from bAspd bonus + amotion += sd->bonus.aspd_add; + + /* angra manyu disregards aspd_base and similar */ + if ( sd->equip_index[EQI_HAND_R] >= 0 && sd->status.inventory[sd->equip_index[EQI_HAND_R]].nameid == ITEMID_ANGRA_MANYU ) + return 0; + + return amotion; +} + +unsigned short status_base_atk(const struct block_list *bl, const struct status_data *st) { + int flag = 0, str, dex, dstr; + + if ( !(bl->type&battle_config.enable_baseatk) ) + return 0; + + if ( bl->type == BL_PC ) + switch ( ((TBL_PC*)bl)->status.weapon ) { + case W_BOW: + case W_MUSICAL: + case W_WHIP: + case W_REVOLVER: + case W_RIFLE: + case W_GATLING: + case W_SHOTGUN: + case W_GRENADE: + flag = 1; + } + if ( flag ) { +#ifdef RENEWAL + dstr = +#endif + str = st->dex; + dex = st->str; + } else { +#ifdef RENEWAL + dstr = +#endif + str = st->str; + dex = st->dex; + } + //Normally only players have base-atk, but homunc have a different batk + // equation, hinting that perhaps non-players should use this for batk. + // [Skotlex] +#ifdef RENEWAL + if ( bl->type == BL_HOM ) + str = 2 * (((TBL_HOM*)bl)->homunculus.level + status_get_homstr(bl)); +#else + dstr = str / 10; + str += dstr*dstr; +#endif + if ( bl->type == BL_PC ) +#ifdef RENEWAL + str = (int)(dstr + (float)dex / 5 + (float)st->luk / 3 + (float)((TBL_PC*)bl)->status.base_level / 4); + else if ( bl->type == BL_MOB ) + str = dstr + ((TBL_MOB*)bl)->level; +#else + str += dex / 5 + st->luk / 5; +#endif + return cap_value(str, 0, USHRT_MAX); +} + +#ifndef RENEWAL +static inline unsigned short status_base_matk_min(const struct status_data *st) { return st->int_ + (st->int_ / 7)*(st->int_ / 7); } +#endif // not RENEWAL +static inline unsigned short status_base_matk_max(const struct status_data *st) { return st->int_ + (st->int_ / 5)*(st->int_ / 5); } + +unsigned short status_base_matk(struct block_list *bl, const struct status_data *st, int level) { +#ifdef RENEWAL + switch ( bl->type ) { + case BL_MOB: + return st->int_ + level; + case BL_HOM: + return status_get_homint(bl) + level; + case BL_PC: + default: // temporary until all are formulated + return st->int_ + (st->int_ / 2) + (st->dex / 5) + (st->luk / 3) + (level / 4); + } +#else + return 0; +#endif +} + +//Fills in the misc data that can be calculated from the other status info (except for level) +void status_calc_misc(struct block_list *bl, struct status_data *st, int level) { + //Non players get the value set, players need to stack with previous bonuses. + if ( bl->type != BL_PC ) + st->batk = + st->hit = st->flee = + st->def2 = st->mdef2 = + st->cri = st->flee2 = 0; + +#ifdef RENEWAL // renewal formulas + if ( bl->type == BL_HOM ) { + st->def2 = status_get_homvit(bl) + status_get_homagi(bl) / 2; + st->mdef2 = (status_get_homvit(bl) + status_get_homint(bl)) / 2; + st->def += status_get_homvit(bl) + level / 2; + st->mdef = (int)(((float)status_get_homvit(bl) + level) / 4 + (float)status_get_homint(bl) / 2); + st->hit = level + st->dex + 150; + st->flee = level + status_get_homagi(bl); + st->rhw.atk = (status_get_homstr(bl) + status_get_homdex(bl)) / 5; + st->rhw.atk2 = (status_get_homluk(bl) + status_get_homstr(bl) + status_get_homdex(bl)) / 3; + } else { + st->hit += level + st->dex + (bl->type == BL_PC ? st->luk / 3 + 175 : 150); //base level + ( every 1 dex = +1 hit ) + (every 3 luk = +1 hit) + 175 + st->flee += level + st->agi + (bl->type == BL_PC ? st->luk / 5 : 0) + 100; //base level + ( every 1 agi = +1 flee ) + (every 5 luk = +1 flee) + 100 + st->def2 += (int)(((float)level + st->vit) / 2 + (bl->type == BL_PC ? ((float)st->agi / 5) : 0)); //base level + (every 2 vit = +1 def) + (every 5 agi = +1 def) + st->mdef2 += (int)(bl->type == BL_PC ? (st->int_ + ((float)level / 4) + ((float)(st->dex + st->vit) / 5)) : ((float)(st->int_ + level) / 4)); //(every 4 base level = +1 mdef) + (every 1 int = +1 mdef) + (every 5 dex = +1 mdef) + (every 5 vit = +1 mdef) + } +#else // not RENEWAL + st->matk_min = status_base_matk_min(st); + st->matk_max = status_base_matk_max(st); + st->hit += level + st->dex; + st->flee += level + st->agi; + st->def2 += st->vit; + st->mdef2 += st->int_ + (st->vit >> 1); +#endif // RENEWAL + + if ( bl->type&battle_config.enable_critical ) + st->cri += 10 + (st->luk * 10 / 3); //(every 1 luk = +0.3 critical) + else + st->cri = 0; + + if ( bl->type&battle_config.enable_perfect_flee ) + st->flee2 += st->luk + 10; //(every 10 luk = +1 perfect flee) + else + st->flee2 = 0; + + if ( st->batk ) { + int temp = st->batk + status->base_atk(bl, st); + st->batk = cap_value(temp, 0, USHRT_MAX); + } else + st->batk = status->base_atk(bl, st); + if ( st->cri ) + switch ( bl->type ) { + case BL_MOB: + if ( battle_config.mob_critical_rate != 100 ) + st->cri = st->cri*battle_config.mob_critical_rate / 100; + if ( !st->cri && battle_config.mob_critical_rate ) + st->cri = 10; + break; + case BL_PC: + //Players don't have a critical adjustment setting as of yet. + break; + case BL_MER: +#ifdef RENEWAL + st->matk_min = st->matk_max = status_base_matk_max(st); + st->def2 = st->vit + level / 10 + st->vit / 5; + st->mdef2 = level / 10 + st->int_ / 5; +#endif + break; + default: + if ( battle_config.critical_rate != 100 ) + st->cri = st->cri*battle_config.critical_rate / 100; + if ( !st->cri && battle_config.critical_rate ) + st->cri = 10; + } + if ( bl->type&BL_REGEN ) + status->calc_regen(bl, st, status->get_regen_data(bl)); +} /*========================================== * Apply shared stat mods from status changes [DracoRPG] @@ -5558,7 +5556,7 @@ short status_calc_fix_aspd(struct block_list *bl, struct status_change *sc, int aspd -= 10; if (sc->data[SC_OVERED_BOOST]) // should be final and unmodifiable by any means - aspd = 2000 - sc->data[SC_OVERED_BOOST]->val3 * 10; + aspd = (200 - sc->data[SC_OVERED_BOOST]->val3) * 10; return cap_value(aspd, 0, 2000); // will be recap for proper bl anyway } @@ -11444,10 +11442,20 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl min = (int)(watk->atk - variance + strdex_bonus) + watk->atk2; max = (int)(watk->atk + variance + strdex_bonus) + watk->atk2; - }else if( watk->atk ){ + } + else if (bl->type == BL_MOB && watk->atk){ min = watk->atk * 80 / 100; max = watk->atk * 120 / 100; } + else if (bl->type == BL_HOM && watk->atk){ + if (flag & 4){ + max = min = status->get_matk(bl, 2); + } + else{ + min = watk->atk; + max = watk->atk2; + } + } if( !(flag&1) ){ if( max > min ) @@ -11456,8 +11464,15 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl max = min; } - if( bl->type == BL_PC && ((TBL_PC*)bl)->right_weapon.overrefine > 0 && !(flag&2) ) - max += rnd()%((TBL_PC*)bl)->right_weapon.overrefine + 1; + if ( bl->type == BL_PC && !(flag & 2) ) { + struct map_session_data *sd = (struct map_session_data *)bl; + short index = sd->equip_index[EQI_HAND_R], refine; + if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON + && (refine = sd->status.inventory[index].refine) < 16 && refine ) { + int r = (rnd() % 100) % ((status->refine_info[watk->wlv].randombonus_max[refine + (4 - watk->wlv)] / 100)) + 1; + max += r / 10; + } + } max = status->calc_watk(bl, sc, max, false); @@ -11468,31 +11483,21 @@ int status_get_weapon_atk(struct block_list *bl, struct weapon_atk *watk, int fl } /** - * Gets a random matk value depending on min matk and max matk - **/ -unsigned short status_get_rand_matk( unsigned short matk_max, unsigned short matk_min ) { - if( matk_max > matk_min ) - return matk_min + rnd()%(matk_max - matk_min); - else - return matk_min; -} - -/** - * Get bl's matk_max and matk_min values depending on flag - * @param flag - * 0 - Get MATK - * 1 - Get MATK w/o SC bonuses - * 3 - Get MATK w/o EATK & SC bonuses - **/ -void status_get_matk_sub( struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min ) { +* Get bl's matk_max and matk_min values depending on flag +* @param flag +* 0 - Get MATK +* 1 - Get MATK w/o SC bonuses +* 3 - Get MATK w/o EATK & SC bonuses +**/ +void status_get_matk_sub(struct block_list *bl, int flag, unsigned short *matk_max, unsigned short *matk_min) { struct status_data *st; struct status_change *sc; struct map_session_data *sd; - if( bl == NULL ) + if ( bl == NULL ) return; - if( flag != 0 && flag != 1 && flag != 3 ) { + if ( flag != 0 && flag != 1 && flag != 3 ) { ShowError("status_get_matk_sub: Unknown flag %d!\n", flag); return; } @@ -11503,107 +11508,120 @@ void status_get_matk_sub( struct block_list *bl, int flag, unsigned short *matk_ #ifdef RENEWAL /** - * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK) - * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers - **/ - *matk_min = status->base_matk(st, status->get_lv(bl)); + * RE MATK Formula (from irowiki:http://irowiki.org/wiki/MATK) + * MATK = (sMATK + wMATK + eMATK) * Multiplicative Modifiers + **/ + *matk_min = status->base_matk(bl, st, status->get_lv(bl)); // Any +MATK you get from skills and cards, including cards in weapon, is added here. - if( sd && sd->bonus.ematk > 0 && flag != 3 ) + if ( sd && sd->bonus.ematk > 0 && flag != 3 ) *matk_min += sd->bonus.ematk; - if( flag != 3 ) + if ( flag != 3 ) *matk_min = status->calc_ematk(bl, sc, *matk_min); *matk_max = *matk_min; - //This is the only portion in MATK that varies depending on the weapon level and refinement rate. - if( bl->type&BL_PC && (st->rhw.matk + st->lhw.matk) > 0 ) { - int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks - int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level - *matk_min += wMatk - variance; - *matk_max += wMatk + variance; - } else if( bl->type&BL_MOB ) { - *matk_min = *matk_max = status_get_int(bl) + status->get_lv(bl); + switch ( bl->type ) { + case BL_PC: + //This is the only portion in MATK that varies depending on the weapon level and refinement rate. + if ( (st->rhw.matk + st->lhw.matk) > 0 ) { + int wMatk = st->rhw.matk + st->lhw.matk; // Left and right matk stacks + int variance = wMatk * st->rhw.wlv / 10; // Only use right hand weapon level + *matk_min += wMatk - variance; + *matk_max += wMatk + variance; + } + break; + case BL_MOB: *matk_min += 70 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; *matk_max += 130 * ((TBL_MOB*)bl)->status.rhw.atk2 / 100; + break; + case BL_HOM: + *matk_min += (status_get_homint(bl) + status_get_homdex(bl)) / 5; + *matk_max += (status_get_homluk(bl) + status_get_homint(bl) + status_get_homdex(bl)) / 3; + break; } + #else // not RENEWAL - *matk_min = status_base_matk_min(st) + (sd?sd->bonus.ematk:0); - *matk_max = status_base_matk_max(st) + (sd?sd->bonus.ematk:0); + *matk_min = status_base_matk_min(st) + (sd ? sd->bonus.ematk : 0); + *matk_max = status_base_matk_max(st) + (sd ? sd->bonus.ematk : 0); #endif - if (sd && sd->matk_rate != 100) { - *matk_max = (*matk_max) * sd->matk_rate/100; - *matk_min = (*matk_min) * sd->matk_rate/100; + if ( sd && sd->matk_rate != 100 ) { + *matk_max = (*matk_max) * sd->matk_rate / 100; + *matk_min = (*matk_min) * sd->matk_rate / 100; } - if ((bl->type&BL_HOM && battle_config.hom_setting&0x20) //Hom Min Matk is always the same as Max Matk - || (sc && sc->data[SC_RECOGNIZEDSPELL])) + if ( (bl->type&BL_HOM && battle_config.hom_setting & 0x20) //Hom Min Matk is always the same as Max Matk + || (sc && sc->data[SC_RECOGNIZEDSPELL]) ) *matk_min = *matk_max; #ifdef RENEWAL - if( sd && sd->right_weapon.overrefine > 0 ) { - (*matk_min)++; - *matk_max += sd->right_weapon.overrefine - 1; + if ( sd && !(flag & 2) ) { + short index = sd->equip_index[EQI_HAND_R], refine; + if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_WEAPON + && (refine = sd->status.inventory[index].refine) < 16 && refine ) { + int r = (rnd() % 100) % ((status->refine_info[sd->inventory_data[index]->wlv].randombonus_max[refine + (4 - sd->inventory_data[index]->wlv)] / 100)) + 1; + st->matk_max += r / 10; + } } #endif return; } /** - * Get bl's matk value depending on flag - * @param flag [malufett] - * 1 - Get MATK w/o SC bonuses - * 2 - Get modified MATK - * 3 - Get MATK w/o eATK & SC bonuses - * @retval 1 failure - * @retval MATK success - * - * Shouldn't change _any_ value! [Panikon] - **/ -int status_get_matk( struct block_list *bl, int flag ) { +* Get bl's matk value depending on flag +* @param flag [malufett] +* 1 - Get MATK w/o SC bonuses +* 2 - Get modified MATK +* 3 - Get MATK w/o eATK & SC bonuses +* @retval 1 failure +* @retval MATK success +* +* Shouldn't change _any_ value! [Panikon] +**/ +int status_get_matk(struct block_list *bl, int flag) { struct status_data *st; unsigned short matk_max, matk_min; - if( bl == NULL ) + if ( bl == NULL ) return 1; - if( flag < 1 || flag > 3 ) { + if ( flag < 1 || flag > 3 ) { ShowError("status_get_matk: Unknown flag %d!\n", flag); return 1; } - if( (st = status->get_status_data(bl)) == NULL ) + if ( (st = status->get_status_data(bl)) == NULL ) return 0; // Just get matk - if( flag == 2 ) + if ( flag == 2 ) return status_get_rand_matk(st->matk_max, st->matk_min); - status_get_matk_sub( bl, flag, &matk_max, &matk_min ); + status_get_matk_sub(bl, flag, &matk_max, &matk_min); // Get unmodified from sc matk return status_get_rand_matk(matk_max, matk_min); } /** - * Updates bl's MATK values - **/ -void status_update_matk( struct block_list *bl ) { +* Updates bl's MATK values +**/ +void status_update_matk(struct block_list *bl) { struct status_data *st; struct status_change *sc; unsigned short matk_max, matk_min; - if( bl == NULL ) + if ( bl == NULL ) return; - if( (st = status->get_status_data(bl)) == NULL ) + if ( (st = status->get_status_data(bl)) == NULL ) return; - if( (sc = status->get_sc(bl)) == NULL ) + if ( (sc = status->get_sc(bl)) == NULL ) return; - status_get_matk_sub( bl, 0, &matk_max, &matk_min ); + status_get_matk_sub(bl, 0, &matk_max, &matk_min); // Update matk st->matk_min = status->calc_matk(bl, sc, matk_min, true); @@ -11612,6 +11630,16 @@ void status_update_matk( struct block_list *bl ) { return; } +/** + * Gets a random matk value depending on min matk and max matk + **/ +unsigned short status_get_rand_matk( unsigned short matk_max, unsigned short matk_min ) { + if( matk_max > matk_min ) + return matk_min + rnd()%(matk_max - matk_min); + else + return matk_min; +} + /*========================================== * Clears buffs/debuffs of a character. * type&1 -> buffs, type&2 -> debuffs diff --git a/src/map/status.h b/src/map/status.h index 00c243543..63f9854d5 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -1939,6 +1939,13 @@ struct status_change { #define status_get_size(bl) (status->get_status_data(bl)->size) #define status_get_mode(bl) (status->get_status_data(bl)->mode) +#define status_get_homstr(bl) (st->str + ((TBL_HOM*)bl)->homunculus.str_value) +#define status_get_homagi(bl) (st->agi + ((TBL_HOM*)bl)->homunculus.agi_value) +#define status_get_homvit(bl) (st->vit + ((TBL_HOM*)bl)->homunculus.vit_value) +#define status_get_homint(bl) (st->int_ + ((TBL_HOM*)bl)->homunculus.int_value) +#define status_get_homdex(bl) (st->dex + ((TBL_HOM*)bl)->homunculus.dex_value) +#define status_get_homluk(bl) (st->luk + ((TBL_HOM*)bl)->homunculus.luk_value) + //Short version, receives rate in 1->100 range, and does not uses a flag setting. #define sc_start(src, bl, type, rate, val1, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),0,0,0,(tick),SCFLAG_NONE)) #define sc_start2(src, bl, type, rate, val1, val2, tick) (status->change_start((src),(bl),(type),100*(rate),(val1),(val2),0,0,(tick),SCFLAG_NONE)) @@ -2062,7 +2069,7 @@ struct status_interface { defType (*calc_mdef) (struct block_list *bl, struct status_change *sc, int mdef, bool viewable); short (*calc_mdef2) (struct block_list *bl, struct status_change *sc, int mdef2, bool viewable); unsigned short (*calc_batk)(struct block_list *bl, struct status_change *sc, int batk, bool viewable); - unsigned short (*base_matk) (const struct status_data *st, int level); + unsigned short(*base_matk) (struct block_list *bl, const struct status_data *st, int level); int (*get_weapon_atk) (struct block_list *src, struct weapon_atk *watk, int flag); int (*get_total_mdef) (struct block_list *src); int (*get_total_def) (struct block_list *src); diff --git a/src/map/unit.c b/src/map/unit.c index c78919f52..243a7c28a 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -1315,31 +1315,31 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui tstatus = status->get_status_data(target); // Record the status of the previous skill) - if(sd) { + if (sd) { - if( (skill->get_inf2(skill_id)&INF2_ENSEMBLE_SKILL) && skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1 ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if ((skill->get_inf2(skill_id)&INF2_ENSEMBLE_SKILL) && skill->check_pc_partner(sd, skill_id, &skill_lv, 1, 0) < 1) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); return 0; } - switch(skill_id){ + 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; } break; case BD_ENCORE: //Prevent using the dance skill if you no longer have the skill in your tree. - if(!sd->skill_id_dance || pc->checkskill(sd,sd->skill_id_dance)<=0){ - clif->skill_fail(sd,skill_id,USESKILL_FAIL_LEVEL,0); + if (!sd->skill_id_dance || pc->checkskill(sd, sd->skill_id_dance) <= 0){ + clif->skill_fail(sd, skill_id, USESKILL_FAIL_LEVEL, 0); return 0; } sd->skill_id_old = skill_id; break; case WL_WHITEIMPRISON: - if( battle->check_target(src,target,BCT_SELF|BCT_ENEMY) < 0 ) { - clif->skill_fail(sd,skill_id,USESKILL_FAIL_TOTARGET,0); + if (battle->check_target(src, target, BCT_SELF | BCT_ENEMY) < 0) { + clif->skill_fail(sd, skill_id, USESKILL_FAIL_TOTARGET, 0); return 0; } break; @@ -1350,13 +1350,20 @@ int unit_skilluse_id2(struct block_list *src, int target_id, uint16 skill_id, ui sd->skill_lv_old = skill_lv; break; } - /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ + } + + if (sd || src->type == BL_HOM){ + if (!sd && (target = battle->get_master(src))) + sd = map->id2sd(target->id); + if (sd){ + /* temporarily disabled, awaiting for kenpachi to detail this so we can make it work properly */ #if 0 - if ( sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) + if (sd->skillitem != skill_id && !skill->check_condition_castbegin(sd, skill_id, skill_lv)) #else - if ( !skill->check_condition_castbegin(sd, skill_id, skill_lv) ) + if (!skill->check_condition_castbegin(sd, skill_id, skill_lv)) #endif - return 0; + return 0; + } } if( src->type == BL_MOB ) -- cgit v1.2.3-70-g09d2