diff options
Diffstat (limited to 'src/map')
-rw-r--r-- | src/map/battle.c | 33 | ||||
-rw-r--r-- | src/map/clif.h | 2 | ||||
-rw-r--r-- | src/map/skill.c | 66 | ||||
-rw-r--r-- | src/map/status.c | 192 | ||||
-rw-r--r-- | src/map/status.h | 10 |
5 files changed, 165 insertions, 138 deletions
diff --git a/src/map/battle.c b/src/map/battle.c index 92b630619..9951090e7 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1027,9 +1027,6 @@ static struct Damage battle_calc_weapon_attack( { if (tsc->data[SC_SLEEP].timer!=-1 ) cri <<=1; - if(tsc->data[SC_JOINTBEAT].timer != -1 && - tsc->data[SC_JOINTBEAT].val2 == 5) // Always take crits with Neck broken by Joint Beat [DracoRPG] - flag.cri=1; } switch (skill_num) { @@ -1131,7 +1128,7 @@ static struct Damage battle_calc_weapon_attack( if(wd.flag&BF_LONG && !skill_num && //Fogwall's hit penalty is only for normal ranged attacks. tsc && tsc->data[SC_FOGWALL].timer!=-1) hitrate-=50; - + if(sd && flag.arrow) hitrate += sd->arrow_hit; if(skill_num) @@ -1843,7 +1840,7 @@ static struct Damage battle_calc_weapon_attack( if(sd && (skill=pc_checkskill(sd,BS_WEAPONRESEARCH)) > 0) ATK_ADD(skill*2); - + if(skill_num==TF_POISON) ATK_ADD(15*skill_lv); @@ -1956,10 +1953,10 @@ static struct Damage battle_calc_weapon_attack( if (tsd) { short s_race2,s_class; short cardfix=1000; - + s_race2 = status_get_race2(src); s_class = status_get_class(src); - + cardfix=cardfix*(100-tsd->subele[s_ele])/100; if (flag.lh && s_ele_ != s_ele) cardfix=cardfix*(100-tsd->subele[s_ele_])/100; @@ -1967,14 +1964,14 @@ static struct Damage battle_calc_weapon_attack( 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; - + for(i=0;i<tsd->add_dmg_count;i++) { if(tsd->add_dmg[i].class_ == s_class) { cardfix=cardfix*(100+tsd->add_dmg[i].rate)/100; break; } } - + if(wd.flag&BF_SHORT) cardfix=cardfix*(100-tsd->near_attack_def_rate)/100; else // BF_LONG (there's no other choice) @@ -1994,7 +1991,7 @@ static struct Damage battle_calc_weapon_attack( //Do not return if you are supposed to deal greater damage to plants than 1. [Skotlex] return wd; } - + if(sd && !skill_num && !flag.cri) { //Check for double attack. if(((skill_lv = pc_checkskill(sd,TF_DOUBLE)) > 0 && sd->weapontype1 == W_DAGGER) || sd->double_rate > 0) @@ -2016,7 +2013,7 @@ static struct Damage battle_calc_weapon_attack( wd.type = 0x08; } } - + if (sd) { if (!flag.rh && flag.lh) @@ -2051,10 +2048,10 @@ static struct Damage battle_calc_weapon_attack( if(!flag.rh && wd.damage) wd.damage=0; - + if(!flag.lh && wd.damage2) wd.damage2=0; - + if(wd.damage + wd.damage2) { //There is a total damage value if(!wd.damage2) { @@ -2082,6 +2079,10 @@ static struct Damage battle_calc_weapon_attack( { //Breaker's int-based damage (a misc attack?) struct Damage md = battle_calc_misc_attack(src, target, skill_num, skill_lv, wflag); wd.damage += md.damage; + } else if( skill_num == LK_JOINTBEAT && wflag&BREAK_NECK ) { + //##TODO should this be here?[FlavioJS] + // Although not clear, it's being assumed that the 2x damage is only for the break neck ailment. + wd.damage *= 2; // 2x damage when breaking neck } if (wd.damage || wd.damage2) { @@ -3002,12 +3003,12 @@ int battle_weapon_attack( struct block_list *src,struct block_list *target, } else if (sc && sc->data[SC_SACRIFICE].timer != -1) return skill_attack(BF_WEAPON,src,src,target,PA_SACRIFICE,sc->data[SC_SACRIFICE].val1,tick,0); - - wd = battle_calc_weapon_attack(src,target, 0, 0,0); + + wd = battle_calc_weapon_attack(src, target, 0, 0, flag); if (sd && sd->state.arrow_atk) //Consume arrow. battle_consume_ammo(sd, 0, 0); - + damage = wd.damage + wd.damage2; if (damage > 0 && src != target) { rdamage = battle_calc_return_damage(target, 0, &damage, wd.flag); diff --git a/src/map/clif.h b/src/map/clif.h index 46875eae0..3e19222f6 100644 --- a/src/map/clif.h +++ b/src/map/clif.h @@ -95,7 +95,7 @@ int clif_additem(struct map_session_data*,int,int,int); //self int clif_delitem(struct map_session_data*,int,int); //self int clif_updatestatus(struct map_session_data*,int); //self int clif_changestatus(struct block_list*,int,int); //area -int clif_damage(struct block_list *,struct block_list *,unsigned int,int,int,int,int,int,int); // area +int clif_damage(struct block_list *src,struct block_list *dst,unsigned int tick,int sdelay,int ddelay,int damage,int div,int type,int damage2); // area #define clif_takeitem(src,dst) clif_damage(src,dst,0,0,0,0,0,1,0) int clif_changelook(struct block_list *,int,int); // area void clif_changetraplook(struct block_list *bl,int val); // area diff --git a/src/map/skill.c b/src/map/skill.c index 8f7fc0b48..77d3c185c 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -998,7 +998,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int md = (struct mob_data *)src; break; } - + switch (bl->type) { case BL_PC: dstsd=(struct map_session_data *)bl; @@ -1061,7 +1061,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int } } - if (sc && sc->count) { + if (sc && sc->count) { // Enchant Poison gives a chance to poison attacked enemies if(sc->data[SC_ENCPOISON].timer != -1) //Don't use sc_start since chance comes in 1/10000 rate. status_change_start(bl,SC_POISON,sc->data[SC_ENCPOISON].val2, @@ -1134,7 +1134,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int sc_start(bl,SC_FREEZE,(3*skilllv+35),skilllv,skill_get_time2(skillid,skilllv)); break; - case HT_FLASHER: + case HT_FLASHER: sc_start(bl,SC_BLIND,(10*skilllv+30),skilllv,skill_get_time2(skillid,skilllv)); break; @@ -1179,7 +1179,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int case AM_DEMONSTRATION: skill_break_equip(bl, EQP_WEAPON, 100*skilllv, BCT_ENEMY); break; - + case CR_SHIELDCHARGE: sc_start(bl,SC_STUN,(15+skilllv*5),skilllv,skill_get_time2(skillid,skilllv)); break; @@ -1275,11 +1275,15 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int if (!(battle_check_undead(tstatus->race, tstatus->def_ele) || tstatus->race == RC_DEMON)) sc_start(bl, SC_BLEEDING,50, skilllv, skill_get_time2(skillid,skilllv)); break; - +/* case LK_JOINTBEAT: - sc_start(bl,SkillStatusChangeTable(skillid),(5*skilllv+5),skilllv,skill_get_time2(skillid,skilllv)); + { + int flag = 0; + //##TODO how should this be done? the ailment has to be calculated before because it also affects the damage [FlavioJS] + sc_start2(bl,SkillStatusChangeTable(skillid),(5*skilllv+5),skilllv,flag&BREAK_FLAGS,skill_get_time2(skillid,skilllv)); break; - + } +*/ case ASC_METEORASSAULT: //Any enemies hit by this skill will receive Stun, Darkness, or external bleeding status ailment with a 5%+5*SkillLV% chance. switch(rand()%3) { @@ -1385,7 +1389,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int if (sd->addeff[i].flag&ATF_TARGET) status_change_start(bl,type,rate,7,0,0,0,skill,0); - + if (sd->addeff[i].flag&ATF_SELF) status_change_start(src,type,rate,7,0,0,0,skill,0); } @@ -1409,7 +1413,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int for (i = 0; i < MAX_PC_BONUS && sd->autospell[i].id; i++) { skill = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id; - + if (skillnotok(skill, sd)) continue; @@ -1422,7 +1426,7 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int tbl = src; else tbl = bl; - + if (tbl != src && !battle_check_range(src, tbl, skill_get_range2(src, skill, skilllv))) continue; //Autoskills DO check for target-src range. [Skotlex] rate = skill_get_inf(skill); @@ -1469,7 +1473,6 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int if (skill < 2000) mob_class_change(dstmd,class_); } - return 0; } @@ -1503,7 +1506,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * tsc = status_get_sc(bl); if (tsc && !tsc->count) tsc = NULL; - + BL_CAST(BL_PC, src, sd); BL_CAST(BL_PC, bl, dstsd); @@ -1567,7 +1570,7 @@ int skill_counter_additional_effect (struct block_list* src, struct block_list * status_change_start(bl,type,rate,7,0,0,0,time,0); } } - + //Trigger counter-spells to retaliate against damage causing skills. [Skotlex] if(dstsd && !status_isdead(bl) && src != bl && !(skillid && skill_get_nk(skillid)&NK_NO_DAMAGE)) { @@ -1636,7 +1639,7 @@ int skill_break_equip (struct block_list *bl, unsigned short where, int rate, in BL_CAST(BL_PC, bl, sd); if (sc && !sc->count) sc = NULL; - + if (sd) { if (sd->unbreakable_equip) where &= ~sd->unbreakable_equip; @@ -1794,10 +1797,10 @@ int skill_blown (struct block_list *src, struct block_list *target, int count) if (!dx && !dy) //Could not knockback. return 0; - + map_foreachinmovearea(clif_outsight, target, AREA_SIZE, dx, dy, target->type==BL_PC?BL_ALL:BL_PC, target); - + if(su) skill_unit_move_unit_group(su->group,target->m,dx,dy); else @@ -1805,7 +1808,7 @@ int skill_blown (struct block_list *src, struct block_list *target, int count) map_foreachinmovearea(clif_insight, target, AREA_SIZE, -dx, -dy, target->type==BL_PC?BL_ALL:BL_PC, target); - + if(!(count&0x20000)) clif_blown(target); @@ -2682,13 +2685,13 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int if (sd) clif_skill_fail(sd,skillid,0,0); return 1; } - + sc = status_get_sc(src); if (sc && !sc->count) sc = NULL; //Unneeded - + tstatus = status_get_status_data(bl); - + map_freeblock_lock(); switch(skillid) @@ -2743,7 +2746,6 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int case LK_AURABLADE: case LK_SPIRALPIERCE: case LK_HEADCRUSH: - case LK_JOINTBEAT: case CG_ARROWVULCAN: case HW_MAGICCRASHER: case ITM_TOMAHAWK: @@ -2775,6 +2777,20 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); break; + case LK_JOINTBEAT: // decide the ailment first (affects attack damage and effect) + switch( rand()%6 ){ + case 0: flag |= BREAK_ANKLE; break; + case 1: flag |= BREAK_WRIST; break; + case 2: flag |= BREAK_KNEE; break; + case 3: flag |= BREAK_SHOULDER; break; + case 4: flag |= BREAK_WAIST; break; + case 5: flag |= BREAK_NECK; break; + } + skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,flag); + //##TODO this is a quick&dirty hack. How do I pass the selected ailment to skill_additional_effect? [FlavioJS] + sc_start2(bl,SkillStatusChangeTable(skillid),(5*skilllv+5),skilllv,flag&BREAK_FLAGS,skill_get_time2(skillid,skilllv)); + break; + case MO_COMBOFINISH: if (!(flag&1) && sc && sc->data[SC_SPIRIT].timer != -1 && sc->data[SC_SPIRIT].val2 == SL_MONK) { //Becomes a splash attack when Soul Linked. @@ -2806,7 +2822,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int if (unit_movepos(src, bl->x, bl->y, 0, 0)) clif_slide(src,bl->x,bl->y); break; - + case SN_SHARPSHOOTING: case NJ_KAMAITACHI: //It won't shoot through walls since on castend there has to be a direct @@ -2854,7 +2870,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int if (sc && sc->data[SC_BLADESTOP].timer != -1) status_change_end(src,SC_BLADESTOP,-1); break; - + case NJ_ISSEN: if (sc) { if (sc->data[SC_NEN].timer != -1) @@ -3003,7 +3019,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl, int skill_attack(BF_WEAPON,src,src,bl,skillid,skilllv,tick,0); } break; - + case KN_SPEARSTAB: if(flag&1){ if (bl->id==skill_area_temp[1]) @@ -3299,7 +3315,7 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if (skillid > 0) type = SkillStatusChangeTable(skillid); - + tsc = status_get_sc(bl); map_freeblock_lock(); diff --git a/src/map/status.c b/src/map/status.c index 72a506e8e..a941d265e 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -528,7 +528,7 @@ int status_set_hp(struct block_list *bl, unsigned int hp, int flag) int status_set_sp(struct block_list *bl, unsigned int sp, int flag) { struct status_data *status; - + status = status_get_status_data(bl); if (status == &dummy_status) return 0; @@ -551,7 +551,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s if(sp && !(target->type&BL_CONSUME)) sp = 0; //Not a valid SP target. - + if (hp < 0) { //Assume absorbed damage. status_heal(target, -hp, 0, 1); hp = 0; @@ -561,16 +561,16 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status_heal(target, 0, -sp, 1); sp = 0; } - + if (!hp && !sp) return 0; - + if (target->type == BL_SKILL) return skill_unit_ondamaged((struct skill_unit *)target, src, hp, gettick()); - + status = status_get_status_data(target); - + if (status == &dummy_status || !status->hp) return 0; //Invalid targets: no damage or dead @@ -646,10 +646,10 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s if (flag&2) return 0; sp = status->sp; } - + status->hp-= hp; status->sp-= sp; - + if (sc && hp && status->hp) { if (sc->data[SC_AUTOBERSERK].timer != -1 && (sc->data[SC_PROVOKE].timer==-1 || !sc->data[SC_PROVOKE].val2) && @@ -659,7 +659,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s status->hp <= 100) status_change_end(target, SC_BERSERK, -1); } - + switch (target->type) { case BL_MOB: @@ -703,7 +703,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s if(!flag) //Death cancelled. return hp+sp; - + //Normal death status->hp = 0; if (battle_config.clear_unit_ondeath && @@ -736,7 +736,7 @@ int status_damage(struct block_list *src,struct block_list *target,int hp, int s skill_unit_move(target,gettick(),4); skill_cleartimerskill(target); } - + return hp+sp; } @@ -751,7 +751,7 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) if (status == &dummy_status || !status->hp) return 0; - + sc = status_get_sc(bl); if (sc && !sc->count) sc = NULL; @@ -760,12 +760,11 @@ int status_heal(struct block_list *bl,int hp,int sp, int flag) status_damage(NULL, bl, -hp, 0, 0, 1); hp = 0; } - + if(hp) { if (!(flag&1) && sc && sc->data[SC_BERSERK].timer!=-1) hp = 0; - if((unsigned int)hp > status->max_hp - status->hp) hp = status->max_hp - status->hp; } @@ -880,7 +879,7 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per status = status_get_status_data(bl); if (status == &dummy_status) return 0; //Invalid target. - + hp = status->max_hp * per_hp/100; sp = status->max_sp * per_sp/100; @@ -889,7 +888,7 @@ int status_revive(struct block_list *bl, unsigned char per_hp, unsigned char per if(sp > status->max_sp - status->sp) sp = status->max_sp - status->sp; - + status->hp += hp; status->sp += sp; @@ -930,7 +929,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int if (src && status_isdead(src)) return 0; - + if (!skill_num) { //Normal attack checks. if (!(status->mode&MD_CANATTACK)) return 0; //This mode is only needed for melee attacking. @@ -961,7 +960,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int } if (src) sc = status_get_sc(src); - + if(sc && sc->count) { if(sc->opt1 >0) @@ -986,7 +985,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int clif_emotion(src, 3); return 0; } - + if (sc->data[SC_BLADESTOP].timer != -1) { switch (sc->data[SC_BLADESTOP].val1) { @@ -1079,7 +1078,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int //You cannot hide from ground skills. if(skill_get_pl(skill_num) == ELE_EARTH) hide_flag &= ~OPTION_HIDE; - + switch (target->type) { case BL_PC: @@ -1132,7 +1131,7 @@ int status_check_visibility(struct block_list *src, struct block_list *target) if (src->m != target->m || !check_distance_bl(src, target, view_range)) return 0; - + switch (target->type) { //Check for chase-walk/hiding/cloaking opponents. case BL_PC: @@ -1271,13 +1270,13 @@ int status_calc_mob(struct mob_data* md, int first) if (md->guardian_data && md->guardian_data->guardup_lv) flag|=4; - + if (battle_config.slaves_inherit_speed && md->master_id) flag|=8; - + if (md->master_id && md->special_state.ai>1) flag|=16; - + if (!flag) { //No special status required. if (md->base_status) { @@ -1290,10 +1289,10 @@ int status_calc_mob(struct mob_data* md, int first) } if (!md->base_status) md->base_status = aCalloc(1, sizeof(struct status_data)); - + status = md->base_status; memcpy(status, &md->db->status, sizeof(struct status_data)); - + if (flag&(8|16)) mbl = map_id2bl(md->master_id); @@ -1304,7 +1303,7 @@ int status_calc_mob(struct mob_data* md, int first) battle_config.slaves_inherit_speed&(mstatus->mode&MD_CANMOVE?1:2)) status->speed = mstatus->speed; } - + if (flag&16 && mbl) { //Max HP setting from Summon Flora/marine Sphere struct unit_data *ud = unit_bl2ud(mbl); @@ -1338,8 +1337,8 @@ int status_calc_mob(struct mob_data* md, int first) status->sp = status->max_sp; status->speed -= diff; } - - + + if (flag&2) { // change for sized monsters [Valaris] if (md->special_state.size==1) { @@ -1409,7 +1408,7 @@ int status_calc_mob(struct mob_data* md, int first) //Skotlex: Calculates the stats of the given pet. int status_calc_pet(struct pet_data *pd, int first) { - + nullpo_retr(0, pd); if (first) { @@ -1439,7 +1438,7 @@ int status_calc_pet(struct pet_data *pd, int first) status->int_ = (bstat->int_*lv)/pd->db->lv; status->dex = (bstat->dex*lv)/pd->db->lv; status->luk = (bstat->luk*lv)/pd->db->lv; - + status->rhw.atk = cap_value(status->rhw.atk, 1, battle_config.pet_max_atk1); status->rhw.atk2 = cap_value(status->rhw.atk2, 2, battle_config.pet_max_atk2); status->str = cap_value(status->str,1,battle_config.pet_max_stats); @@ -1502,7 +1501,7 @@ static unsigned int status_base_pc_maxsp(struct map_session_data* sd, struct sta val -= val * 30/100; if ((sd->class_&MAPID_UPPERMASK) == MAPID_TAEKWON && sd->status.base_level >= 90 && pc_famerank(sd->status.char_id, MAPID_TAEKWON)) val *= 3; //Triple max SP for top ranking Taekwons over level 90. - + return val; } @@ -1529,13 +1528,13 @@ int status_calc_pc(struct map_session_data* sd,int first) memcpy(&b_status, &sd->battle_status, sizeof(struct status_data)); memcpy(&b_lhw, &sd->battle_lhw, sizeof(struct weapon_atk)); b_status.lhw = &b_lhw; - + memcpy(b_skill,&sd->status.skill,sizeof(b_skill)); b_weight = sd->weight; b_max_weight = sd->max_weight; - + pc_calc_skilltree(sd); // スキルツリ?の計算 - + sd->max_weight = max_weight_base[sd->status.class_]+sd->status.str*300; if(first&1) { @@ -1578,7 +1577,7 @@ int status_calc_pc(struct map_session_data* sd,int first) sd->critical_rate = sd->hit_rate = sd->flee_rate = sd->flee2_rate = 100; sd->def_rate = sd->def2_rate = sd->mdef_rate = sd->mdef2_rate = 100; sd->regen.state.block = 0; - + // zeroed arays, order follows the order in map.h. // add new arrays to the end of zeroed area in map.h (see comments) and size here. [zzo] malloc_set (sd->param_bonus, 0, sizeof(sd->param_bonus) @@ -1643,7 +1642,7 @@ int status_calc_pc(struct map_session_data* sd,int first) + sizeof(sd->add_drop) + sizeof(sd->itemhealrate) ); - + // vars zeroing. ints, shorts, chars. in that order. malloc_set (&sd->arrow_atk, 0,sizeof(sd->arrow_atk) + sizeof(sd->arrow_ele) @@ -1714,7 +1713,7 @@ int status_calc_pc(struct map_session_data* sd,int first) continue; if(!sd->inventory_data[index]) continue; - + status->def += sd->inventory_data[index]->def; if(first&1 && sd->inventory_data[index]->equip_script) @@ -1787,11 +1786,11 @@ int status_calc_pc(struct map_session_data* sd,int first) return 1; } } - + //Store equipment script bonuses memcpy(sd->param_equip,sd->param_bonus,sizeof(sd->param_equip)); malloc_set(sd->param_bonus, 0, sizeof(sd->param_bonus)); - + status->def += (refinedef+50)/100; //Parse Cards @@ -1809,7 +1808,7 @@ int status_calc_pc(struct map_session_data* sd,int first) if(sd->inventory_data[index]) { int j,c; struct item_data *data; - + //Card script execution. if(itemdb_isspecial(sd->status.inventory[index].card[0])) continue; @@ -1848,7 +1847,7 @@ int status_calc_pc(struct map_session_data* sd,int first) } } } - + if(sd->pd && battle_config.pet_status_support) { // Pet struct pet_data *pd=sd->pd; @@ -1858,7 +1857,7 @@ int status_calc_pc(struct map_session_data* sd,int first) pc_bonus(sd,pd->bonus->type, pd->bonus->val); } //param_bonus now holds card bonuses. - + if(status->rhw.range < 1) status->rhw.range = 1; if(status->lhw->range < 1) status->lhw->range = 1; if(status->rhw.range < status->lhw->range) @@ -1947,7 +1946,7 @@ int status_calc_pc(struct map_session_data* sd,int first) status->dex = cap_value(i,0,USHRT_MAX); i = status->luk + sd->status.luk + sd->param_bonus[5] + sd->param_equip[5]; status->luk = cap_value(i,0,USHRT_MAX); - + // ------ BASE ATTACK CALCULATION ------ // Base batk value is set on status_calc_misc @@ -1981,7 +1980,7 @@ int status_calc_pc(struct map_session_data* sd,int first) status->max_hp = battle_config.max_hp; else if(!status->max_hp) status->max_hp = 1; - + // ----- SP MAX CALCULATION ----- // Basic MaxSP value @@ -2058,7 +2057,7 @@ int status_calc_pc(struct map_session_data* sd,int first) sd->mdef2_rate = 0; if(sd->mdef2_rate != 100) status->mdef2 = status->mdef2 * sd->mdef2_rate/100; - + if(sd->critical_rate < 0) sd->critical_rate = 0; if(sd->critical_rate != 100) @@ -2128,7 +2127,7 @@ int status_calc_pc(struct map_session_data* sd,int first) status->mdef2 += battle_config.over_def_bonus*(status->mdef -battle_config.max_def); status->mdef = (signed char)battle_config.max_def; } - + // ----- WALKING SPEED CALCULATION ----- if(sd->speed_rate < 0) @@ -2175,9 +2174,9 @@ int status_calc_pc(struct map_session_data* sd,int first) status->aspd_rate -= ((skill+1)/2) * 10; if(pc_isriding(sd)) status->aspd_rate += 500-100*pc_checkskill(sd,KN_CAVALIERMASTERY); - + status->adelay = 2*status->amotion; - + // ----- DMOTION ----- // @@ -2263,7 +2262,7 @@ int status_calc_pc(struct map_session_data* sd,int first) status_cpy(&sd->battle_status, status); status_calc_bl(&sd->bl, SCB_ALL); //Status related changes. status = &sd->battle_status; //Need to compare versus this. - + // ----- CLIENT-SIDE REFRESH ----- if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill))) clif_skillinfoblock(sd); @@ -2336,12 +2335,12 @@ int status_calc_homunculus(struct homun_data *hd, int first) struct status_data b_status, *status; struct s_homunculus *hom; int skill; - + memcpy(&b_status, &hd->base_status, sizeof(struct status_data)); hom = &hd->homunculus; status = &hd->base_status; - + status->str = hom->str / 10; status->agi = hom->agi / 10; status->vit = hom->vit / 10; @@ -2377,7 +2376,7 @@ int status_calc_homunculus(struct homun_data *hd, int first) if((skill=merc_hom_checkskill(hd,HAMI_SKIN)) > 0) status->def += skill * 4; - + if((skill = merc_hom_checkskill(hd,HVAN_INSTRUCT)) > 0) { status->int_ += 1 +skill/2 +skill/4 +skill/5; @@ -2402,7 +2401,7 @@ int status_calc_homunculus(struct homun_data *hd, int first) skill = (1000 -4*status->agi -status->dex) *hd->homunculusDB->baseASPD/1000; - + status->amotion = cap_value(skill,battle_config.max_aspd,2000); status->adelay = status->amotion; //It seems adelay = amotion for Homunculus. @@ -2446,11 +2445,11 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct { struct map_session_data *sd; int val, skill; - + if (!(bl->type&BL_REGEN) || !regen) return; BL_CAST(BL_PC,bl,sd); - + val = 1 + (status->vit/5) + (status->max_hp/200); if (sd && sd->hprecov_rate != 100) @@ -2466,7 +2465,7 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct val = val*sd->sprecov_rate/100; regen->sp = cap_value(val, 1, SHRT_MAX); - + if(sd) { struct regen_data_sub *sregen; @@ -2489,10 +2488,10 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct if((skill=pc_checkskill(sd,NJ_NINPOU)) > 0) val += skill*3 + (status->max_sp*skill/500); sregen->sp = cap_value(val, 0, SHRT_MAX); - + // Skill-related recovery (only when sit) sregen = regen->ssregen; - + val = 0; if((skill=pc_checkskill(sd,MO_SPIRITSRECOVERY)) > 0) val += skill*4 + (status->max_hp*skill/500); @@ -2512,7 +2511,7 @@ void status_calc_regen(struct block_list *bl, struct status_data *status, struct val += skill*2 + (status->max_sp*skill/500); sregen->sp = cap_value(val, 0, SHRT_MAX); } - + if(bl->type==BL_HOM) { struct homun_data *hd = (TBL_HOM*)bl; @@ -2534,7 +2533,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str { if (!(bl->type&BL_REGEN) || !regen) return; - + regen->flag = RGN_HP|RGN_SP; if(regen->sregen) { @@ -2555,7 +2554,7 @@ void status_calc_regen_rate(struct block_list *bl, struct regen_data *regen, str regen->ssregen->rate.hp = regen->ssregen->rate.sp = 1; } regen->rate.hp = regen->rate.sp = 1; - + if (!sc || !sc->count) return; @@ -2608,17 +2607,17 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) if(flag&(SCB_MAXHP|SCB_VIT)) { flag|=SCB_MAXHP; //Ensures client-side refresh - + status->max_hp = status_base_pc_maxhp(sd,status); status->max_hp += b_status->max_hp - sd->status.max_hp; - + status->max_hp = status_calc_maxhp(&sd->bl, &sd->sc, status->max_hp); - + if(status->max_hp > (unsigned int)battle_config.max_hp) status->max_hp = battle_config.max_hp; else if(!status->max_hp) status->max_hp = 1; - + if(status->hp > status->max_hp) { status->hp = status->max_hp; clif_updatestatus(sd,SP_HP); @@ -2628,17 +2627,17 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) if(flag&(SCB_MAXSP|SCB_INT)) { flag|=SCB_MAXSP; - + status->max_sp = status_base_pc_maxsp(sd,status); status->max_sp += b_status->max_sp - sd->status.max_sp; - + status->max_sp = status_calc_maxsp(&sd->bl, &sd->sc, status->max_sp); - + if(status->max_sp > (unsigned int)battle_config.max_sp) status->max_sp = battle_config.max_sp; else if(!status->max_sp) status->max_sp = 1; - + if(status->sp > status->max_sp) { status->sp = status->max_sp; clif_updatestatus(sd,SP_SP); @@ -2692,7 +2691,7 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) )) *2/3; status->aspd_rate = status_calc_aspd_rate(&sd->bl, &sd->sc , b_status->aspd_rate); - + // Apply all relative modifiers if(status->aspd_rate != 1000) skill = skill *status->aspd_rate/1000; @@ -2711,7 +2710,7 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) } } - + if(flag&(SCB_AGI|SCB_DSPD)) { if (b_status->agi == status->agi) status->dmotion = status_calc_dmotion(&sd->bl, &sd->sc, b_status->dmotion); @@ -2733,13 +2732,13 @@ void status_calc_bl_sub_pc(struct map_session_data *sd, unsigned long flag) if(flag&(SCB_INT|SCB_MAXSP|SCB_VIT|SCB_MAXHP)) status_calc_regen(&sd->bl, status, &sd->regen); - + if(flag&SCB_REGEN) status_calc_regen_rate(&sd->bl, &sd->regen, &sd->sc); - + if (flag == SCB_ALL) return; //Refresh is done on invoking function (status_calc_pc) - + if(flag&SCB_STR) clif_updatestatus(sd,SP_STR); if(flag&SCB_AGI) @@ -2859,7 +2858,7 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] status->amotion = cap_value(skill,battle_config.max_aspd,2000); status->adelay = 2*status->amotion; } - + if(flag&(SCB_AGI|SCB_DSPD)) { skill = 800-status->agi*4; status->dmotion = cap_value(skill, 400, 800); @@ -2868,7 +2867,7 @@ void status_calc_bl_sub_hom(struct homun_data *hd, unsigned long flag) //[orn] if(flag&(SCB_INT|SCB_MAXSP|SCB_VIT|SCB_MAXHP) && flag != SCB_ALL) status_calc_regen(&hd->bl, status, &hd->regen); - + if(flag&SCB_REGEN) status_calc_regen_rate(&hd->bl, &hd->regen, sc); @@ -2894,7 +2893,7 @@ void status_calc_bl(struct block_list *bl, unsigned long flag) b_status = status_get_base_status(bl); status = status_get_status_data(bl); sc = status_get_sc(bl); - + if (!b_status || !status) return; @@ -2905,12 +2904,12 @@ void status_calc_bl(struct block_list *bl, unsigned long flag) status_calc_pc(sd,0); return; } - + if((!bl->type&(BL_REGEN)) && (!sc || !sc->count)) { //No difference. status_cpy(status, b_status); return; } - + if(flag&SCB_STR) { status->str = status_calc_str(bl, sc, b_status->str); flag|=SCB_BATK; @@ -3113,7 +3112,7 @@ static unsigned short status_calc_str(struct block_list *bl, struct status_chang { if(!sc || !sc->count) return cap_value(str,1,USHRT_MAX); - + if(sc->data[SC_INCALLSTATUS].timer!=-1) str += sc->data[SC_INCALLSTATUS].val1; if(sc->data[SC_INCSTR].timer!=-1) @@ -3341,7 +3340,7 @@ static unsigned short status_calc_batk(struct block_list *bl, struct status_chan batk += batk * 3; if(sc->data[SC_BLOODLUST].timer!=-1) batk += batk * sc->data[SC_BLOODLUST].val2/100; - if(sc->data[SC_JOINTBEAT].timer!=-1 && sc->data[SC_JOINTBEAT].val2==4) + if(sc->data[SC_JOINTBEAT].timer!=-1 && sc->data[SC_JOINTBEAT].val2&BREAK_WAIST) batk -= batk * 25/100; if(sc->data[SC_CURSE].timer!=-1) batk -= batk * 25/100; @@ -3580,10 +3579,9 @@ static signed short status_calc_def2(struct block_list *bl, struct status_change if(sc->data[SC_PROVOKE].timer!=-1) def2 -= def2 * sc->data[SC_PROVOKE].val4/100; if(sc->data[SC_JOINTBEAT].timer!=-1){ - if(sc->data[SC_JOINTBEAT].val2==3) - def2 -= def2 * 50/100; - else if(sc->data[SC_JOINTBEAT].val2==4) - def2 -= def2 * 25/100; + def2 -= def2 * + ( ( sc->data[SC_JOINTBEAT].val2&BREAK_SHOULDER ? 50 : 0 ) + + ( sc->data[SC_JOINTBEAT].val2&BREAK_WAIST ? 25 : 0 ) ); } if(sc->data[SC_FLING].timer!=-1) def2 -= def2 * (sc->data[SC_FLING].val3)/100; @@ -3679,11 +3677,9 @@ static unsigned short status_calc_speed(struct block_list *bl, struct status_cha if(sc->data[SC_GOSPEL].timer!=-1 && sc->data[SC_GOSPEL].val4 == BCT_ENEMY) speed = speed * 100/75; if(sc->data[SC_JOINTBEAT].timer!=-1) { - if (sc->data[SC_JOINTBEAT].val2 == 0) - speed = speed * 100/50; - else - if (sc->data[SC_JOINTBEAT].val2 == 2) - speed = speed * 100/70; + speed = speed * ( 100 + - ( sc->data[SC_JOINTBEAT].val2&BREAK_ANKLE ? 50 : 0 ) + - ( sc->data[SC_JOINTBEAT].val2&BREAK_KNEE ? 30 : 0 )); } if(sc->data[SC_CLOAKING].timer!=-1) speed = speed * 100 /( @@ -3794,9 +3790,9 @@ static short status_calc_aspd_rate(struct block_list *bl, struct status_change * // if(sc->data[SC_BLEEDING].timer != -1) // aspd_rate += 250; if(sc->data[SC_JOINTBEAT].timer!=-1) { - if (sc->data[SC_JOINTBEAT].val2 == 1) + if( sc->data[SC_JOINTBEAT].val2&BREAK_WRIST ) aspd_rate += 250; - else if (sc->data[SC_JOINTBEAT].val2 == 2) + if( sc->data[SC_JOINTBEAT].val2&BREAK_KNEE ) aspd_rate += 100; } @@ -5250,9 +5246,10 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val val3 = 4*val2; //movement speed % increase is 4 times that break; - case SC_JOINTBEAT: // Random break [DracoRPG] - val2 = rand()%6; //Type of break -> [0,5] - if (val2 == 5) sc_start(bl,SC_BLEEDING,100,val1,skill_get_time2(StatusSkillChangeTable[type],val1)); + case SC_JOINTBEAT: + val2 |= sc->data[SC_JOINTBEAT].val2; // stackable ailments + if( val2&BREAK_NECK ) + sc_start(bl,SC_BLEEDING,100,val1,skill_get_time2(StatusSkillChangeTable[type],val1)); break; case SC_BERSERK: @@ -6309,6 +6306,9 @@ int status_change_end( struct block_list* bl , int type,int tid ) status_set_hp(bl, 10, 0); status_set_sp(bl, 10, 0); break; + case SC_JOINTBEAT: + sc->data[type].val2 = 0; // Clear stackable ailments + break; } opt_flag = 1; diff --git a/src/map/status.h b/src/map/status.h index 8f7a02916..84a231548 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -402,6 +402,15 @@ enum { SI_ACCURACY = 210 }; +// JOINTBEAT stackable ailments +#define BREAK_ANKLE 0x01 // MoveSpeed reduced by 50% +#define BREAK_WRIST 0x02 // ASPD reduced by 25% +#define BREAK_KNEE 0x04 // MoveSpeed reduced by 30%, ASPD reduced by 10% +#define BREAK_SHOULDER 0x08 // DEF reduced by 50% +#define BREAK_WAIST 0x10 // DEF reduced by 25%, ATK reduced by 25% +#define BREAK_NECK 0x20 // current attack does 2x damage, inflicts 'bleeding' for 30 seconds +#define BREAK_FLAGS ( BREAK_ANKLE | BREAK_WRIST | BREAK_KNEE | BREAK_SHOULDER | BREAK_WAIST | BREAK_NECK ) + extern int current_equip_item_index; extern int current_equip_card_id; @@ -611,6 +620,7 @@ int status_get_sc_def(struct block_list *bl, int type); //Short version, receives rate in 1->100 range, and does not uses a flag setting. #define sc_start(bl, type, rate, val1, tick) status_change_start(bl,type,100*(rate),val1,0,0,0,tick,0) +#define sc_start2(bl, type, rate, val1, val2, tick) status_change_start(bl,type,100*(rate),val1,val2,0,0,tick,0) #define sc_start4(bl, type, rate, val1, val2, val3, val4, tick) status_change_start(bl,type,100*(rate),val1,val2,val3,val4,tick,0) int status_change_start(struct block_list *bl,int type,int rate,int val1,int val2,int val3,int val4,int tick,int flag); |