summaryrefslogtreecommitdiff
path: root/src/map/battle.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/map/battle.c')
-rw-r--r--src/map/battle.c140
1 files changed, 103 insertions, 37 deletions
diff --git a/src/map/battle.c b/src/map/battle.c
index f9472692e..c8862137f 100644
--- a/src/map/battle.c
+++ b/src/map/battle.c
@@ -497,7 +497,18 @@ int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uin
int64 damage;
struct status_data *st = status->get_status_data(src);
struct status_change *sc = status->get_sc(src);
-
+
+ if ( !skill_id ) {
+ s_ele = st->rhw.ele;
+ s_ele_ = st->lhw.ele;
+ if ( src->type == BL_PC ) {
+ if ( ((TBL_PC*)src)->charm_type != CHARM_TYPE_NONE && ((TBL_PC*)src)->charm_count >= MAX_SPIRITCHARM ) {
+ s_ele = s_ele_ = ((TBL_PC*)src)->charm_type;
+ }
+ if ( flag & 2 && ((TBL_PC*)src)->bonus.arrow_ele )
+ s_ele = ((TBL_PC*)src)->bonus.arrow_ele;
+ }
+ }
if (src->type == BL_PC) {
int64 batk;
// Property from mild wind bypasses it
@@ -1349,7 +1360,9 @@ int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_
def2 -= (target_count - (battle_config.vit_penalty_count - 1))*battle_config.vit_penalty_num;
}
}
+#ifndef RENEWAL
if(skill_id == AM_ACIDTERROR) def1 = 0; //Acid Terror ignores only armor defense. [Skotlex]
+#endif
if(def2 < 1) def2 = 1;
}
//Vitality reduction from rodatazone: http://rodatazone.simgaming.net/mechanics/substats.php#def
@@ -2001,7 +2014,11 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
skillratio += 20 * skill_lv;
break;
case AM_ACIDTERROR:
+#ifdef RENEWAL
+ skillratio += 80 * skill_lv + 100;
+#else
skillratio += 40 * skill_lv;
+#endif
break;
case MO_FINGEROFFENSIVE:
skillratio+= 50 * skill_lv;
@@ -2009,8 +2026,8 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case MO_INVESTIGATE:
skillratio += 75 * skill_lv;
break;
- #ifndef RENEWAL
case MO_EXTREMITYFIST:
+ #ifndef RENEWAL
{
//Overflow check. [Skotlex]
unsigned int ratio = skillratio + 100*(8 + st->sp/10);
@@ -2018,8 +2035,10 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
if (ratio > 60000) ratio = 60000; //We leave some room here in case skillratio gets further increased.
skillratio = (unsigned short)ratio;
}
+#else
+ skillratio += 150 * (skill_lv + 1);
+#endif
break;
- #endif
case MO_TRIPLEATTACK:
skillratio += 20 * skill_lv;
break;
@@ -2124,14 +2143,11 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block
case GS_TRACKING:
skillratio += 100 * (skill_lv+1);
break;
+#ifndef RENEWAL
case GS_PIERCINGSHOT:
-#ifdef RENEWAL
- if( sd && sd->weapontype1 == W_RIFLE )
- skillratio += 50 + 30 * skill_lv;
- else
-#endif
skillratio += 20 * skill_lv;
break;
+#endif
case GS_RAPIDSHOWER:
skillratio += 10 * skill_lv;
break;
@@ -4204,6 +4220,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
unsigned weapon : 1; ///< It's a weapon attack (consider VVS, and all that)
#ifdef RENEWAL
unsigned tdef : 1; ///< Total defense reduction
+ unsigned distinct : 1; ///< Has its own battle calc formula
#endif
} flag;
@@ -4332,12 +4349,19 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 );
break;
#ifdef RENEWAL
+ case MO_EXTREMITYFIST:
+ case GS_PIERCINGSHOT:
+ case AM_ACIDTERROR:
+ case AM_DEMONSTRATION:
+ flag.distinct = 1;
+ break;
case PA_SHIELDCHAIN:
- case NJ_KUNAI:
- case HW_MAGICCRASHER:
- case NJ_SYURIKEN:
case GS_MAGICALBULLET:
+ case NJ_SYURIKEN:
case KO_BAKURETSU:
+ flag.distinct = 1;
+ case NJ_KUNAI:
+ case HW_MAGICCRASHER:
flag.tdef = 1;
break;
#endif
@@ -4666,8 +4690,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
#define ATK_ADD( a ) do { int64 temp__ = (a); wd.damage += temp__; if (flag.lh) wd.damage2 += temp__; } while(0)
#define ATK_ADD2( a , b ) do { wd.damage += (a); if (flag.lh) wd.damage2 += (b); } while(0)
#ifdef RENEWAL
-#define GET_NORMAL_ATTACK( f ) ( wd.damage = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (f), wd.flag) )
-#define GET_NORMAL_ATTACK2( f ) ( wd.damage2 = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (f), wd.flag) )
+#define GET_NORMAL_ATTACK( f , s ) ( wd.damage = battle->calc_base_damage(src, target, s, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_R, (f), wd.flag) )
+#define GET_NORMAL_ATTACK2( f , s ) ( wd.damage2 = battle->calc_base_damage(src, target, s, skill_lv, nk, n_ele, s_ele, s_ele_, EQI_HAND_L, (f), wd.flag) )
#endif
switch (skill_id) {
//Calc base damage according to skill
@@ -4686,7 +4710,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
{
short totaldef = status->get_total_def(target);
i = 0;
- GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
+ GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0 );
if( sc && sc->data[SC_NJ_BUNSINJYUTSU] && (i=sc->data[SC_NJ_BUNSINJYUTSU]->val2) > 0 )
wd.div_ = ~( i++ + 2 ) + 1;
if( wd.damage ){
@@ -4699,18 +4723,8 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
break;
case NJ_SYURIKEN: // [malufett]
- GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
- wd.damage += battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon);
- break;
- case MO_EXTREMITYFIST: // [malufett]
- {
- short totaldef = status->get_total_def(target);
- GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|8 );
- if( wd.damage ){
- wd.damage = (250 + 150 * skill_lv) + (10 * (status_get_sp(src)+1) * wd.damage / 100) + (8 * wd.damage);
- ATK_ADD(-totaldef);
- }
- }
+ GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0);
+ ATK_ADD(battle->calc_masteryfix(src, target, skill_id, skill_lv, 4 * skill_lv + (sd ? sd->bonus.arrow_atk : 0), wd.div_, 0, flag.weapon));
#endif
break;
#ifndef RENEWAL
@@ -4786,11 +4800,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
i |= 16; // for ex. shuriken must not be influenced by DEX
}
#ifdef RENEWAL
- GET_NORMAL_ATTACK( i );
+ GET_NORMAL_ATTACK( i, skill_id);
wd.damage = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage, wd.div_, 0, flag.weapon);
wd.damage = battle->calc_cardfix2(src, target, wd.damage, s_ele, nk, wd.flag);
if (flag.lh){
- GET_NORMAL_ATTACK2( i );
+ GET_NORMAL_ATTACK2( i, skill_id );
wd.damage2 = battle->calc_masteryfix(src, target, skill_id, skill_lv, wd.damage2, wd.div_, 1, flag.weapon);
wd.damage2 = battle->calc_cardfix2(src, target, wd.damage2, s_ele, nk, wd.flag);
}
@@ -4855,7 +4869,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case KO_BAKURETSU:
{
#ifdef RENEWAL
- GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0));
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id);
#endif
skillratio = skill_lv * (50 + status_get_dex(src) / 4);
skillratio = (int)(skillratio * (sd ? pc->checkskill(sd, NJ_TOBIDOUGU) : 10) * 40.f / 100.0f * status->get_lv(src) / 120);
@@ -4864,7 +4878,33 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
break;
#ifdef RENEWAL
+ case GS_MAGICALBULLET:
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id);
+ ATK_ADD(battle->attr_fix(src, target,
+ battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, status->get_matk(src, 2), 0, wd.flag), ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv));
+ break;
+ case GS_PIERCINGSHOT:
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), 0);
+ if ( wd.damage ) {
+ if ( sd && sd->weapontype1 == W_RIFLE )
+ ATK_RATE(30 * (skill_lv + 5));
+ else
+ ATK_RATE(20 * (skill_lv + 5));
+ }
+ break;
+ case MO_EXTREMITYFIST: // [malufett]
+ {
+ short totaldef = status->get_total_def(target);
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | 8, skill_id);
+ if ( wd.damage ) {
+ ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
+ ATK_ADD((10 * (status_get_sp(src) + 1) * wd.damage / 100) + (8 * wd.damage));
+ ATK_ADD(-totaldef);
+ }
+ }
+ break;
case PA_SHIELDCHAIN:
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), skill_id);
if ( sd ) {
short index = sd->equip_index[EQI_HAND_L];
if ( index >= 0 && sd->inventory_data[index] && sd->inventory_data[index]->type == IT_ARMOR ) {
@@ -4874,6 +4914,24 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
ATK_ADD(sstatus->rhw.atk2); //Else use Atk2
ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
break;
+ case AM_DEMONSTRATION:
+ case AM_ACIDTERROR: // [malufett/Hercules]
+ {
+ int64 matk;
+ int totaldef = status->get_total_def(target) + status->get_total_mdef(target);
+ matk = battle->calc_cardfix(BF_MAGIC, src, target, nk, s_ele, 0, status->get_matk(src, 2), 0, wd.flag);
+ matk = battle->attr_fix(src, target, matk, ELE_NEUTRAL, tstatus->def_ele, tstatus->ele_lv);
+ matk = matk * battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag) / 100;
+ GET_NORMAL_ATTACK((sc && sc->data[SC_MAXIMIZEPOWER] ? 1 : 0) | (sc && sc->data[SC_WEAPONPERFECT] ? 8 : 0), 0);
+ ATK_RATE(battle->calc_skillratio(BF_WEAPON, src, target, skill_id, skill_lv, skillratio, wflag));
+ ATK_ADD(matk);
+ ATK_ADD(-totaldef);
+ if ( skill_id == AM_ACIDTERROR && is_boss(target) )
+ ATK_RATE(50);
+ if ( skill_id == AM_DEMONSTRATION )
+ wd.damage = max(wd.damage, 1);
+ }
+ break;
case NJ_TATAMIGAESHI:
ATK_RATE(200);
/* Fall through */
@@ -4881,7 +4939,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
case ML_SPIRALPIERCE: // [malufett]
if( skill_id != NJ_TATAMIGAESHI ){
short index = sd?sd->equip_index[EQI_HAND_R]:0;
- GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0) );
+ GET_NORMAL_ATTACK( (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), 0);
wd.damage = wd.damage * 70 / 100;
//n_ele = true; // FIXME: This is has no effect if it's after GET_NORMAL_ATTACK (was this intended, or was it supposed to be put above?)
@@ -4926,13 +4984,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
if(sd && sd->weapontype1 == W_FIST && sd->weapontype2 == W_FIST)
ATK_ADD(10*pc->checkskill(sd, TK_RUN));
break;
- case GS_MAGICALBULLET:
+
#ifndef RENEWAL
+ case GS_MAGICALBULLET:
ATK_ADD( status->get_matk(src, 2) );
-#else
- ATK_ADD( battle->calc_magic_attack(src, target, skill_id, skill_lv, wflag).damage );
-#endif
-#ifndef RENEWAL
+ break;
case NJ_SYURIKEN:
ATK_ADD(4*skill_lv);
#endif
@@ -5126,7 +5182,11 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
}
- if(!flag.idef || !flag.idef2) { //Defense reduction
+ if((!flag.idef || !flag.idef2)
+#ifdef RENEWAL
+ && (!flag.distinct || flag.tdef)
+#endif
+ ) { //Defense reduction
wd.damage = battle->calc_defense(BF_WEAPON, src, target, skill_id, skill_lv, wd.damage,
(flag.idef?1:0)|(flag.pdef?2:0)
#ifdef RENEWAL
@@ -5143,9 +5203,15 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list
}
#ifdef RENEWAL
+ if ( flag.distinct ) {
+ wd.damage = battle->calc_cardfix2(src, target, wd.damage, s_ele, nk, wd.flag);
+ if ( flag.lh ) {
+ wd.damage2 = battle->calc_cardfix2(src, target, wd.damage2, s_ele, nk, wd.flag);
+ }
+ }
//Div fix.
damage_div_fix(wd.damage, wd.div_);
- if ( skill_id > 0 && skill->get_ele(skill_id, skill_lv) == ELE_NEUTRAL ) { // re-evaluate forced neutral skills
+ if ( skill_id > 0 && (skill->get_ele(skill_id, skill_lv) == ELE_NEUTRAL || flag.distinct) ) { // re-evaluate forced neutral skills
wd.damage = battle->attr_fix(src, target, wd.damage, s_ele_, tstatus->def_ele, tstatus->ele_lv);
if ( flag.lh )
wd.damage2 = battle->attr_fix(src, target, wd.damage2, s_ele_, tstatus->def_ele, tstatus->ele_lv);