From 356a83b11ae56778992b27b0c9b358d7d79722cd Mon Sep 17 00:00:00 2001 From: Michieru Date: Wed, 6 Aug 2014 15:07:26 +0100 Subject: - Fix 3rd class skills on pre-renewal. - When under Mind Break Matk Effect and Mdef reduction should not show on ALT Q(bug:7915) - Plagiarism should not copy New 3rd class skills. Thanks to OmegaRed (bug:8118) - Update Runstone Lux Anima to official formula (bug:8285) - Add official formula for Demonic Fire - Update damage formula for Unlimit, apply Def and Mdef to 1 during the skill and adjust the cooldown to official. (bug:8227) - Flash Combo should not consume hp-sp and the skill not ignore the distance. - Fix a bug with Full Throttle that not consuming sp correctly and adjust the cooldown to official. - All WoE items are inactive outside WoE or PVP - Add bonus3 bSPVanishRate for Vellum Items. - Script Vellum Items. - Add 2 new bonus bSetDefRace and bSetMDefRace for the Vellum Items. (rAthena c046668034) - Fixed Bowling Bash, Brandish Spear, Grand Darkness and Meteor Assault reducing def during cast; the only skill that does this officially is Grand Cross (rAthena 694719048e) - Implemented official Bowling Bash with all its special behaviors including the gutter line * As many servers probably want to remove the gutter line problem, it is configurable; just adjust the bowling_bash_area setting in skill.conf (Bug:4209) - Sonic Blow now has a fixed range of 1, even for monsters; a monster can't use this skill if you tank it from farther away (rAthena a15cee063d) --- src/map/battle.c | 39 ++++++++++-------- src/map/battle.h | 3 +- src/map/map.h | 1 + src/map/pc.c | 46 +++++++++++++++++---- src/map/pc.h | 6 ++- src/map/skill.c | 119 ++++++++++++++++++++++++++++++++++++++++--------------- src/map/skill.h | 1 + src/map/status.c | 50 +++++++++++++++-------- src/map/status.h | 4 ++ 9 files changed, 197 insertions(+), 72 deletions(-) (limited to 'src/map') diff --git a/src/map/battle.c b/src/map/battle.c index 7610d97b2..a83767728 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -1693,19 +1693,17 @@ int battle_calc_skillratio(int attack_type, struct block_list *src, struct block if( sc && sc->data[SC_CURSED_SOIL_OPTION] ) skillratio += sc->data[SC_CURSED_SOIL_OPTION]->val3; break; - case GN_DEMONIC_FIRE: - if( skill_lv > 20) - { // Fire expansion Lv.2 - skillratio += 110 + 20 * (skill_lv - 20) + status_get_int(src) * 3; // Need official INT bonus. [LimitLine] - } - else if( skill_lv > 10 ) - { // Fire expansion Lv.1 - skillratio += 110 + 20 * (skill_lv - 10) / 2; - } - else - skillratio += 110 + 20 * skill_lv; - break; - // Magical Elemental Spirits Attack Skills + case GN_DEMONIC_FIRE: { + int fire_expansion_lv = skill_lv / 100; + skill_lv = skill_lv % 100; + skillratio = 110 + 20 * skill_lv; + if ( fire_expansion_lv == 1 ) + skillratio += status_get_int(src) + (sd?sd->status.job_level:50); + else if ( fire_expansion_lv == 2 ) + skillratio += status_get_int(src) * 10; + } + break; + // Magical Elemental Spirits Attack Skills case EL_FIRE_MANTLE: case EL_WATER_SCREW: skillratio += 900; @@ -4651,7 +4649,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list case RA_WUGBITE: break; default: - ATK_ADD( 50 * sc->data[SC_UNLIMIT]->val1 ); + ATK_ADDRATE( 50 * sc->data[SC_UNLIMIT]->val1 ); } } @@ -5261,6 +5259,7 @@ struct Damage battle_calc_weapon_attack(struct block_list *src,struct block_list struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct block_list *target,uint16 skill_id,uint16 skill_lv,int count) { struct Damage d; + struct map_session_data *sd=BL_CAST(BL_PC,bl); switch(attack_type) { case BF_WEAPON: d = battle->calc_weapon_attack(bl,target,skill_id,skill_lv,count); break; case BF_MAGIC: d = battle->calc_magic_attack(bl,target,skill_id,skill_lv,count); break; @@ -5299,6 +5298,13 @@ struct Damage battle_calc_attack(int attack_type,struct block_list *bl,struct bl d.dmotion = 0; } else // Some skills like Weaponry Research will cause damage even if attack is dodged d.dmg_lv = ATK_DEF; + + if(sd && d.damage+d.damage2>1) { + if(sd->bonus.sp_vanish_rate && sd->bonus.sp_vanish_trigger && rnd()%10000bonus.sp_vanish_rate && + ( (d.flag&sd->bonus.sp_vanish_trigger&BF_WEAPONMASK) || (d.flag&sd->bonus.sp_vanish_trigger&BF_RANGEMASK) + || (d.flag&sd->bonus.sp_vanish_trigger&BF_SKILLMASK) )) + status_percent_damage(&sd->bl,target,0,-sd->bonus.sp_vanish_per,false); + } return d; } //Performs reflect damage (magic (maya) is performed over skill.c). @@ -5523,8 +5529,8 @@ void battle_drain(TBL_PC *sd, struct block_list *tbl, int64 rdamage, int64 ldama } } - if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate) - status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false); + if (sd->bonus.sp_vanish_rate && rnd()%1000 < sd->bonus.sp_vanish_rate && !sd->bonus.sp_vanish_trigger) + status_percent_damage(&sd->bl, tbl, 0, (unsigned char)sd->bonus.sp_vanish_per, false); if( sd->sp_gain_race_attack[race] ) tsp += sd->sp_gain_race_attack[race]; @@ -6728,6 +6734,7 @@ static const struct battle_data { { "homunculus_max_level", &battle_config.hom_max_level, 99, 0, MAX_LEVEL, }, { "homunculus_S_max_level", &battle_config.hom_S_max_level, 150, 0, MAX_LEVEL, }, { "mob_size_influence", &battle_config.mob_size_influence, 0, 0, 1, }, + { "bowling_bash_area", &battle_config.bowling_bash_area, 0, 0, 20, }, /** * Hercules **/ diff --git a/src/map/battle.h b/src/map/battle.h index aab94420a..71633372e 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -449,7 +449,8 @@ struct Battle_Config { int atcommand_mobinfo_type; int mob_size_influence; // Enable modifications on earned experience, drop rates and monster status depending on monster size. [mkbu95] - + int bowling_bash_area; + /** Hercules **/ int skill_trap_type; int item_restricted_consumption_type; diff --git a/src/map/map.h b/src/map/map.h index 4f7f09131..dba565cc0 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -409,6 +409,7 @@ enum status_point_types { SP_EMATK, SP_SP_GAIN_RACE_ATTACK, SP_HP_GAIN_RACE_ATTACK, SP_SKILL_USE_SP_RATE, //2046-2049 SP_SKILL_COOLDOWN,SP_SKILL_FIXEDCAST, SP_SKILL_VARIABLECAST, SP_FIXCASTRATE, SP_VARCASTRATE, //2050-2054 SP_SKILL_USE_SP,SP_MAGIC_ATK_ELE, SP_ADD_FIXEDCAST, SP_ADD_VARIABLECAST, //2055-2058 + SP_SET_DEF_RACE,SP_SET_MDEF_RACE, //2059-2060 /* must be the last, plugins add bonuses from this value onwards */ diff --git a/src/map/pc.c b/src/map/pc.c index 8b84ee3bc..58a066edf 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -2945,11 +2945,12 @@ int pc_bonus2(struct map_session_data *sd,int type,int type2,int val) sd->left_weapon.sp_drain[RC_BOSS].type = val; } break; - case SP_SP_VANISH_RATE: - if(sd->state.lr_flag != 2) { - sd->bonus.sp_vanish_rate += type2; - sd->bonus.sp_vanish_per += val; - } + case SP_SP_VANISH_RATE: + if(sd->state.lr_flag != 2) { + sd->bonus.sp_vanish_rate += type2; + sd->bonus.sp_vanish_per = max(sd->bonus.sp_vanish_per,val); + sd->bonus.sp_vanish_trigger=0; + } break; case SP_GET_ZENY_NUM: if(sd->state.lr_flag != 2 && sd->bonus.get_zeny_rate < val) { @@ -3434,6 +3435,13 @@ int pc_bonus3(struct map_session_data *sd,int type,int type2,int type3,int val) if (sd->state.lr_flag != 2) pc_bonus_subele(sd, (unsigned char)type2, type3, val); break; + case SP_SP_VANISH_RATE: + if(sd->state.lr_flag != 2) { + sd->bonus.sp_vanish_rate += type2; + sd->bonus.sp_vanish_per = max(sd->bonus.sp_vanish_per,type3); + sd->bonus.sp_vanish_trigger=val; + } + break; default: ShowWarning("pc_bonus3: unknown type %d %d %d %d!\n",type,type2,type3,val); @@ -3468,13 +3476,37 @@ int pc_bonus4(struct map_session_data *sd,int type,int type2,int type3,int type4 case SP_ADDEFF_ONSKILL: if( type2 > SC_MAX ) { - ShowWarning("pc_bonus3 (Add Effect on skill): %d is not supported.\n", type2); + ShowWarning("pc_bonus4 (Add Effect on skill): %d is not supported.\n", type2); break; } if( sd->state.lr_flag != 2 ) pc->bonus_addeff_onskill(sd->addeff3, ARRAYLENGTH(sd->addeff3), (sc_type)type3, type4, type2, val); break; + case SP_SET_DEF_RACE: //bonus4 bSetDefRace,n,x,r,y; + if( type2 > RC_MAX ) { + ShowWarning("pc_bonus4 (DEF_SET): %d is not supported.\n", type2); + break; + } + if(sd->state.lr_flag == 2) + break; + sd->def_set_race[type2].rate = type3; + sd->def_set_race[type2].tick = type4; + sd->def_set_race[type2].value = val; + break; + + case SP_SET_MDEF_RACE: //bonus4 bSetMDefRace,n,x,r,y; + if( type2 > RC_MAX ) { + ShowWarning("pc_bonus4 (MDEF_SET): %d is not supported.\n", type2); + break; + } + if(sd->state.lr_flag == 2) + break; + sd->mdef_set_race[type2].rate = type3; + sd->mdef_set_race[type2].tick = type4; + sd->mdef_set_race[type2].value = val; + break; + default: ShowWarning("pc_bonus4: unknown type %d %d %d %d %d!\n",type,type2,type3,type4,val); break; @@ -9519,7 +9551,7 @@ int map_night_timer(int tid, int64 tick, int id, intptr_t data) { void pc_setstand(struct map_session_data *sd) { nullpo_retv(sd); - + status_change_end(&sd->bl, SC_TENSIONRELAX, INVALID_TIMER); clif->sc_end(&sd->bl,sd->bl.id,SELF,SI_SIT); //Reset sitting tick. diff --git a/src/map/pc.h b/src/map/pc.h index fcd6f39d0..aa92baf17 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -311,6 +311,10 @@ struct map_session_data { short flag, rate; unsigned char ele; } subele2[MAX_PC_BONUS]; + struct { + short value; + int rate, tick; + } def_set_race[RC_MAX], mdef_set_race[RC_MAX]; // zeroed structures end here // manually zeroed structures start here. struct s_autobonus autobonus[MAX_PC_BONUS], autobonus2[MAX_PC_BONUS], autobonus3[MAX_PC_BONUS]; //Auto script on attack, when attacked, on skill usage @@ -344,7 +348,7 @@ struct map_session_data { short add_heal_rate, add_heal2_rate; short sp_gain_value, hp_gain_value, magic_sp_gain_value, magic_hp_gain_value; short sp_vanish_rate; - short sp_vanish_per; + short sp_vanish_per, sp_vanish_trigger; unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest] unsigned short unbreakable_equip; //100% break resistance on certain equipment unsigned short unstripable_equip; diff --git a/src/map/skill.c b/src/map/skill.c index e16cb0cc7..e31e8f61e 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -439,6 +439,10 @@ int can_copy (struct map_session_data *sd, uint16 skill_id, struct block_list* b else if( sd->sc.data[SC__REPRODUCE] && !skill->reproduce_db[skill->get_index(skill_id)] ) return 0; + //Never copy new 3rd class skills By OmegaRed + if(skill_id >= GC_DARKCROW && skill_id <= ALL_FULL_THROTTLE) + return 0; + return 1; } @@ -1384,6 +1388,14 @@ int skill_additional_effect(struct block_list* src, struct block_list *bl, uint1 if( rate ) skill->break_equip(bl, EQP_ARMOR, rate, BCT_ENEMY); } + if (sd && !skill_id && bl->type == BL_PC) { // This effect does not work with skills. + if (sd->def_set_race[tstatus->race].rate) + status->change_start(src,bl, SC_DEFSET, sd->def_set_race[tstatus->race].rate, sd->def_set_race[tstatus->race].value, + 0, 0, 0, sd->def_set_race[tstatus->race].tick, 2); + if (sd->def_set_race[tstatus->race].rate) + status->change_start(src,bl, SC_MDEFSET, sd->mdef_set_race[tstatus->race].rate, sd->mdef_set_race[tstatus->race].value, + 0, 0, 0, sd->mdef_set_race[tstatus->race].tick, 2); + } } if( sd && sd->ed && sc && !status->isdead(bl) && !skill_id ) { @@ -3225,10 +3237,9 @@ int skill_timerskill(int tid, int64 tick, int id, intptr_t data) { struct map_session_data *sd = NULL; if( src->type == BL_PC && (sd = ((TBL_PC*)src)) ) { - if( distance_xy(src->x, src->y, target->x, target->y) >= 3 ) // FIXME: Don't combos ignore distance? [Panikon] + if( distance_xy(src->x, src->y, target->x, target->y) >= 3 ) break; - skill->consume_requirement(sd, skl->skill_id, pc->checkskill(sd, skl->skill_id),1); skill->castend_damage_id(src, target, skl->skill_id, pc->checkskill(sd, skl->skill_id), tick, 0); } break; @@ -3847,33 +3858,78 @@ int skill_castend_damage_id(struct block_list* src, struct block_list *bl, uint1 skill->attack(skill->get_type(skill_id), src, src, bl, skill_id, skill_lv, tick, flag); break; - case KN_BOWLINGBASH: - case MS_BOWLINGBASH: - if(flag&1){ - if(bl->id==skill->area_temp[1]) - break; - //two hits for 500% - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,SD_ANIMATION); - } else { - int i,c; - c = skill->get_blewcount(skill_id,skill_lv); - // keep moving target in the direction that src is looking, square by square - for(i=0;iblown(src,bl,1,(unit->getdir(src)+4)%8,0x1)) - break; //Can't knockback - skill->area_temp[0] = map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), BL_CHAR, src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count); - if( skill->area_temp[0] > 1 ) break; // collision - } - clif->blown(bl); //Update target pos. - if (i!=c) { //Splash - skill->area_temp[1] = bl->id; - map->foreachinrange(skill->area_sub, bl, skill->get_splash(skill_id, skill_lv), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY|1, skill->castend_damage_id); - } - //Weirdo dual-hit property, two attacks for 500% - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); - skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,0); - } + case KN_BOWLINGBASH: + case MS_BOWLINGBASH: + { + int min_x,max_x,min_y,max_y,i,c,dir,tx,ty; + // Chain effect and check range gets reduction by recursive depth, as this can reach 0, we don't use blowcount + c = (skill_lv-(flag&0xFFF)+1)/2; + // Determine the Bowling Bash area depending on configuration + if (battle_config.bowling_bash_area == 0) { + // Gutter line system + min_x = ((src->x)-c) - ((src->x)-c)%40; + if(min_x < 0) min_x = 0; + max_x = min_x + 39; + min_y = ((src->y)-c) - ((src->y)-c)%40; + if(min_y < 0) min_y = 0; + max_y = min_y + 39; + } else if (battle_config.bowling_bash_area == 1) { + // Gutter line system without demi gutter bug + min_x = src->x - (src->x)%40; + max_x = min_x + 39; + min_y = src->y - (src->y)%40; + max_y = min_y + 39; + } else { + // Area around caster + min_x = src->x - battle_config.bowling_bash_area; + max_x = src->x + battle_config.bowling_bash_area; + min_y = src->y - battle_config.bowling_bash_area; + max_y = src->y + battle_config.bowling_bash_area; + } + // Initialization, break checks, direction + if((flag&0xFFF) > 0) { + // Ignore monsters outside area + if(bl->x < min_x || bl->x > max_x || bl->y < min_y || bl->y > max_y) + break; + // Ignore monsters already in list + if(idb_exists(skill->bowling_db, bl->id)) + break; + // Random direction + dir = rnd()%8; + } else { + // Create an empty list of already hit targets + db_clear(skill->bowling_db); + // Direction is walkpath + dir = (unit->getdir(src)+4)%8; + } + // Add current target to the list of already hit targets + idb_put(skill->bowling_db, bl->id, bl); + // Keep moving target in direction square by square + tx = bl->x; + ty = bl->y; + for(i=0;igetcell(bl->m,tx,ty,CELL_CHKWALL)) + break; + skill_blown(src,bl,1,dir,0); + // Splash around target cell, but only cells inside area; we first have to check the area is not negative + if((max(min_x,tx-1) <= min(max_x,tx+1)) && + (max(min_y,ty-1) <= min(max_y,ty+1)) && + (map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, flag|BCT_ENEMY, skill->area_sub_count))) { + // Recursive call + map->foreachinarea(skill->area_sub, bl->m, max(min_x,tx-1), max(min_y,ty-1), min(max_x,tx+1), min(max_y,ty+1), splash_target(src), src, skill_id, skill_lv, tick, (flag|BCT_ENEMY)+1, skill->castend_damage_id); + // Self-collision + if(bl->x >= min_x && bl->x <= max_x && bl->y >= min_y && bl->y <= max_y) + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0); + break; + } + } + // Original hit or chain hit depending on flag + skill->attack(BF_WEAPON,src,src,bl,skill_id,skill_lv,tick,(flag&0xFFF)>0?SD_ANIMATION:0); + } break; case KN_SPEARSTAB: @@ -18442,7 +18498,7 @@ int do_init_skill(bool minimal) { skill->unit_db = idb_alloc(DB_OPT_BASE); skill->cd_db = idb_alloc(DB_OPT_BASE); skill->usave_db = idb_alloc(DB_OPT_RELEASE_DATA); - + skill->bowling_db = idb_alloc(DB_OPT_BASE); skill->unit_ers = ers_new(sizeof(struct skill_unit_group),"skill.c::skill_unit_ers",ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); skill->timer_ers = ers_new(sizeof(struct skill_timerskill),"skill.c::skill_timer_ers",ERS_OPT_NONE|ERS_OPT_FLEX_CHUNK); skill->cd_ers = ers_new(sizeof(struct skill_cd),"skill.c::skill_cd_ers",ERS_OPT_CLEAR|ERS_OPT_CLEAN|ERS_OPT_FLEX_CHUNK); @@ -18471,7 +18527,7 @@ int do_final_skill(void) { db_destroy(skill->unit_db); db_destroy(skill->cd_db); db_destroy(skill->usave_db); - + db_destroy(skill->bowling_db); ers_destroy(skill->unit_ers); ers_destroy(skill->timer_ers); ers_destroy(skill->cd_ers); @@ -18493,6 +18549,7 @@ void skill_defaults(void) { skill->name2id_db = NULL; skill->unit_db = NULL; skill->usave_db = NULL; + skill->bowling_db = NULL; skill->group_db = NULL; /* */ skill->unit_ers = NULL; diff --git a/src/map/skill.h b/src/map/skill.h index 352e31f9e..6373d9275 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -1825,6 +1825,7 @@ struct skill_interface { DBMap* unit_db; // int id -> struct skill_unit* DBMap* usave_db; // char_id -> struct skill_unit_save DBMap* group_db;// int group_id -> struct skill_unit_group* + DBMap* bowling_db;// int mob_id -> struct mob_data*s /* */ struct eri *unit_ers; //For handling skill_unit's [Skotlex] struct eri *timer_ers; //For handling skill_timerskills [Skotlex] diff --git a/src/map/status.c b/src/map/status.c index 30bedf565..df0f65fd7 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -586,7 +586,7 @@ void initChangeTables(void) { add_sc( RA_VERDURETRAP , SC_ARMOR_PROPERTY ); add_sc( RA_FIRINGTRAP , SC_BURNING ); add_sc( RA_ICEBOUNDTRAP , SC_FROSTMISTY ); - set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_NONE ); + set_sc( RA_UNLIMIT , SC_UNLIMIT , SI_UNLIMIT , SCB_DEF|SCB_DEF2|SCB_MDEF|SCB_MDEF2 ); /** * Mechanic **/ @@ -1002,6 +1002,8 @@ void initChangeTables(void) { status->ChangeFlagTable[SC_VITATA_500] |= SCB_REGEN; status->ChangeFlagTable[SC_EXTRACT_SALAMINE_JUICE] |= SCB_ASPD; status->ChangeFlagTable[SC_REBOUND] |= SCB_SPEED|SCB_REGEN; + status->ChangeFlagTable[SC_DEFSET] |= SCB_DEF|SCB_DEF2; + status->ChangeFlagTable[SC_MDEFSET] |= SCB_MDEF|SCB_MDEF2; status->ChangeFlagTable[SC_ALL_RIDING] = SCB_SPEED; status->ChangeFlagTable[SC_WEDDING] = SCB_SPEED; @@ -2514,6 +2516,8 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt) { + sizeof(sd->skillfixcast) + sizeof(sd->skillvarcast) + sizeof(sd->skillfixcastrate) + + sizeof(sd->def_set_race) + + sizeof(sd->mdef_set_race) ); memset (&sd->bonus, 0,sizeof(sd->bonus)); @@ -4686,6 +4690,8 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, if( !viewable ){ /* some statuses that are hidden in the status window */ + if (sc->data[SC_MINDBREAKER]) + matk += matk * sc->data[SC_MINDBREAKER]->val2/100; return (unsigned short)cap_value(matk,0,USHRT_MAX); } @@ -4716,8 +4722,6 @@ unsigned short status_calc_matk(struct block_list *bl, struct status_change *sc, matk += sc->data[SC_ZANGETSU]->val3; if (sc->data[SC_MAGICPOWER] && sc->data[SC_MAGICPOWER]->val4) matk += matk * sc->data[SC_MAGICPOWER]->val3/100; - if (sc->data[SC_MINDBREAKER]) - matk += matk * sc->data[SC_MINDBREAKER]->val2/100; if (sc->data[SC_INCMATKRATE]) matk += matk * sc->data[SC_INCMATKRATE]->val1/100; if (sc->data[SC_MOONLIT_SERENADE]) @@ -4933,6 +4937,8 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def def += 2 * sc->data[SC_GENTLETOUCH_REVITALIZE]->val4; if( sc->data[SC_FORCEOFVANGUARD] ) def += def * 2 * sc->data[SC_FORCEOFVANGUARD]->val1 / 100; + if(sc->data[SC_DEFSET]) + return sc->data[SC_DEFSET]->val1; return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); } @@ -5007,6 +5013,8 @@ defType status_calc_def(struct block_list *bl, struct status_change *sc, int def if(status_get_race(bl)==RC_PLANT) def /= 2; } + if(sc->data[SC_UNLIMIT]) + return 1; return (defType)cap_value(def,DEFTYPE_MIN,DEFTYPE_MAX); } @@ -5028,6 +5036,8 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i #endif if( sc && sc->data[SC_CAMOUFLAGE] ) def2 -= def2 * 5 * (10-sc->data[SC_CAMOUFLAGE]->val4) / 100; + if(sc->data[SC_DEFSET]) + return sc->data[SC_DEFSET]->val1; #ifdef RENEWAL return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); #else @@ -5074,7 +5084,8 @@ signed short status_calc_def2(struct block_list *bl, struct status_change *sc, i } if (sc->data[SC_NEEDLE_OF_PARALYZE]) def2 -= def2 * sc->data[SC_NEEDLE_OF_PARALYZE]->val2 / 100; - + if (sc->data[SC_UNLIMIT]) + return 1; #ifdef RENEWAL return (short)cap_value(def2,SHRT_MIN,SHRT_MAX); #else @@ -5090,6 +5101,8 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md if( !viewable ){ /* some statuses that are hidden in the status window */ + if(sc->data[SC_MDEFSET]) + return sc->data[SC_MDEFSET]->val1; return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); } @@ -5129,6 +5142,8 @@ defType status_calc_mdef(struct block_list *bl, struct status_change *sc, int md mdef -= 20; if(sc->data[SC_BURNING]) mdef -= mdef *25 / 100; + if (sc->data[SC_UNLIMIT]) + return 1; return (defType)cap_value(mdef,DEFTYPE_MIN,DEFTYPE_MAX); } @@ -5144,6 +5159,10 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, if( !viewable ){ /* some statuses that are hidden in the status window */ + if(sc->data[SC_MDEFSET]) + return sc->data[SC_MDEFSET]->val1; + if(sc->data[SC_MINDBREAKER]) + mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; #ifdef RENEWAL if(sc && sc->data[SC_ASSUMPTIO]) mdef2 <<= 1; @@ -5157,11 +5176,10 @@ signed short status_calc_mdef2(struct block_list *bl, struct status_change *sc, return 0; if(sc->data[SC_SKA]) return 90; - if(sc->data[SC_MINDBREAKER]) - mdef2 -= mdef2 * sc->data[SC_MINDBREAKER]->val3/100; if(sc->data[SC_ANALYZE]) mdef2 -= mdef2 * ( 14 * sc->data[SC_ANALYZE]->val1 ) / 100; - + if (sc->data[SC_UNLIMIT]) + return 1; #ifdef RENEWAL return (short)cap_value(mdef2,SHRT_MIN,SHRT_MAX); #else @@ -8983,11 +9001,11 @@ int status_change_start(struct block_list *src, struct block_list *bl, enum sc_t if(val2 == MH_MD_FIGHTING) val2 = MH_MD_GRAPPLING; else val2 = MH_MD_FIGHTING; break; - case SC_FULL_THROTTLE: + case SC_FULL_THROTTLE: status_percent_heal(bl,100,0); val2 = 7 - val1; - tick_time = 1000; - val4 = tick / tick_time; + tick_time = 1000; + val4 = tick / tick_time; break; case SC_KINGS_GRACE: val2 = 3 + val1; @@ -11235,12 +11253,12 @@ int status_change_timer(int tid, int64 tick, int id, intptr_t data) { return 0; } break; - case SC_FULL_THROTTLE: - if( --(sce->val4) > 0 ) { - status_percent_damage(bl, bl, sce->val2, 0, false); - sc_timer_next(1000 + tick, status->change_timer, bl->id, data); - return 0; - } + case SC_FULL_THROTTLE: + if( --(sce->val4) >= 0 ) { + status_percent_damage(bl, bl, 0, sce->val2, false); + sc_timer_next(1000 + tick, status->change_timer, bl->id, data); + return 0; + } break; case SC_KINGS_GRACE: if( --(sce->val4) > 0 ) { diff --git a/src/map/status.h b/src/map/status.h index 599f36c73..c90efd2e0 100644 --- a/src/map/status.h +++ b/src/map/status.h @@ -715,6 +715,10 @@ typedef enum sc_type { SC_FALLENEMPIRE, SC_FLASHCOMBO, + //Vellum Weapon reductions + SC_DEFSET, + SC_MDEFSET, + SC_MAX, //Automatically updated max, used in for's to check we are within bounds. } sc_type; -- cgit v1.2.3-70-g09d2