summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--conf/battle/homunc.conf2
-rw-r--r--conf/messages.conf5
-rw-r--r--src/common/mmo.h8
-rw-r--r--src/config/const.h6
-rw-r--r--src/map/atcommand.c6
-rw-r--r--src/map/battle.c83
-rw-r--r--src/map/clif.c44
-rw-r--r--src/map/clif.h1
-rw-r--r--src/map/homunculus.c2
-rw-r--r--src/map/homunculus.h11
-rw-r--r--src/map/pc.c16
-rw-r--r--src/map/pc.h4
-rw-r--r--src/map/skill.c2
-rw-r--r--src/map/status.c928
-rw-r--r--src/map/status.h9
-rw-r--r--src/map/unit.c33
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 )