summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMichieru <Michieru@users.noreply.github.com>2014-08-06 15:07:26 +0100
committerMichieru <Michieru@users.noreply.github.com>2014-08-06 15:07:26 +0100
commit356a83b11ae56778992b27b0c9b358d7d79722cd (patch)
treef113b57f6276ff0ed4c26c9042b7e41c11382e51 /src
parent254f47e4f04141f6ceeb68d0dbbb4a0001d01a24 (diff)
downloadhercules-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.c39
-rw-r--r--src/map/battle.h3
-rw-r--r--src/map/map.h1
-rw-r--r--src/map/pc.c46
-rw-r--r--src/map/pc.h6
-rw-r--r--src/map/skill.c119
-rw-r--r--src/map/skill.h1
-rw-r--r--src/map/status.c50
-rw-r--r--src/map/status.h4
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;