diff options
Diffstat (limited to 'src/map/battle.c')
-rw-r--r-- | src/map/battle.c | 413 |
1 files changed, 226 insertions, 187 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index a511650a2..1cbc3baa5 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -4,50 +4,52 @@ #define HERCULES_CORE -#include "../config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT +#include "config/core.h" // CELL_NOSTACK, CIRCULAR_AREA, CONSOLE_INPUT, HMAP_ZONE_DAMAGE_CAP_TYPE, OFFICIAL_WALKPATH, RENEWAL, RENEWAL_ASPD, RENEWAL_CAST, RENEWAL_DROP, RENEWAL_EDP, RENEWAL_EXP, RENEWAL_LVDMG, RE_LVL_DMOD(), RE_LVL_MDMOD(), RE_LVL_TMDMOD(), RE_SKILL_REDUCTION(), SCRIPT_CALLFUNC_CHECK, SECURE_NPCTIMEOUT, STATS_OPT_OUT #include "battle.h" +#include "map/battleground.h" +#include "map/chrif.h" +#include "map/clif.h" +#include "map/elemental.h" +#include "map/guild.h" +#include "map/homunculus.h" +#include "map/itemdb.h" +#include "map/map.h" +#include "map/mercenary.h" +#include "map/mob.h" +#include "map/party.h" +#include "map/path.h" +#include "map/pc.h" +#include "map/pet.h" +#include "map/skill.h" +#include "map/status.h" +#include "common/HPM.h" +#include "common/cbasetypes.h" +#include "common/ers.h" +#include "common/memmgr.h" +#include "common/nullpo.h" +#include "common/random.h" +#include "common/showmsg.h" +#include "common/socket.h" +#include "common/strlib.h" +#include "common/sysinfo.h" +#include "common/timer.h" +#include "common/utils.h" + #include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include "battleground.h" -#include "chrif.h" -#include "clif.h" -#include "elemental.h" -#include "guild.h" -#include "homunculus.h" -#include "itemdb.h" -#include "map.h" -#include "mercenary.h" -#include "mob.h" -#include "party.h" -#include "path.h" -#include "pc.h" -#include "pet.h" -#include "skill.h" -#include "status.h" -#include "../common/HPM.h" -#include "../common/cbasetypes.h" -#include "../common/ers.h" -#include "../common/malloc.h" -#include "../common/nullpo.h" -#include "../common/random.h" -#include "../common/showmsg.h" -#include "../common/socket.h" -#include "../common/strlib.h" -#include "../common/sysinfo.h" -#include "../common/timer.h" -#include "../common/utils.h" - struct Battle_Config battle_config; struct battle_interface battle_s; +struct battle_interface *battle; int battle_getcurrentskill(struct block_list *bl) { //Returns the current/last skill in use by this bl. struct unit_data *ud; - if( bl->type == BL_SKILL ) { + nullpo_ret(bl); + if (bl->type == BL_SKILL) { struct skill_unit * su = (struct skill_unit*)bl; return su->group?su->group->skill_id:0; } @@ -66,6 +68,7 @@ int battle_gettargeted_sub(struct block_list *bl, va_list ap) { int target_id; int *c; + nullpo_ret(bl); bl_list = va_arg(ap, struct block_list **); c = va_arg(ap, int *); target_id = va_arg(ap, int); @@ -76,7 +79,7 @@ int battle_gettargeted_sub(struct block_list *bl, va_list ap) { if (*c >= 24) return 0; - if ( !(ud = unit->bl2ud(bl)) ) + if (!(ud = unit->bl2ud(bl))) return 0; if (ud->target == target_id || ud->skilltarget == target_id) { @@ -101,10 +104,10 @@ struct block_list* battle_gettargeted(struct block_list *target) { return bl_list[rnd()%c]; } - //Returns the id of the current targeted character of the passed bl. [Skotlex] int battle_gettarget(struct block_list* bl) { + nullpo_ret(bl); switch (bl->type) { case BL_PC: return ((struct map_session_data*)bl)->ud.target; case BL_MOB: return ((struct mob_data*)bl)->target_id; @@ -122,6 +125,7 @@ int battle_getenemy_sub(struct block_list *bl, va_list ap) { struct block_list *target; int *c; + nullpo_ret(bl); bl_list = va_arg(ap, struct block_list **); c = va_arg(ap, int *); target = va_arg(ap, struct block_list *); @@ -148,6 +152,7 @@ struct block_list* battle_getenemy(struct block_list *target, int type, int rang struct block_list *bl_list[24]; int c = 0; + nullpo_retr(NULL, target); memset(bl_list, 0, sizeof(bl_list)); map->foreachinrange(battle->get_enemy_sub, target, range, type, bl_list, &c, target); @@ -163,8 +168,11 @@ int battle_getenemyarea_sub(struct block_list *bl, va_list ap) { struct block_list **bl_list, *src; int *c, ignore_id; + nullpo_ret(bl); bl_list = va_arg(ap, struct block_list **); + nullpo_ret(bl_list); c = va_arg(ap, int *); + nullpo_ret(c); src = va_arg(ap, struct block_list *); ignore_id = va_arg(ap, int); @@ -190,6 +198,7 @@ struct block_list* battle_getenemyarea(struct block_list *src, int x, int y, int struct block_list *bl_list[24]; int c = 0; + nullpo_retr(NULL, src); memset(bl_list, 0, sizeof(bl_list)); map->foreachinarea(battle->get_enemy_area_sub, src->m, x - range, y - range, x + range, y + range, type, bl_list, &c, src, ignore_id); @@ -209,7 +218,7 @@ int battle_delay_damage_sub(int tid, int64 tick, int id, intptr_t data) { struct block_list* target = map->id2bl(dat->target_id); if( !target || status->isdead(target) ) {/* nothing we can do */ - if( dat->src_type == BL_PC && ( src = map->id2bl(dat->src_id) ) && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) { + if( dat->src_type == BL_PC && (src = map->id2bl(dat->src_id)) != NULL && --((TBL_PC*)src)->delayed_damage == 0 && ((TBL_PC*)src)->state.hold_recalc ) { ((TBL_PC*)src)->state.hold_recalc = 0; status_calc_pc(((TBL_PC*)src),SCO_FORCE); } @@ -263,7 +272,7 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct if (d_tbl && sc && check_distance_bl(target, d_tbl, sc->data[SC_DEVOTION]->val3) && damage > 0 && skill_id != PA_PRESSURE && skill_id != CR_REFLECTSHIELD) damage = 0; - + if ( !battle_config.delay_battle_damage || amotion <= 1 ) { map->freeblock_lock(); status_fix_damage(src, target, damage, ddelay); // We have to separate here between reflect damage and others [icescope] @@ -299,11 +308,10 @@ int battle_delay_damage(int64 tick, int amotion, struct block_list *src, struct } int battle_attr_ratio(int atk_elem,int def_type, int def_lv) { - - if (atk_elem < 0 || atk_elem >= ELE_MAX) + if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX) return 100; - if (def_type < 0 || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) + if (def_type < ELE_NEUTRAL || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) return 100; return battle->attr_fix_table[def_lv-1][atk_elem][def_type]; @@ -322,10 +330,10 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d if (src) sc = status->get_sc(src); if (target) tsc = status->get_sc(target); - if (atk_elem < 0 || atk_elem >= ELE_MAX) + if (atk_elem < ELE_NEUTRAL || atk_elem >= ELE_MAX) atk_elem = rnd()%ELE_MAX; - if (def_type < 0 || def_type >= ELE_MAX || + if (def_type < ELE_NEUTRAL || def_type >= ELE_MAX || def_lv < 1 || def_lv > 4) { ShowError("battle_attr_fix: unknown attr type: atk=%d def_type=%d def_lv=%d\n",atk_elem,def_type,def_lv); return damage; @@ -407,6 +415,8 @@ int64 battle_attr_fix(struct block_list *src, struct block_list *target, int64 d else return damage + (damage * (ratio - 100) / 100); } + +//FIXME: Missing documentation for flag, flag2 int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, struct weapon_atk *watk, int nk, bool n_ele, short s_ele, short s_ele_, int size, int type, int flag, int flag2){ // [malufett] #ifdef RENEWAL int64 damage, eatk = 0; @@ -449,7 +459,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u if( sc->data[SC_ZENKAI] && watk->ele == sc->data[SC_ZENKAI]->val2 ) eatk += 200; } - + #ifdef RENEWAL_EDP if ( sc && sc->data[SC_EDP] && skill_id != AS_GRIMTOOTH && skill_id != AS_VENOMKNIFE && skill_id != ASC_BREAKER ) { struct status_data *tstatus; @@ -459,9 +469,8 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u } else /* fall through */ #endif damage += eatk; - damage = battle->calc_elefix(src, bl, skill_id, skill_lv, damage, nk, n_ele, s_ele, s_ele_, type == EQI_HAND_L, flag); - + /** * In RE Shield Boomerang takes weapon element only for damage calculation, * - resist calculation is always against neutral @@ -485,7 +494,7 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u * it calculates nothing extra fancy, is needed for magnum breaks WATK_ELEMENT bonus. [Skotlex] *------------------------------------------ * Pass damage2 as NULL to not calc it. - * Flag values: + * Flag values: // TODO: Check whether these values are correct (the flag parameter seems to be passed through to other functions), and replace them with an enum. * &1: Critical hit * &2: Arrow attack * &4: Skill is Magic Crasher @@ -493,11 +502,13 @@ int64 battle_calc_weapon_damage(struct block_list *src, struct block_list *bl, u *&16: Arrow attack but BOW, REVOLVER, RIFLE, SHOTGUN, GATLING or GRENADE type weapon not equipped (i.e. shuriken, kunai and venom knives not affected by DEX) */ /* 'battle_calc_base_damage' is used on renewal, 'battle_calc_base_damage2' otherwise. */ +// FIXME: Missing documentation for flag2 int64 battle_calc_base_damage(struct block_list *src, struct block_list *bl, uint16 skill_id, uint16 skill_lv, int nk, bool n_ele, short s_ele, short s_ele_, int type, int flag, int flag2) { int64 damage; struct status_data *st = status->get_status_data(src); struct status_change *sc = status->get_sc(src); - + + nullpo_retr(0, src); if ( !skill_id ) { s_ele = st->rhw.ele; s_ele_ = st->lhw.ele; @@ -532,6 +543,8 @@ int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, st short type = 0; int64 damage = 0; + nullpo_retr(damage, st); + nullpo_retr(damage, wa); if (!sd) { //Mobs/Pets if(flag&4) { atkmin = st->matk_min; @@ -608,6 +621,7 @@ int64 battle_calc_base_damage2(struct status_data *st, struct weapon_atk *wa, st int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, int size, bool ignore){ //SizeFix only for players + nullpo_retr(damage, sd); if (!(sd->special_state.no_sizefix || (ignore))) damage = damage * ( type == EQI_HAND_L ? sd->left_weapon.atkmods[size] : sd->right_weapon.atkmods[size] ) / 100; return damage; @@ -616,14 +630,15 @@ int64 battle_calc_sizefix(struct map_session_data *sd, int64 damage, int type, i /*========================================== * Passive skill damages increases *------------------------------------------*/ +// FIXME: type is undocumented int64 battle_addmastery(struct map_session_data *sd,struct block_list *target,int64 dmg,int type) { int64 damage; struct status_data *st = status->get_status_data(target); int weapon, skill_lv; damage = dmg; - nullpo_ret(sd); - + nullpo_retr(damage, sd); + nullpo_retr(damage, target); if((skill_lv = pc->checkskill(sd,AL_DEMONBANE)) > 0 && target->type == BL_MOB && //This bonus doesn't work against players. (battle->check_undead(st->race,st->def_ele) || st->race==RC_DEMON) ) @@ -843,7 +858,7 @@ int64 battle_calc_masteryfix(struct block_list *src, struct block_list *target, i = 2; //Star anger else ARR_FIND(0, MAX_PC_FEELHATE, i, status->get_class(target) == sd->hate_mob[i]); - if ( i < MAX_PC_FEELHATE && (skill2_lv=pc->checkskill(sd,pc->sg_info[i].anger_id)) && weapon ) { + if (i < MAX_PC_FEELHATE && (skill2_lv=pc->checkskill(sd,pc->sg_info[i].anger_id)) > 0 && weapon) { int ratio = sd->status.base_level + status_get_dex(src) + status_get_luk(src); if ( i == 2 ) ratio += status_get_str(src); //Star Anger if (skill2_lv < 4 ) @@ -866,6 +881,7 @@ void battle_calc_masteryfix_unknown(struct block_list *src, struct block_list *t /*========================================== * Elemental attribute fix. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_elefix(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int nk, int n_ele, int s_ele, int s_ele_, bool left, int flag){ struct status_data *tstatus; @@ -930,8 +946,6 @@ int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 // RaceAddTolerance damage -= damage * tsd->race_tolerance[sstatus->race] / 100; damage -= damage * tsd->race_tolerance[is_boss(src) ? RC_BOSS : RC_NONBOSS] / 100; - if ( sstatus->race != RC_DEMIHUMAN ) - damage -= damage *tsd->race_tolerance[RC_NONDEMIHUMAN] / 100; if ( flag&BF_SHORT ) damage -= damage * tsd->bonus.near_attack_def_rate / 100; else // SubRangeAttackDamage or bLongAtkDef @@ -950,13 +964,13 @@ int64 battle_calc_cardfix2(struct block_list *src, struct block_list *bl, int64 * &1 - calc for left hand. * &2 - atker side cardfix(BF_WEAPON) otherwise target side(BF_WEAPON). *------------------------------------------*/ +// FIXME: wflag is undocumented int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_list *target, int nk, int s_ele, int s_ele_, int64 damage, int cflag, int wflag){ struct map_session_data *sd, *tsd; - short cardfix = #ifdef RENEWAL - 100; + short cardfix = 100; #else - 1000; + short cardfix = 1000; #endif short t_class, s_class, s_race2, t_race2; struct status_data *sstatus, *tstatus; @@ -1013,8 +1027,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100 - tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100 - tsd->subrace[sstatus->race]) / 100; cardfix = cardfix * (100 - tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100-tsd->subrace[RC_NONDEMIHUMAN]) / 100; for(i=0; i < ARRAYLENGTH(tsd->add_mdef) && tsd->add_mdef[i].rate;i++) { if(tsd->add_mdef[i].class_ == s_class) { @@ -1070,8 +1082,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size]+sd->arrow_addsize[tstatus->size]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2]) / 100; cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->arrow_addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100 + sd->right_weapon.addrace[RC_NONDEMIHUMAN]+sd->arrow_addrace[RC_NONDEMIHUMAN]) / 100; }else{ // Melee attack if( !battle_config.left_cardfix_to_right ){ cardfix=cardfix*(100+sd->right_weapon.addrace[tstatus->race])/100; @@ -1090,8 +1100,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100+sd->right_weapon.addsize[tstatus->size]) / 100; cardfix = cardfix * (100+sd->right_weapon.addrace2[t_race2]) / 100; cardfix = cardfix * (100+sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100 + sd->right_weapon.addrace[RC_NONDEMIHUMAN]) / 100; if( cflag&1 ){ cardfix_ = cardfix_*(100+sd->left_weapon.addrace[tstatus->race])/100; @@ -1110,8 +1118,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix_ = cardfix_ * (100+sd->left_weapon.addsize[tstatus->size]) / 100; cardfix_ = cardfix_ * (100+sd->left_weapon.addrace2[t_race2]) / 100; cardfix_ = cardfix_ * (100+sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix_ = cardfix_*(100+sd->left_weapon.addrace[RC_NONDEMIHUMAN])/100; } }else{ int ele_fix = sd->right_weapon.addele[tstatus->def_ele] + sd->left_weapon.addele[tstatus->def_ele]; @@ -1137,8 +1143,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100 + sd->right_weapon.addsize[tstatus->size] + sd->left_weapon.addsize[tstatus->size])/100; cardfix = cardfix * (100 + sd->right_weapon.addrace2[t_race2] + sd->left_weapon.addrace2[t_race2])/100; cardfix = cardfix * (100 + sd->right_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS] + sd->left_weapon.addrace[is_boss(target)?RC_BOSS:RC_NONBOSS]) / 100; - if( tstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100+sd->right_weapon.addrace[RC_NONDEMIHUMAN] + sd->left_weapon.addrace[RC_NONDEMIHUMAN]) / 100; } } @@ -1203,8 +1207,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ cardfix = cardfix * (100-tsd->subrace2[s_race2]) / 100; cardfix = cardfix * (100-tsd->subrace[sstatus->race]) / 100; cardfix = cardfix * (100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100 - tsd->subrace[RC_NONDEMIHUMAN]) / 100; for( i = 0; i < ARRAYLENGTH(tsd->add_def) && tsd->add_def[i].rate;i++ ){ if( tsd->add_def[i].class_ == s_class ) @@ -1251,8 +1253,6 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ } cardfix = cardfix*(100-tsd->subrace[sstatus->race]) / 100; cardfix = cardfix*(100-tsd->subrace[is_boss(src)?RC_BOSS:RC_NONBOSS]) / 100; - if( sstatus->race != RC_DEMIHUMAN ) - cardfix = cardfix * (100 - tsd->subrace[RC_NONDEMIHUMAN]) / 100; if( wflag&BF_SHORT ) cardfix = cardfix * ( 100 - tsd->bonus.near_attack_def_rate ) / 100; else // BF_LONG (there's no other choice) @@ -1282,6 +1282,7 @@ int64 battle_calc_cardfix(int attack_type, struct block_list *src, struct block_ * &2 - pdef(Pierce defense) * &4 - tdef(Total defense reduction) *------------------------------------------*/ +// TODO: Add an enum for flag int64 battle_calc_defense(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int64 damage, int flag, int pdef){ struct status_data *sstatus, *tstatus; struct map_session_data *sd, *tsd; @@ -1485,6 +1486,7 @@ int battle_calc_chorusbonus(struct map_session_data *sd) { return members - 2; // Effect bonus from additional Minstrel's/Wanderer's if not above the max possible } +// FIXME: flag is undocumented int battle_calc_skillratio(int attack_type, struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv, int skillratio, int flag){ int i; struct status_change *sc, *tsc; @@ -2695,9 +2697,12 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam struct map_session_data *sd = NULL; struct status_change *sc, *tsc; struct status_change_entry *sce; - int div_ = d->div_, flag = d->flag; + int div_, flag; nullpo_ret(bl); + nullpo_ret(d); + div_ = d->div_; + flag = d->flag; // need check src for null pointer? @@ -2788,6 +2793,8 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam group->val2 -= (int)cap_value(damage,INT_MIN,INT_MAX); } else skill->del_unitgroup(group,ALC_MARK); + if (--group->val3<=0) + skill->del_unitgroup(group,ALC_MARK); #else if (--group->val2<=0) skill->del_unitgroup(group,ALC_MARK); @@ -2807,7 +2814,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam } if( sc->data[SC__MAELSTROM] && (flag&BF_MAGIC) && skill_id && (skill->get_inf(skill_id)&INF_GROUND_SKILL) ) { // {(Maelstrom Skill LevelxAbsorbed Skill Level)+(Caster's Job/5)}/2 - int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + sd->status.job_level / 5) / 2; + int sp = (sc->data[SC__MAELSTROM]->val1 * skill_lv + (sd ? sd->status.job_level / 5 : 0)) / 2; status->heal(bl, 0, sp, 3); d->dmg_lv = ATK_BLOCK; return 0; @@ -2874,7 +2881,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam return 0; } - if( (sce=sc->data[SC_PARRYING]) && flag&BF_WEAPON && skill_id != WS_CARTTERMINATION && rnd()%100 < sce->val2 ) { // attack blocked by Parrying clif->skill_nodamage(bl, bl, LK_PARRYING, sce->val1,1); @@ -2907,7 +2913,7 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam return 0; } - if( flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) && rnd()%100 < sce->val2) { + if (flag&BF_MAGIC && (sce=sc->data[SC_PRESTIGE]) != NULL && rnd()%100 < sce->val2) { clif->specialeffect(bl, 462, AREA); // Still need confirm it. return 0; } @@ -3131,7 +3137,6 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC_MEIKYOUSISUI] && rnd()%100 < 40 ) // custom value damage = 0; - if (!damage) return 0; if( (sce = sc->data[SC_LIGHTNINGWALK]) && flag&BF_LONG && rnd()%100 < sce->val1 ) { @@ -3164,28 +3169,31 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(bl, src); // Deadly infect attacked side + + if (sd && damage > 0 && (sce = sc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { + if ( rnd() % 100 < sce->val2 ) + pc->addspiritball(sd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(sd, 0)); + } } //SC effects from caster side. - sc = status->get_sc(src); - - if (sc && sc->count) { - if( sc->data[SC_INVINCIBLE] && !sc->data[SC_INVINCIBLEOFF] ) + if (tsc && tsc->count) { + if( tsc->data[SC_INVINCIBLE] && !tsc->data[SC_INVINCIBLEOFF] ) damage += damage * 75 / 100; // [Epoque] if (bl->type == BL_MOB) { int i; - if ( ((sce=sc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) + if ( ((sce=tsc->data[SC_MANU_ATK]) && (flag&BF_WEAPON)) || + ((sce=tsc->data[SC_MANU_MATK]) && (flag&BF_MAGIC)) ) for (i=0;ARRAYLENGTH(mob->manuk)>i;i++) if (((TBL_MOB*)bl)->class_==mob->manuk[i]) { damage += damage * sce->val1 / 100; break; } - if ( ((sce=sc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || - ((sce=sc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) + if ( ((sce=tsc->data[SC_SPL_ATK]) && (flag&BF_WEAPON)) || + ((sce=tsc->data[SC_SPL_MATK]) && (flag&BF_MAGIC)) ) for (i=0;ARRAYLENGTH(mob->splendide)>i;i++) if (((TBL_MOB*)bl)->class_==mob->splendide[i]) { @@ -3202,14 +3210,19 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam sc_start(src,bl,tsc->data[SC_POISONINGWEAPON]->val2,rate,tsc->data[SC_POISONINGWEAPON]->val1,skill->get_time2(GC_POISONINGWEAPON,1) - (tstatus->vit + tstatus->luk) / 2 * 1000); } } - if( sc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * sc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) + if( tsc->data[SC__DEADLYINFECT] && flag&BF_SHORT && damage > 0 && rnd()%100 < 30 + 10 * tsc->data[SC__DEADLYINFECT]->val1 && !is_boss(src) ) status->change_spread(src, bl); - if (sc->data[SC_SHIELDSPELL_REF] && sc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) + if (tsc->data[SC_SHIELDSPELL_REF] && tsc->data[SC_SHIELDSPELL_REF]->val1 == 1 && damage > 0) skill->break_equip(bl,EQP_ARMOR,10000,BCT_ENEMY ); - if (sc->data[SC_STYLE_CHANGE] && rnd()%2) { + if (tsc->data[SC_STYLE_CHANGE] && rnd()%2) { TBL_HOM *hd = BL_CAST(BL_HOM,bl); if (hd) homun->addspiritball(hd, 10); } + if (src->type == BL_PC && damage > 0 && (sce = tsc->data[SC_GENTLETOUCH_ENERGYGAIN]) != NULL) { + struct map_session_data *tsd = (struct map_session_data *)src; + if ( tsd && rnd() % 100 < sce->val2 ) + pc->addspiritball(tsd, skill->get_time(MO_CALLSPIRITS, 1), pc->getmaxspiritball(tsd, 0)); + } } /* no data claims these settings affect anything other than players */ if( damage && sd && bl->type == BL_PC ) { @@ -3253,24 +3266,27 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam if (skill_id) mob->skill_event((TBL_MOB*)bl,src,timer->gettick(),MSC_SKILLUSED|(skill_id<<16)); } - if( sd ) { - if( pc_ismadogear(sd) && rnd()%100 < 50 ) { - short element = skill->get_ele(skill_id, skill_lv); - if( !skill_id || element == -1 ) { //Take weapon's element - struct status_data *sstatus = NULL; - if( src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele ) - element = ((TBL_PC*)src)->bonus.arrow_ele; - else if( (sstatus = status->get_status_data(src)) ) { - element = sstatus->rhw.ele; - } + if (sd && pc_ismadogear(sd) && rnd()%100 < 50) { + int element = -1; + if (!skill_id || (element = skill->get_ele(skill_id, skill_lv)) == -1) { + // Take weapon's element + struct status_data *sstatus = NULL; + if (src->type == BL_PC && ((TBL_PC*)src)->bonus.arrow_ele) { + element = ((TBL_PC*)src)->bonus.arrow_ele; + } else if ((sstatus = status->get_status_data(src)) != NULL) { + element = sstatus->rhw.ele; } - else if( element == -2 ) //Use enchantment's element - element = status_get_attack_sc_element(src,status->get_sc(src)); - else if( element == -3 ) //Use random element - element = rnd()%ELE_MAX; - if( element == ELE_FIRE || element == ELE_WATER ) - pc->overheat(sd,element == ELE_FIRE ? 1 : -1); - } + } else if (element == -2) { + // Use enchantment's element + element = status_get_attack_sc_element(src,status->get_sc(src)); + } else if (element == -3) { + // Use random element + element = rnd()%ELE_MAX; + } + if (element == ELE_FIRE) + pc->overheat(sd, 1); + else if (element == ELE_WATER) + pc->overheat(sd, -1); } return damage; @@ -3279,11 +3295,13 @@ int64 battle_calc_damage(struct block_list *src,struct block_list *bl,struct Dam /*========================================== * Calculates BG related damage adjustments. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 damage, int div_, uint16 skill_id, uint16 skill_lv, int flag) { if( !damage ) return 0; + nullpo_retr(damage, bl); if( bl->type == BL_MOB ) { struct mob_data* md = BL_CAST(BL_MOB, bl); @@ -3297,12 +3315,15 @@ int64 battle_calc_bg_damage(struct block_list *src, struct block_list *bl, int64 /*========================================== * Calculates GVG related damage adjustments. *------------------------------------------*/ +// FIXME: flag is undocumented int64 battle_calc_gvg_damage(struct block_list *src,struct block_list *bl,int64 damage,int div_,uint16 skill_id,uint16 skill_lv,int flag) { struct mob_data* md = BL_CAST(BL_MOB, bl); int class_ = status->get_class(bl); if (!damage) //No reductions to make. return 0; + nullpo_retr(damage, src); + nullpo_retr(damage, bl); if(md && md->guardian_data) { if(class_ == MOBID_EMPERIUM && flag&BF_SKILL) { @@ -3370,21 +3391,27 @@ int battle_calc_drain(int64 damage, int rate, int per) { *------------------------------------------*/ void battle_consume_ammo(TBL_PC*sd, int skill_id, int lv) { int qty=1; + + nullpo_retv(sd); if (!battle_config.arrow_decrement) return; - if (skill_id) { + if (skill_id && lv) { qty = skill->get_ammo_qty(skill_id, lv); if (!qty) qty = 1; } if(sd->equip_index[EQI_AMMO]>=0) //Qty check should have been done in skill_check_condition - pc->delitem(sd,sd->equip_index[EQI_AMMO],qty,0,1,LOG_TYPE_CONSUME); + pc->delitem(sd, sd->equip_index[EQI_AMMO], qty, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); sd->state.arrow_atk = 0; } + //Skill Range Criteria int battle_range_type(struct block_list *src, struct block_list *target, uint16 skill_id, uint16 skill_lv) { + nullpo_retr(BF_SHORT, src); + nullpo_retr(BF_SHORT, target); + if (battle_config.skillrange_by_distance && (src->type&battle_config.skillrange_by_distance) ) { //based on distance between src/target [Skotlex] @@ -3417,8 +3444,10 @@ int battle_adjust_skill_damage(int m, unsigned short skill_id) { return 0; } + int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { int i; + nullpo_ret(sd); if (!sd->skillblown[0].id) return 0; //Apply the bonus blow count. [Skotlex] @@ -3433,6 +3462,7 @@ int battle_blewcount_bonus(struct map_session_data *sd, uint16 skill_id) { /*========================================== * battle_calc_magic_attack [DracoRPG] *------------------------------------------*/ +// FIXME: mflag is undocumented struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int nk; short s_ele = 0; @@ -3611,7 +3641,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list skillratio = sc->data[SC_SPELLFIST]->val2 * 50 + sc->data[SC_SPELLFIST]->val4 * 100;// val4 = used bolt level, val2 = used spellfist level. [Rytech] ad.div_ = 1;// ad mods, to make it work similar to regular hits [Xazax] ad.flag = BF_WEAPON|BF_SHORT; - ad.type = 0; + ad.type = BDT_NORMAL; } /* Fall through */ default: @@ -3627,7 +3657,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list } } #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -3759,6 +3789,7 @@ struct Damage battle_calc_magic_attack(struct block_list *src,struct block_list /*========================================== * Calculate Misc damage for skill_id *------------------------------------------*/ +// FIXME: mflag is undocumented struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int mflag) { int temp; short i, nk; @@ -3877,7 +3908,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * short tdef = status->get_total_def(target); short tmdef = status->get_total_mdef(target); int targetVit = min(120, status_get_vit(target)); - short totaldef = (tmdef + tdef - ((uint64)(tmdef + tdef) >> 32)) >> 1; + short totaldef = (tmdef + tdef - ((uint64)(tmdef + tdef) >> 32)) >> 1; // FIXME: What's the >> 32 supposed to do here? tmdef and tdef are both 16-bit... matk = battle->calc_magic_attack(src, target, skill_id, skill_lv, mflag).damage; atk = battle->calc_base_damage(src, target, skill_id, skill_lv, nk, false, s_ele, ELE_NEUTRAL, EQI_HAND_R, (sc && sc->data[SC_MAXIMIZEPOWER]?1:0)|(sc && sc->data[SC_WEAPONPERFECT]?8:0), md.flag); @@ -3984,7 +4015,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * case RA_CLUSTERBOMB: case RA_FIRINGTRAP: case RA_ICEBOUNDTRAP: - md.damage = skill_lv * sstatus->dex + sstatus->int_ * 5 ; + md.damage = (int64)skill_lv * sstatus->dex + sstatus->int_ * 5 ; RE_LVL_TMDMOD(); if(sd) { @@ -3998,7 +4029,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * break; case WM_SOUND_OF_DESTRUCTION: - md.damage = 1000 * skill_lv + sstatus->int_ * (sd ? pc->checkskill(sd,WM_LESSON) : 10); + md.damage = 1000 * (int64)skill_lv + sstatus->int_ * (sd ? pc->checkskill(sd,WM_LESSON) : 10); md.damage += md.damage * 10 * battle->calc_chorusbonus(sd) / 100; break; /** @@ -4100,7 +4131,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * } } #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -4129,7 +4160,7 @@ struct Damage battle_calc_misc_attack(struct block_list *src,struct block_list * default: rskill = skill_id; } - if (sd && (i = pc->skillatk_bonus(sd, rskill))) + if (sd && (i = pc->skillatk_bonus(sd, rskill)) != 0) md.damage += md.damage*i/100; } if( (i = battle->adjust_skill_damage(src->m,skill_id)) ) @@ -4190,6 +4221,7 @@ void battle_calc_misc_attack_unknown(struct block_list *src, struct block_list * /*========================================== * battle_calc_weapon_attack (by Skotlex) *------------------------------------------*/ +// FIXME: wflag is undocumented struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list *target,uint16 skill_id,uint16 skill_lv,int wflag) { unsigned int skillratio = 100; //Skill dmg modifiers. @@ -4240,7 +4272,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list flag.infdef = 1; // Reverberation takes 1 damage //Initial Values - wd.type=0; //Normal attack + wd.type = BDT_NORMAL; wd.div_ = skill_id ? skill->get_num(skill_id,skill_lv) : 1; wd.amotion=(skill_id && skill->get_inf(skill_id)&INF_GROUND_SKILL)?0:sstatus->amotion; //Amotion should be 0 for ground skills. if(skill_id == KN_AUTOCOUNTER) @@ -4307,7 +4339,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case TF_DOUBLE: //For NPC used skill. case GS_CHAINACTION: - wd.type = 0x08; + wd.type = BDT_MULTIHIT; break; case GS_GROUNDDRIFT: @@ -4346,6 +4378,10 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if( tsc && (tsc->data[SC_WUGBITE] || tsc->data[SC_ANKLESNARE] || tsc->data[SC_ELECTRICSHOCKER]) ) wd.div_ = tstatus->size + 2 + ( (rnd()%100 < 50-tstatus->size*10) ? 1 : 0 ); break; + + case NPC_EARTHQUAKE: + wd.flag = (wd.flag&~(BF_WEAPON)) | BF_MAGIC; + break; #ifdef RENEWAL case MO_EXTREMITYFIST: case GS_PIERCINGSHOT: @@ -4361,6 +4397,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case NJ_SYURIKEN: case KO_BAKURETSU: flag.distinct = 1; + /* Fall through */ case NJ_KUNAI: case HW_MAGICCRASHER: flag.tdef = 1; @@ -4371,7 +4408,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list wd.flag |= flag.arrow?BF_LONG:BF_SHORT; if ((!skill_id || skill_id == PA_SACRIFICE) && tstatus->flee2 && rnd()%1000 < tstatus->flee2) { //Check for Lucky Dodge - wd.type=0x0b; + wd.type = BDT_PDODGE; wd.dmg_lv=ATK_LUCKY; if (wd.div_ < 0) wd.div_*=-1; return wd; @@ -4439,13 +4476,13 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if( rnd()%100 < ( 5*skill_lv > sd->bonus.double_rate ? 5*skill_lv : sc && sc->data[SC_KAGEMUSYA]?sc->data[SC_KAGEMUSYA]->val1*3:sd->bonus.double_rate ) ) { wd.div_ = skill->get_num(TF_DOUBLE,skill_lv?skill_lv:1); - wd.type = 0x08; + wd.type = BDT_MULTIHIT; } } else if( sd->weapontype1 == W_REVOLVER && (skill_lv = pc->checkskill(sd,GS_CHAINACTION)) > 0 && rnd()%100 < 5*skill_lv ) { wd.div_ = skill->get_num(GS_CHAINACTION,skill_lv); - wd.type = 0x08; + wd.type = BDT_MULTIHIT; } else if(sc && sc->data[SC_FEARBREEZE] && sd->weapontype1==W_BOW && (i = sd->equip_index[EQI_AMMO]) >= 0 && sd->inventory_data[i] && sd->status.inventory[i].amount > 1){ @@ -4476,26 +4513,32 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if ( wd.div_ > 1 ) { wd.div_ = min(wd.div_, sd->status.inventory[i].amount); sc->data[SC_FEARBREEZE]->val4 = wd.div_ - 1; - wd.type = 0x08; + wd.type = BDT_MULTIHIT; } } } //Check for critical - if( !flag.cri && !(wd.type&0x08) && sstatus->cri && + if( !flag.cri && wd.type != BDT_MULTIHIT && sstatus->cri && (!skill_id || skill_id == KN_AUTOCOUNTER || skill_id == SN_SHARPSHOOTING || skill_id == MA_SHARPSHOOTING || skill_id == NJ_KIRIKAGE)) { short cri = sstatus->cri; - if (sd) - { + if (sd) { + // Check for katar here as katar crit bonus should not be displayed + if (sd->status.weapon == W_KATAR) { + cri <<= 1; + } + cri+= sd->critaddrace[tstatus->race]; - if(flag.arrow) + + if (flag.arrow) { cri += sd->bonus.arrow_cri; + } } - if( sc && sc->data[SC_CAMOUFLAGE] ) + if (sc && sc->data[SC_CAMOUFLAGE]) cri += 10 * (10-sc->data[SC_CAMOUFLAGE]->val4); #ifndef RENEWAL //The official equation is *2, but that only applies when sd's do critical. @@ -4534,7 +4577,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list flag.cri = 1; } if (flag.cri) { - wd.type = 0x0a; + wd.type = BDT_CRIT; #ifndef RENEWAL flag.idef = flag.idef2 = #endif @@ -4867,7 +4910,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list else wd.dmg_lv = ATK_DEF; break; - + case KO_BAKURETSU: { #ifdef RENEWAL @@ -5040,7 +5083,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list } break; case SR_FALLENEMPIRE:// [(Target Size value + Skill Level - 1) x Caster STR] + [(Target current weight x Caster DEX / 120)] - ATK_ADD( ((tstatus->size+1)*2 + skill_lv - 1) * sstatus->str); + ATK_ADD( ((tstatus->size+1)*2 + (int64)skill_lv - 1) * sstatus->str); if( tsd && tsd->weight ){ ATK_ADD( (tsd->weight/10) * sstatus->dex / 120 ); }else{ @@ -5307,7 +5350,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list if(skill_id == CR_GRANDCROSS || skill_id == NPC_GRANDDARKNESS) return wd; //Enough, rest is not needed. #ifndef HMAP_ZONE_DAMAGE_CAP_TYPE - if( target && skill_id ) { + if (skill_id) { for(i = 0; i < map->list[target->m].zone->capped_skills_count; i++) { if( skill_id == map->list[target->m].zone->capped_skills[i]->nameid && (map->list[target->m].zone->capped_skills[i]->type & target->type) ) { if( target->type == BL_MOB && map->list[target->m].zone->capped_skills[i]->subtype != MZS_NONE ) { @@ -5505,7 +5548,6 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list #endif } - if( src != target ) { // Don't reflect your own damage (Grand Cross) if( wd.dmg_lv == ATK_MISS || wd.dmg_lv == ATK_BLOCK ) { int64 prev1 = wd.damage, prev2 = wd.damage2; @@ -5532,7 +5574,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list rnd()%100 < tsc->data[SC_SWORDREJECT]->val2 ) { ATK_RATER(50); - status_fix_damage(target,src,wd.damage,clif->damage(target,src,0,0,wd.damage,0,0,0)); + status_fix_damage(target,src,wd.damage,clif->damage(target,src,0,0,wd.damage,0,BDT_NORMAL,0)); clif->skill_nodamage(target,target,ST_REJECTSWORD,tsc->data[SC_SWORDREJECT]->val1,1); if( --(tsc->data[SC_SWORDREJECT]->val3) <= 0 ) status_change_end(target, SC_SWORDREJECT, INVALID_TIMER); @@ -5565,6 +5607,7 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl break; } + nullpo_retr(d, target); #ifdef HMAP_ZONE_DAMAGE_CAP_TYPE if( target && skill_id ) { int i; @@ -5602,9 +5645,10 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl } return d; } + //Performs reflect damage (magic (maya) is performed over skill.c). void battle_reflect_damage(struct block_list *target, struct block_list *src, struct Damage *wd,uint16 skill_id) { - int64 damage = wd->damage + wd->damage2, rdamage = 0, trdamage = 0; + int64 damage, rdamage = 0, trdamage = 0; struct map_session_data *sd, *tsd; struct status_change *sc; int64 tick = timer->gettick(); @@ -5615,6 +5659,10 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st max_reflect_damage = max(status_get_max_hp(target), status_get_max_hp(target) * status->get_lv(target) / 100); #endif + damage = wd->damage + wd->damage2; + + nullpo_retv(wd); + sd = BL_CAST(BL_PC, src); tsd = BL_CAST(BL_PC, target); @@ -5638,8 +5686,8 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st rdamage = ratio + (damage)* (10 + sc->data[SC_CRESCENTELBOW]->val1 * 20 / 10) / 10; skill->blown(target, src, skill->get_blewcount(SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1), unit->getdir(src), 0); clif->skill_damage(target, src, tick, status_get_amotion(src), 0, rdamage, - 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, 6); // This is how official does - clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, 0); + 1, SR_CRESCENTELBOW_AUTOSPELL, sc->data[SC_CRESCENTELBOW]->val1, BDT_SKILL); // This is how official does + clif->delay_damage(tick + delay, src, target,status_get_amotion(src)+1000,0, rdamage/10, 1, BDT_NORMAL); status->damage(src, target, status->damage(target, src, rdamage, 0, 0, 1)/10, 0, 0, 1); status_change_end(target, SC_CRESCENTELBOW, INVALID_TIMER); /* shouldn't this trigger skill->additional_effect? */ @@ -5657,7 +5705,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st int64 rd1 = damage * sc->data[SC_DEATHBOUND]->val2 / 100; // Amplify damage. trdamage += rdamage = rd1 - (damage = rd1 * 30 / 100); // not normalized as intended. - rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, 6); + rdelay = clif->skill_damage(src, target, tick, status_get_amotion(src), status_get_dmotion(src), -3000, 1, RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1, BDT_SKILL); skill->blown(target, src, skill->get_blewcount(RK_DEATHBOUND, sc->data[SC_DEATHBOUND]->val1), unit->getdir(src), 0); if( tsd ) /* is this right? rdamage as both left and right? */ @@ -5684,7 +5732,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if ( tsd && tsd->bonus.short_weapon_damage_return ) { NORMALIZE_RDAMAGE(damage * tsd->bonus.short_weapon_damage_return / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0); @@ -5709,9 +5757,9 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st NORMALIZE_RDAMAGE(damage * sc->data[SC_REFLECTSHIELD]->val2 / 100); #ifndef RENEWAL - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); #else - rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, 4); + rdelay = clif->skill_damage(src, src, tick, delay, status_get_dmotion(src), rdamage, 1, CR_REFLECTSHIELD, 1, BDT_ENDURE); #endif /* is this right? rdamage as both left and right? */ if( tsd ) @@ -5745,7 +5793,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if( sc->data[SC_SHIELDSPELL_DEF] && sc->data[SC_SHIELDSPELL_DEF]->val1 == 2 ){ NORMALIZE_RDAMAGE(damage * sc->data[SC_SHIELDSPELL_DEF]->val2 / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ if( tsd ) @@ -5759,7 +5807,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if( ssc->data[SC_INSPIRATION] ) { NORMALIZE_RDAMAGE(damage / 100); - rdelay = clif->delay_damage(tick+delay,target, target, status_get_amotion(target), status_get_dmotion(target), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,target, target, status_get_amotion(target), status_get_dmotion(target), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ if( sd ) @@ -5774,7 +5822,7 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st if ( tsd && tsd->bonus.long_weapon_damage_return ) { NORMALIZE_RDAMAGE(damage * tsd->bonus.long_weapon_damage_return / 100); - rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, 4); + rdelay = clif->delay_damage(tick+delay,src, src, status_get_amotion(src), status_get_dmotion(src), rdamage, 1, BDT_ENDURE); /* is this right? rdamage as both left and right? */ battle->drain(tsd, src, rdamage, rdamage, status_get_race(src), 0); @@ -5795,11 +5843,14 @@ void battle_reflect_damage(struct block_list *target, struct block_list *src, st return; #undef NORMALIZE_RDAMAGE } + void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldamage, int race, int boss) { struct weapon_data *wd; int type, thp = 0, tsp = 0, rhp = 0, rsp = 0, hp, sp, i; int64 *damage; + + nullpo_retv(sd); for (i = 0; i < 4; i++) { //First two iterations: Right hand if (i < 2) { wd = &sd->right_weapon; damage = &rdamage; } @@ -5862,6 +5913,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { if( bl->type == BL_MOB && ((TBL_MOB*)bl)->class_ == MOBID_EMPERIUM ) return 0; if( bl != src && battle->check_target(src,bl,BCT_ENEMY) > 0 ) { + nullpo_ret(src); map->freeblock_lock(); if( src->type == BL_PC ) battle->drain((TBL_PC*)src, bl, damage, damage, status_get_race(bl), is_boss(bl)); @@ -5869,7 +5921,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { battle->delay_damage(tick, amotion,src,bl,0,CR_REFLECTSHIELD,0,damage,ATK_DEF,0,true); else status_fix_damage(src,bl,damage,0); - clif->damage(bl,bl,amotion,dmotion,damage,1,ATK_BLOCK,0); + clif->damage(bl,bl,amotion,dmotion,damage,1,BDT_ENDURE,0); if( !(src->type == BL_PC && ((TBL_PC*)src)->state.autocast) ) skill->additional_effect(src, bl, CR_REFLECTSHIELD, 1, BF_WEAPON|BF_SHORT|BF_NORMAL,ATK_DEF,tick); map->freeblock_unlock(); @@ -5880,6 +5932,7 @@ int battle_damage_area(struct block_list *bl, va_list ap) { /*========================================== * Do a basic physical attack (call trough unit_attack_timer) *------------------------------------------*/ +// FIXME: flag is undocumented enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* target, int64 tick, int flag) { struct map_session_data *sd = NULL, *tsd = NULL; struct status_data *sstatus, *tstatus; @@ -5961,7 +6014,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t if(dist <= 0 || (!map->check_dir(dir,t_dir) && dist <= tstatus->rhw.range+1)) { uint16 skill_lv = tsc->data[SC_AUTOCOUNTER]->val1; clif->skillcastcancel(target); //Remove the casting bar. [Skotlex] - clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->damage(src, target, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS. status_change_end(target, SC_AUTOCOUNTER, INVALID_TIMER); skill->attack(BF_WEAPON,target,target,src,KN_AUTOCOUNTER,skill_lv,tick,0); return ATK_BLOCK; @@ -5974,7 +6027,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t status_change_end(target, SC_BLADESTOP_WAIT, INVALID_TIMER); if(sc_start4(target, src, SC_BLADESTOP, 100, sd?pc->checkskill(sd, MO_BLADESTOP):5, 0, 0, target->id, duration)) { //Target locked. - clif->damage(src, target, sstatus->amotion, 1, 0, 1, 0, 0); //Display MISS. + clif->damage(src, target, sstatus->amotion, 1, 0, 1, BDT_NORMAL, 0); //Display MISS. clif->bladestop(target, src->id, 1); sc_start4(target, target, SC_BLADESTOP, 100, skill_lv, 0, 0, src->id, duration); return ATK_BLOCK; @@ -6018,18 +6071,6 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t return ATK_DEF; return ATK_MISS; } - if( sc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { - if( sd && rnd()%100 < 10 + 5 * sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) - pc->addspiritball(sd, - skill->get_time(MO_CALLSPIRITS, sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), - sc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); - } - if( tsc && tsc->data[SC_GENTLETOUCH_ENERGYGAIN] ) { - if( tsd && rnd()%100 < 10 + 5 * tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1) - pc->addspiritball(tsd, - skill->get_time(MO_CALLSPIRITS, tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1), - tsc->data[SC_GENTLETOUCH_ENERGYGAIN]->val1); - } if( tsc && tsc->data[SC_MTF_MLEATKED] && rnd()%100 < 20 ) clif->skill_nodamage(target, target, SM_ENDURE, 5, @@ -6052,7 +6093,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } if( sd && sc->data[SC_FEARBREEZE] && sc->data[SC_FEARBREEZE]->val4 > 0 && sd->status.inventory[sd->equip_index[EQI_AMMO]].amount >= sc->data[SC_FEARBREEZE]->val4 && battle_config.arrow_decrement){ - pc->delitem(sd,sd->equip_index[EQI_AMMO],sc->data[SC_FEARBREEZE]->val4,0,1,LOG_TYPE_CONSUME); + pc->delitem(sd, sd->equip_index[EQI_AMMO], sc->data[SC_FEARBREEZE]->val4, 0, DELITEM_SKILLUSE, LOG_TYPE_CONSUME); sc->data[SC_FEARBREEZE]->val4 = 0; } } @@ -6100,7 +6141,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t (d_bl->type == BL_PC && ((TBL_PC*)d_bl)->devotion[sce->val2] == target->id) ) && check_distance_bl(target, d_bl, sce->val3) ) { - clif->damage(d_bl, d_bl, 0, 0, damage, 0, 0, 0); + clif->damage(d_bl, d_bl, 0, 0, damage, 0, BDT_NORMAL, 0); status_fix_damage(NULL, d_bl, damage, 0); } else @@ -6108,7 +6149,7 @@ enum damage_lv battle_weapon_attack(struct block_list* src, struct block_list* t } else if( tsc->data[SC_CIRCLE_OF_FIRE_OPTION] && (wd.flag&BF_SHORT) && target->type == BL_PC ) { struct elemental_data *ed = ((TBL_PC*)target)->ed; if( ed ) { - clif->skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, 6); + clif->skill_damage(&ed->bl, target, tick, status_get_amotion(src), 0, -30000, 1, EL_CIRCLE_OF_FIRE, tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1, BDT_SKILL); skill->attack(BF_MAGIC,&ed->bl,&ed->bl,src,EL_CIRCLE_OF_FIRE,tsc->data[SC_CIRCLE_OF_FIRE_OPTION]->val1,tick,wd.flag); } } else if( tsc->data[SC_WATER_SCREEN_OPTION] && tsc->data[SC_WATER_SCREEN_OPTION]->val1 ) { @@ -6273,6 +6314,7 @@ bool battle_check_undead(int race,int element) //Returns the upmost level master starting with the given object struct block_list* battle_get_master(struct block_list *src) { struct block_list *prev; //Used for infinite loop check (master of yourself?) + nullpo_retr(NULL, src); do { prev = src; switch (src->type) { @@ -6327,7 +6369,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f m = target->m; - if (flag&BCT_ENEMY && ( map->getcell(m,src->x,src->y,CELL_CHKBASILICA) || map->getcell(m,target->x,target->y,CELL_CHKBASILICA) ) ) { + if (flag & BCT_ENEMY && (map->getcell(m, src, src->x, src->y, CELL_CHKBASILICA) || map->getcell(m, src, target->x, target->y, CELL_CHKBASILICA))) { return -1; } @@ -6357,7 +6399,6 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f switch( target->type ) { // Checks on actual target case BL_PC: { struct status_change* sc = status->get_sc(src); - if( ((TBL_PC*)target)->invincible_timer != INVALID_TIMER ) { switch( battle->get_current_skill(src) ) { /* TODO a proper distinction should be established bugreport:8397 */ @@ -6377,21 +6418,26 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f } break; case BL_MOB: - if(((((TBL_MOB*)target)->special_state.ai == 2 || //Marine Spheres - (((TBL_MOB*)target)->special_state.ai == 3 && battle_config.summon_flora&1)) && //Floras - s_bl->type == BL_PC && src->type != BL_MOB) || (((TBL_MOB*)target)->special_state.ai == 4 && t_bl->id != s_bl->id)) //Zanzoe - { + { + TBL_MOB *md = BL_CAST(BL_MOB, target); + if(( + (md->special_state.ai == AI_SPHERE || (md->special_state.ai == AI_FLORA && battle_config.summon_flora&1)) + && s_bl->type == BL_PC && src->type != BL_MOB + ) + || (md->special_state.ai == AI_ZANZOU && t_bl->id != s_bl->id) + ) { //Targetable by players state |= BCT_ENEMY; strip_enemy = 0; } break; + } case BL_SKILL: { TBL_SKILL *su = (TBL_SKILL*)target; if( !su->group ) return 0; - if( skill->get_inf2(su->group->skill_id)&INF2_TRAP && + if( skill->get_inf2(su->group->skill_id)&INF2_TRAP && su->group->unit_id != UNT_USED_TRAPS && su->group->unit_id != UNT_NETHERWORLD ) { //Only a few skills can target traps... switch( battle->get_current_skill(src) ) { @@ -6531,7 +6577,7 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f ) { if( t_bl->type == BL_PC && (sd->duel_group == ((TBL_PC*)t_bl)->duel_group) ) return (BCT_ENEMY&flag)?1:-1; // Duel targets can ONLY be your enemy, nothing else. - else if ( src->type != BL_SKILL || (flag&BCT_ENEMY) ) + else if (src->type != BL_SKILL || (flag&BCT_ALL) != BCT_ALL) return 0; } } @@ -6548,19 +6594,16 @@ int battle_check_target( struct block_list *src, struct block_list *target,int f && md->guardian_data && (md->guardian_data->g || md->guardian_data->castle->guild_id) ) return 0; // Disable guardians/emperium owned by Guilds on non-woe times. - if( !md->special_state.ai ) - { //Normal mobs - if( - ( target->type == BL_MOB && t_bl->type == BL_PC && ( ((TBL_MOB*)target)->special_state.ai != 4 && ((TBL_MOB*)target)->special_state.ai != 1 ) ) || - ( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) - ) + if (md->special_state.ai == AI_NONE) { + //Normal mobs + struct mob_data *target_md = BL_CAST(BL_MOB, target); + if( (target_md && t_bl->type == BL_PC && target_md->special_state.ai != AI_ZANZOU && target_md->special_state.ai != AI_ATTACK) + || (t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai) ) state |= BCT_PARTY; //Normal mobs with no ai are friends. else state |= BCT_ENEMY; //However, all else are enemies. - } - else - { - if( t_bl->type == BL_MOB && !((TBL_MOB*)t_bl)->special_state.ai ) + } else { + if (t_bl->type == BL_MOB && ((TBL_MOB*)t_bl)->special_state.ai == AI_NONE) state |= BCT_ENEMY; //Natural enemy for AI mobs are normal mobs. } break; @@ -6687,7 +6730,7 @@ bool battle_check_range(struct block_list *src, struct block_list *bl, int range if( d > AREA_SIZE ) return false; // Avoid targeting objects beyond your range of sight. - return path->search_long(NULL,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL); + return path->search_long(NULL,src,src->m,src->x,src->y,bl->x,bl->y,CELL_CHKWALL); } static const struct battle_data { @@ -7046,7 +7089,6 @@ static const struct battle_data { { "mail_show_status", &battle_config.mail_show_status, 0, 0, 2, }, { "client_limit_unit_lv", &battle_config.client_limit_unit_lv, 0, 0, BL_ALL, }, { "client_emblem_max_blank_percent", &battle_config.client_emblem_max_blank_percent, 100, 0, 100, }, - // BattleGround Settings { "bg_update_interval", &battle_config.bg_update_interval, 1000, 100, INT_MAX, }, { "bg_flee_penalty", &battle_config.bg_flee_penalty, 20, 0, INT_MAX, }, @@ -7082,7 +7124,6 @@ static const struct battle_data { { "feature.banking", &battle_config.feature_banking, 1, 0, 1, }, { "feature.auction", &battle_config.feature_auction, 0, 0, 2, }, { "idletime_criteria", &battle_config.idletime_criteria, 0x25, 1, INT_MAX, }, - { "mon_trans_disable_in_gvg", &battle_config.mon_trans_disable_in_gvg, 0, 0, 1, }, { "case_sensitive_aegisnames", &battle_config.case_sensitive_aegisnames, 1, 0, 1, }, { "guild_castle_invite", &battle_config.guild_castle_invite, 0, 0, 1, }, @@ -7094,6 +7135,7 @@ static const struct battle_data { { "mob_icewall_walk_block", &battle_config.mob_icewall_walk_block, 75, 0, 255, }, { "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, }, { "feature.roulette", &battle_config.feature_roulette, 1, 0, 1, }, + { "show_monster_hp_bar", &battle_config.show_monster_hp_bar, 1, 0, 1, }, }; #ifndef STATS_OPT_OUT /** @@ -7120,14 +7162,14 @@ void Hercules_report(char* date, char *time_c) { C_RENEWAL_EDP = 0x0400, C_RENEWAL_ASPD = 0x0800, C_SECURE_NPCTIMEOUT = 0x1000, - C_SQL_DB_ITEM = 0x2000, + //C_SQL_DB_ITEM = 0x2000, C_SQL_LOGS = 0x4000, C_MEMWATCH = 0x8000, C_DMALLOC = 0x10000, C_GCOLLECT = 0x20000, C_SEND_SHORTLIST = 0x40000, - C_SQL_DB_MOB = 0x80000, - C_SQL_DB_MOBSKILL = 0x100000, + //C_SQL_DB_MOB = 0x80000, + //C_SQL_DB_MOBSKILL = 0x100000, C_PACKETVER_RE = 0x200000, }; @@ -7192,13 +7234,6 @@ void Hercules_report(char* date, char *time_c) { #endif /* non-define part */ - if( map->db_use_sql_item_db ) - config |= C_SQL_DB_ITEM; - if( map->db_use_sql_mob_db ) - config |= C_SQL_DB_MOB; - if( map->db_use_sql_mob_skill_db ) - config |= C_SQL_DB_MOBSKILL; - if( logs->config.sql_logs ) config |= C_SQL_LOGS; @@ -7268,8 +7303,10 @@ static int Hercules_report_timer(int tid, int64 tick, int id, intptr_t data) { int battle_set_value(const char* w1, const char* w2) { int val = config_switch(w2); - int i; + + nullpo_retr(1, w1); + nullpo_retr(1, w2); ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); if (i == ARRAYLENGTH(battle_data)) { if( HPM->parseConf(w1,w2,HPCT_BATTLE) ) /* if plugin-owned, succeed */ @@ -7290,6 +7327,7 @@ int battle_set_value(const char* w1, const char* w2) int battle_get_value(const char* w1) { int i; + nullpo_retr(1, w1); ARR_FIND(0, ARRAYLENGTH(battle_data), i, strcmpi(w1, battle_data[i].str) == 0); if (i == ARRAYLENGTH(battle_data)) return 0; // not found @@ -7360,7 +7398,6 @@ void battle_adjust_conf(void) { } #endif - #ifndef CELL_NOSTACK if (battle_config.custom_cell_stack_limit != 1) ShowWarning("Battle setting 'custom_cell_stack_limit' takes no effect as this server was compiled without Cell Stack Limit support.\n"); @@ -7372,6 +7409,8 @@ int battle_config_read(const char* cfgName) FILE* fp; static int count = 0; + nullpo_ret(cfgName); + if (count == 0) battle->config_set_defaults(); |