diff options
author | Michieru <Michieru@users.noreply.github.com> | 2014-08-06 15:07:26 +0100 |
---|---|---|
committer | Michieru <Michieru@users.noreply.github.com> | 2014-08-06 15:07:26 +0100 |
commit | 356a83b11ae56778992b27b0c9b358d7d79722cd (patch) | |
tree | f113b57f6276ff0ed4c26c9042b7e41c11382e51 /src | |
parent | 254f47e4f04141f6ceeb68d0dbbb4a0001d01a24 (diff) | |
download | hercules-356a83b11ae56778992b27b0c9b358d7d79722cd.tar.gz hercules-356a83b11ae56778992b27b0c9b358d7d79722cd.tar.bz2 hercules-356a83b11ae56778992b27b0c9b358d7d79722cd.tar.xz hercules-356a83b11ae56778992b27b0c9b358d7d79722cd.zip |
- 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)
Diffstat (limited to 'src')
-rw-r--r-- | src/map/battle.c | 39 | ||||
-rw-r--r-- | src/map/battle.h | 3 | ||||
-rw-r--r-- | src/map/map.h | 1 | ||||
-rw-r--r-- | src/map/pc.c | 46 | ||||
-rw-r--r-- | src/map/pc.h | 6 | ||||
-rw-r--r-- | src/map/skill.c | 119 | ||||
-rw-r--r-- | src/map/skill.h | 1 | ||||
-rw-r--r-- | src/map/status.c | 50 | ||||
-rw-r--r-- | src/map/status.h | 4 |
9 files changed, 197 insertions, 72 deletions
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()%10000<sd->bonus.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;i<c;i++){ - if (!skill->blown(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;i<c;i++) {
+ // Target coordinates (get changed even if knockback fails)
+ tx -= dirx[dir];
+ ty -= diry[dir];
+ // If target cell is a wall then break
+ if(map->getcell(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; |