Merge pull request #136 from rathena/cleanup/renewal_cast

Clean up something RENEWAL_CAST
* Moved additive bonuses (reducing/increasing) to first calculation before the rate adjustment
* Corrected `bonus(2) bFixedCastrate` shouldn't be stacked. Example between Puente_Robe (15012) is -3% and +10 Rafini_Staff (1649) is -10%, only -10% will be used not -13%.
* Reversed some value assignment, `-=` to `+=` and other part that affected by this change.
* Also as follow up c3e488e & 4f4d8fe, fixed `bonus2 bFixedCastrate,"sk",rate;` algorithm
* Corrected `bFixedCastrate` for Krieger_Knuckle2 (1827) only for skill `MO_EXTREMITYFIST`
* Moved default the 20% of fixed cast rate to conf/battle/skill.conf `default_fixed_castrate`
This commit is contained in:
Cydh Ramdh 2014-12-08 13:04:26 +07:00
commit d3704d50dd
12 changed files with 230 additions and 182 deletions

View File

@ -330,3 +330,9 @@ arrow_shower_knockback: yes
// punch a hole into SG it will for example create a "suck in" effect.
// If you disable this setting, the knockback direction will be completely random (eAthena style).
stormgust_knockback: yes
// For RENEWAL_CAST (Note 2)
// By default skill that has '0' value for Fixed Casting Time will use 20% of cast time
// as Fixed Casting Time, and the rest (80%) as Variable Casting Time.
// Put it 0 to disable default Fixed Casting Time (just like -1 is the skill_cast_db.txt).
default_fixed_castrate: 20

View File

@ -1078,7 +1078,7 @@
1824,BF_Knuckle2,Brave Battle Fist,5,20,,0,30,,1,0,0x00008100,63,2,2,3,80,1,12,{ bonus bStr,2; bonus bInt,1; bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bVariableCastrate,"MO_EXTREMITYFIST",-25; autobonus "{ bonus2 bVariableCastrate,\"MO_EXTREMITYFIST\",-100; }",50,6000,BF_WEAPON,"{ specialeffect2 EF_SUFFRAGIUM; }"; bonus bUnbreakableWeapon,0; },{},{}
1825,Horn_Of_Hilthrion,Horn of Hillslion,5,20,,600,95,,1,3,0x00008000,18,2,2,3,60,1,12,{ bonus3 bAutoSpell,"NPC_CRITICALWOUND",1,100; bonus4 bAutoSpellOnSkill,"CH_PALMSTRIKE","MO_INVESTIGATE",1,100; bonus3 bAutoSpell,"MO_CALLSPIRITS",5,100; },{},{}
1826,Krieger_Knuckle1,Glorious Claw,5,20,,0,30,,1,0,0x00008100,63,2,2,4,80,1,12,{ bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bIgnoreDefRaceRate,RC_DemiHuman,20; bonus2 bIgnoreDefRaceRate,RC_Player,20; bonus bUnbreakableWeapon,0; if(getrefine()>5) { bonus2 bAddRace,RC_DemiHuman,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bAddRace,RC_Player,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bIgnoreDefRaceRate,RC_DemiHuman,5; bonus2 bIgnoreDefRaceRate,RC_Player,5; } if(getrefine()>8) { bonus3 bAutoSpell,"MO_INVESTIGATE",5,(getrefine()*10-50); bonus3 bAutoSpell,"AL_DECAGI",1,(getrefine()*10-50); } },{},{}
1827,Krieger_Knuckle2,Glorious Fist,5,20,,0,30,,1,0,0x00008100,63,2,2,4,80,1,12,{ bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bIgnoreDefRaceRate,RC_DemiHuman,20; bonus2 bIgnoreDefRaceRate,RC_Player,20; bonus bUnbreakableWeapon,0; if(getrefine()>5) { bonus2 bAddRace,RC_DemiHuman,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bAddRace,RC_Player,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bIgnoreDefRaceRate,RC_DemiHuman,5; bonus2 bIgnoreDefRaceRate,RC_Player,5; } if(getrefine()>8) { bonus2 bVariableCastrate,"MO_EXTREMITYFIST",-100; bonus4 bautospellonskill,"MO_EXPLOSIONSPIRITS","CH_SOULCOLLECT",1,1000; bonus bFixedCastrate,-100; } },{},{}
1827,Krieger_Knuckle2,Glorious Fist,5,20,,0,30,,1,0,0x00008100,63,2,2,4,80,1,12,{ bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bIgnoreDefRaceRate,RC_DemiHuman,20; bonus2 bIgnoreDefRaceRate,RC_Player,20; bonus bUnbreakableWeapon,0; if(getrefine()>5) { bonus2 bAddRace,RC_DemiHuman,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bAddRace,RC_Player,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bIgnoreDefRaceRate,RC_DemiHuman,5; bonus2 bIgnoreDefRaceRate,RC_Player,5; } if(getrefine()>8) { bonus2 bVariableCastrate,"MO_EXTREMITYFIST",-100; bonus2 bFixedCastrate,"MO_EXTREMITYFIST",-100; bonus4 bautospellonskill,"MO_EXPLOSIONSPIRITS","CH_SOULCOLLECT",1,1000; } },{},{}
1828,Monk_Knuckle,Monk Knuckle,5,20,,0,150,,1,0,0x00008100,63,2,2,4,0,0,12,{ bonus bInt,2; bonus2 bSkillAtk,"MO_FINGEROFFENSIVE",25; },{},{}
1829,Fist_C,Fist,5,0,,0,150,,1,0,0x00008100,63,2,2,3,1,0,12,{ bonus2 bAddSize,Size_All,40; },{},{}
1830,Sura_Rampage,Sura Rampage,5,20,,500,142,,1,1,0x00008100,63,2,2,3,102,1,12,{ bonus2 bSkillAtk,"SR_EARTHSHAKER",20; bonus2 bSkillAtk,"SR_SKYNETBLOW",20; bonus bUseSPrate,5; if(getrefine()>6) { bonus bUseSPrate,-1*(getrefine()-6); } },{},{}

View File

@ -174,16 +174,18 @@ bonus2 bAddItemGroupHealRate,ig,n; Increases HP recovered by n% for items of ite
Cast time/delay
---------------
bonus bCastrate,n; Skill cast time rate + n%
bonus2 bCastrate,sk,n; Adjust casting time of skill sk by n%
bonus bFixedCastrate,n; Increases fixed cast time of all skills by n%
bonus2 bFixedCastrate,sk,n; Increases fixed cast time of skill sk by n%
bonus bVariableCastrate,n; Increases variable cast time of all skills by n%
bonus2 bVariableCastrate,sk,n; Increases variable cast time of skill sk by n%
bonus bFixedCast,t; Increases fixed cast time of all skills by t milliseconds
bonus2 bSkillFixedCast,sk,t; Increases fixed cast time of skill sk by t milliseconds
bonus bVariableCast,t; Increases variable cast time of all skills by t milliseconds
bonus2 bSkillVariableCast,sk,t; Increases variable cast time of skill sk by t milliseconds
bonus bCastrate,n; Skill cast time rate + n%. (If RENEWAL_CAST is defined, this bonus is equal to bVariableCastrate)
bonus2 bCastrate,sk,n; Adjust casting time of skill sk by n%.(If RENEWAL_CAST is defined, this bonus is equal to bVariableCastrate)
bonus bFixedCastrate,n; Increases fixed cast time of all skills by n% (has effect in RENEWAL_CAST only)
bonus2 bFixedCastrate,sk,n; Increases fixed cast time of skill sk by n% (has effect in RENEWAL_CAST only)
bonus bVariableCastrate,n; Increases variable cast time of all skills by n%. (If RENEWAL_CAST is NOT defined, this bonus is equal to bCastrate)
bonus2 bVariableCastrate,sk,n; Increases variable cast time of skill sk by n% (If RENEWAL_CAST is NOT defined, this bonus is equal to bCastrate)
bonus bFixedCast,t; Increases fixed cast time of all skills by t milliseconds (has effect in RENEWAL_CAST only)
bonus2 bSkillFixedCast,sk,t; Increases fixed cast time of skill sk by t milliseconds (has effect in RENEWAL_CAST only)
bonus bVariableCast,t; Increases variable cast time of all skills by t milliseconds (has effect in RENEWAL_CAST only)
bonus2 bSkillVariableCast,sk,t; Increases variable cast time of skill sk by t milliseconds (has effect in RENEWAL_CAST only)
bonus bNoCastCancel,n; Prevents casting from being interrupted when hit (does not work in GvG | n is meaningless)
bonus bNoCastCancel2,n; Prevents casting from being interrupted when hit (works even in GvG | n is meaningless)

View File

@ -1109,7 +1109,7 @@ REPLACE INTO `item_db_re` VALUES (1823,'BF_Knuckle1','Valorous Battle Fist',5,20
REPLACE INTO `item_db_re` VALUES (1824,'BF_Knuckle2','Brave Battle Fist',5,20,NULL,0,'30',NULL,1,0,0x00008100,63,2,2,3,'80',1,12,'bonus bStr,2; bonus bInt,1; bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bVariableCastrate,"MO_EXTREMITYFIST",-25; autobonus "{ bonus2 bVariableCastrate,\\\"MO_EXTREMITYFIST\\\",-100; }",50,6000,BF_WEAPON,"{ specialeffect2 EF_SUFFRAGIUM; }"; bonus bUnbreakableWeapon,0;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (1825,'Horn_Of_Hilthrion','Horn of Hillslion',5,20,NULL,600,'95',NULL,1,3,0x00008000,18,2,2,3,'60',1,12,'bonus3 bAutoSpell,"NPC_CRITICALWOUND",1,100; bonus4 bAutoSpellOnSkill,"CH_PALMSTRIKE","MO_INVESTIGATE",1,100; bonus3 bAutoSpell,"MO_CALLSPIRITS",5,100;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (1826,'Krieger_Knuckle1','Glorious Claw',5,20,NULL,0,'30',NULL,1,0,0x00008100,63,2,2,4,'80',1,12,'bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bIgnoreDefRaceRate,RC_DemiHuman,20; bonus2 bIgnoreDefRaceRate,RC_Player,20; bonus bUnbreakableWeapon,0; if(getrefine()>5) { bonus2 bAddRace,RC_DemiHuman,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bAddRace,RC_Player,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bIgnoreDefRaceRate,RC_DemiHuman,5; bonus2 bIgnoreDefRaceRate,RC_Player,5; } if(getrefine()>8) { bonus3 bAutoSpell,"MO_INVESTIGATE",5,(getrefine()*10-50); bonus3 bAutoSpell,"AL_DECAGI",1,(getrefine()*10-50); }',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (1827,'Krieger_Knuckle2','Glorious Fist',5,20,NULL,0,'30',NULL,1,0,0x00008100,63,2,2,4,'80',1,12,'bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bIgnoreDefRaceRate,RC_DemiHuman,20; bonus2 bIgnoreDefRaceRate,RC_Player,20; bonus bUnbreakableWeapon,0; if(getrefine()>5) { bonus2 bAddRace,RC_DemiHuman,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bAddRace,RC_Player,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bIgnoreDefRaceRate,RC_DemiHuman,5; bonus2 bIgnoreDefRaceRate,RC_Player,5; } if(getrefine()>8) { bonus2 bVariableCastrate,"MO_EXTREMITYFIST",-100; bonus4 bautospellonskill,"MO_EXPLOSIONSPIRITS","CH_SOULCOLLECT",1,1000; bonus bFixedCastrate,-100; }',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (1827,'Krieger_Knuckle2','Glorious Fist',5,20,NULL,0,'30',NULL,1,0,0x00008100,63,2,2,4,'80',1,12,'bonus2 bAddRace,RC_DemiHuman,95; bonus2 bAddRace,RC_Player,95; bonus2 bIgnoreDefRaceRate,RC_DemiHuman,20; bonus2 bIgnoreDefRaceRate,RC_Player,20; bonus bUnbreakableWeapon,0; if(getrefine()>5) { bonus2 bAddRace,RC_DemiHuman,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bAddRace,RC_Player,pow(((getrefine()>14)?14:getrefine())-4,2); bonus2 bIgnoreDefRaceRate,RC_DemiHuman,5; bonus2 bIgnoreDefRaceRate,RC_Player,5; } if(getrefine()>8) { bonus2 bVariableCastrate,"MO_EXTREMITYFIST",-100; bonus2 bFixedCastrate,"MO_EXTREMITYFIST",-100; bonus4 bautospellonskill,"MO_EXPLOSIONSPIRITS","CH_SOULCOLLECT",1,1000; }',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (1828,'Monk_Knuckle','Monk Knuckle',5,20,NULL,0,'150',NULL,1,0,0x00008100,63,2,2,4,'0',0,12,'bonus bInt,2; bonus2 bSkillAtk,"MO_FINGEROFFENSIVE",25;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (1829,'Fist_C','Fist',5,0,NULL,0,'150',NULL,1,0,0x00008100,63,2,2,3,'1',0,12,'bonus2 bAddSize,Size_All,40;',NULL,NULL);
REPLACE INTO `item_db_re` VALUES (1830,'Sura_Rampage','Sura Rampage',5,20,NULL,500,'142',NULL,1,1,0x00008100,63,2,2,3,'102',1,12,'bonus2 bSkillAtk,"SR_EARTHSHAKER",20; bonus2 bSkillAtk,"SR_SKYNETBLOW",20; bonus bUseSPrate,5; if(getrefine()>6) { bonus bUseSPrate,-1*(getrefine()-6); }',NULL,NULL);

View File

@ -99,10 +99,12 @@
// Renewal variable cast time reduction
#ifdef RENEWAL_CAST
#define VARCAST_REDUCTION(val){ \
if( (varcast_r += (val)) != 0 && varcast_r >= 0 ) \
time = time * (1 - (float)min((val), 100) / 100); \
}
// Multiply the Variable CastTime
#define VARCAST_REDUCTION(val) ( time = time * (1 + (val) * 0.01) )
// Get the highest rate TO REDUCE Fixed CastTime
// -100 is "the highest" rate than 100.
#define FIXEDCASTRATE(fcast,val) ( ((fcast) == 0) ? ((fcast) = (val)) : ((fcast) = min((fcast),(val))) )
#endif
/**
* End of File

View File

@ -16,57 +16,60 @@
* @INFO: This file holds general-purpose renewal settings, for class-specific ones check /src/config/classes folder
**/
/// game renewal server mode
/// Game renewal server mode
/// (disable by commenting the line)
///
/// leave this line to enable renewal specific support such as renewal formulas
/// Leave this line to enable renewal specific support such as renewal formulas
#define RENEWAL
/// renewal cast time
/// Renewal cast time
/// (disable by commenting the line)
///
/// leave this line to enable renewal casting time algorithms
/// cast time is decreased by DEX * 2 + INT while 20% of the cast time is not reduced by stats.
/// example:
/// on a skill whos cast time is 10s, only 8s may be reduced. the other 2s are part of a
/// "fixed cast time" which can only be reduced by specialist items and skills
/// Leave this line to enable renewal casting time algorithms and enable fixed cast bonuses.
/// See also default_fixed_castrate in conf/battle/skill.conf for default fixed cast time (default is 20%).
/// Cast time is altered be 2 portion, Variable Cast Time (VCT) and Fixed Cast Time (FCT).
/// By default FCT is 20% of VCT (some skills aren't)
/// - VCT is decreased by DEX * 2 + INT.
/// - FCT is NOT reduced by stats, reduced by equips or buffs.
/// Example:
/// On a skill whos cast time is 10s, only 8s may be reduced. the other 2s are part of a FCT
#define RENEWAL_CAST
/// renewal drop rate algorithms
/// Renewal drop rate algorithms
/// (disable by commenting the line)
///
/// leave this line to enable renewal item drop rate algorithms
/// while enabled a special modified based on the difference between the player and monster level is applied
/// based on the http://irowiki.org/wiki/Drop_System#Level_Factor table
/// Leave this line to enable renewal item drop rate algorithms
/// While enabled a special modified based on the difference between the player and monster level is applied
/// Based on the http://irowiki.org/wiki/Drop_System#Level_Factor table
#define RENEWAL_DROP
/// renewal exp rate algorithms
/// Renewal exp rate algorithms
/// (disable by commenting the line)
///
/// leave this line to enable renewal item exp rate algorithms
/// while enabled a special modified based on the difference between the player and monster level is applied
/// Leave this line to enable renewal item exp rate algorithms
/// While enabled a special modified based on the difference between the player and monster level is applied
#define RENEWAL_EXP
/// renewal level modifier on damage
/// Renewal level modifier on damage
/// (disable by commenting the line)
///
// leave this line to enable renewal base level modifier on skill damage (selected skills only)
// Leave this line to enable renewal base level modifier on skill damage (selected skills only)
#define RENEWAL_LVDMG
/// renewal ASPD [malufett]
/// Renewal ASPD [malufett]
/// (disable by commenting the line)
///
/// leave this line to enable renewal ASPD
/// Leave this line to enable renewal ASPD
/// - shield penalty is applied
/// - AGI has a greater factor in ASPD increase
/// - there is a change in how skills/items give ASPD
/// - some skill/item ASPD bonuses won't stack
#define RENEWAL_ASPD
/// renewal stat calculations
/// Renewal stat calculations
/// (disable by commenting the line)
///
/// leave this line to enable renewal calculation for increasing status/parameter points
/// Leave this line to enable renewal calculation for increasing status/parameter points
#define RENEWAL_STAT
#endif

View File

@ -7945,6 +7945,7 @@ static const struct _battle_data {
{ "boss_icewall_walk_block", &battle_config.boss_icewall_walk_block, 0, 0, 255, },
{ "snap_dodge", &battle_config.snap_dodge, 0, 0, 1, },
{ "stormgust_knockback", &battle_config.stormgust_knockback, 1, 0, 1, },
{ "default_fixed_castrate", &battle_config.default_fixed_castrate, 20, 0, 100, },
};
#ifndef STATS_OPT_OUT

View File

@ -579,6 +579,7 @@ extern struct Battle_Config
int boss_icewall_walk_block; //How a boss monster should be trapped in icewall [Playtester]
int snap_dodge; // Enable or disable dodging damage snapping away [csnv]
int stormgust_knockback;
int default_fixed_castrate;
} battle_config;
void do_init_battle(void);

View File

@ -2497,13 +2497,6 @@ void pc_bonus(struct map_session_data *sd,int type,int val)
break;
sd->bonus.sp += val;
break;
#ifndef RENEWAL_CAST
case SP_VARCASTRATE:
#endif
case SP_CASTRATE:
if(sd->state.lr_flag != 2)
sd->castrate+=val;
break;
case SP_MAXHPRATE:
if(sd->state.lr_flag != 2)
sd->hprate+=val;
@ -2911,26 +2904,38 @@ void pc_bonus(struct map_session_data *sd,int type,int val)
sd->bonus.itemhealrate2 += val;
break;
case SP_EMATK:
if(sd->state.lr_flag != 2)
sd->bonus.ematk += val;
break;
if(sd->state.lr_flag != 2)
sd->bonus.ematk += val;
break;
#ifdef RENEWAL_CAST
case SP_FIXCASTRATE:
if(sd->state.lr_flag != 2)
sd->bonus.fixcastrate -= val;
FIXEDCASTRATE(sd->bonus.fixcastrate,val);
break;
case SP_ADD_FIXEDCAST:
if(sd->state.lr_flag != 2)
sd->bonus.add_fixcast += val;
break;
#ifdef RENEWAL_CAST
case SP_CASTRATE:
case SP_VARCASTRATE:
if(sd->state.lr_flag != 2)
sd->bonus.varcastrate -= val;
sd->bonus.varcastrate += val;
break;
case SP_ADD_VARIABLECAST:
if(sd->state.lr_flag != 2)
sd->bonus.add_varcast += val;
break;
#else
case SP_ADD_FIXEDCAST:
case SP_FIXCASTRATE:
case SP_ADD_VARIABLECAST:
//ShowWarning("pc_bonus: non-RENEWAL_CAST doesn't support this bonus %d.\n", type);
break;
case SP_VARCASTRATE:
case SP_CASTRATE:
if(sd->state.lr_flag != 2)
sd->castrate += val;
break;
#endif
case SP_ADDMAXWEIGHT:
if (sd->state.lr_flag != 2)
@ -3305,7 +3310,7 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
ARR_FIND(0, ARRAYLENGTH(sd->skillblown), i, sd->skillblown[i].id == 0 || sd->skillblown[i].id == type2);
if (i == ARRAYLENGTH(sd->skillblown))
{ //Better mention this so the array length can be updated. [Skotlex]
ShowError("pc_bonus2: SP_ADD_SKILL_BLOW: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val);
ShowError("pc_bonus2: SP_ADD_SKILL_BLOW: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillblown), type2, val);
break;
}
if(sd->skillblown[i].id == type2)
@ -3315,49 +3320,6 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
sd->skillblown[i].val = val;
}
break;
#ifndef RENEWAL_CAST
case SP_VARCASTRATE: // bonus2 bVariableCastrate,sk,n;
#endif
case SP_CASTRATE: // bonus2 bCastrate,sk,n;
if(sd->state.lr_flag == 2)
break;
ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
if (i == ARRAYLENGTH(sd->skillcast))
{ //Better mention this so the array length can be updated. [Skotlex]
ShowError("run_script: %s: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n",
#ifndef RENEWAL_CAST
"SP_VARCASTRATE",
#else
"SP_CASTRATE",
#endif
ARRAYLENGTH(sd->skillcast), type2, val);
break;
}
if(sd->skillcast[i].id == type2)
sd->skillcast[i].val += val;
else {
sd->skillcast[i].id = type2;
sd->skillcast[i].val = val;
}
break;
case SP_FIXCASTRATE: // bonus2 bFixedCastrate,sk,n;
if(sd->state.lr_flag == 2)
break;
ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2);
if (i == ARRAYLENGTH(sd->skillfixcastrate))
{
ShowError("run_script: SP_FIXCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcastrate), type2, val);
break;
}
if(sd->skillfixcastrate[i].id == type2)
sd->skillfixcastrate[i].val -= val;
else {
sd->skillfixcastrate[i].id = type2;
sd->skillfixcastrate[i].val -= val;
}
break;
case SP_HP_LOSS_RATE: // bonus2 bHPLossRate,n,t;
if(sd->state.lr_flag != 2) {
sd->hp_loss.value = type2;
@ -3528,7 +3490,7 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
ARR_FIND(0, ARRAYLENGTH(sd->skillcooldown), i, sd->skillcooldown[i].id == 0 || sd->skillcooldown[i].id == type2);
if (i == ARRAYLENGTH(sd->skillcooldown))
{
ShowError("pc_bonus2: SP_SKILL_COOLDOWN: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val);
ShowError("pc_bonus2: SP_SKILL_COOLDOWN: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillcooldown), type2, val);
break;
}
if (sd->skillcooldown[i].id == type2)
@ -3538,13 +3500,14 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
sd->skillcooldown[i].val = val;
}
break;
#ifdef RENEWAL_CAST
case SP_SKILL_FIXEDCAST: // bonus2 bSkillFixedCast,sk,t;
if(sd->state.lr_flag == 2)
break;
ARR_FIND(0, ARRAYLENGTH(sd->skillfixcast), i, sd->skillfixcast[i].id == 0 || sd->skillfixcast[i].id == type2);
if (i == ARRAYLENGTH(sd->skillfixcast))
{
ShowError("pc_bonus2: SP_SKILL_FIXEDCAST: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val);
ShowError("pc_bonus2: SP_SKILL_FIXEDCAST: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillfixcast), type2, val);
break;
}
if (sd->skillfixcast[i].id == type2)
@ -3560,7 +3523,7 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
ARR_FIND(0, ARRAYLENGTH(sd->skillvarcast), i, sd->skillvarcast[i].id == 0 || sd->skillvarcast[i].id == type2);
if (i == ARRAYLENGTH(sd->skillvarcast))
{
ShowError("pc_bonus2: SP_SKILL_VARIABLECAST: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val);
ShowError("pc_bonus2: SP_SKILL_VARIABLECAST: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillvarcast), type2, val);
break;
}
if (sd->skillvarcast[i].id == type2)
@ -3570,21 +3533,61 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
sd->skillvarcast[i].val = val;
}
break;
#ifdef RENEWAL_CAST
case SP_CASTRATE: // bonus2 bCastrate,sk,n;
case SP_VARCASTRATE: // bonus2 bVariableCastrate,sk,n;
if(sd->state.lr_flag == 2)
break;
ARR_FIND(0, ARRAYLENGTH(sd->skillcast), i, sd->skillcast[i].id == 0 || sd->skillcast[i].id == type2);
if (i == ARRAYLENGTH(sd->skillcast))
ARR_FIND(0, ARRAYLENGTH(sd->skillcastrate), i, sd->skillcastrate[i].id == 0 || sd->skillcastrate[i].id == type2);
if (i == ARRAYLENGTH(sd->skillcastrate))
{
ShowError("pc_bonus2: SP_VARCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n",ARRAYLENGTH(sd->skillcast), type2, val);
ShowError("pc_bonus2: SP_VARCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n",ARRAYLENGTH(sd->skillcastrate), type2, val);
break;
}
if(sd->skillcast[i].id == type2)
sd->skillcast[i].val -= val;
if(sd->skillcastrate[i].id == type2)
sd->skillcastrate[i].val += val;
else {
sd->skillcast[i].id = type2;
sd->skillcast[i].val -= val;
sd->skillcastrate[i].id = type2;
sd->skillcastrate[i].val += val;
}
break;
case SP_FIXCASTRATE: // bonus2 bFixedCastrate,sk,n;
if(sd->state.lr_flag == 2)
break;
ARR_FIND(0, ARRAYLENGTH(sd->skillfixcastrate), i, sd->skillfixcastrate[i].id == 0 || sd->skillfixcastrate[i].id == type2);
if (i == ARRAYLENGTH(sd->skillfixcastrate))
{
ShowError("pc_bonus2: SP_FIXCASTRATE: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n", ARRAYLENGTH(sd->skillfixcastrate), type2, val);
break;
}
if(sd->skillfixcastrate[i].id == type2)
FIXEDCASTRATE(sd->skillfixcastrate[i].val,val);
else {
sd->skillfixcastrate[i].id = type2;
sd->skillfixcastrate[i].val = val;
}
break;
#else
case SP_SKILL_FIXEDCAST: // bonus2 bSkillFixedCast,sk,t;
case SP_SKILL_VARIABLECAST: // bonus2 bSkillVariableCast,sk,t;
case SP_FIXCASTRATE: // bonus2 bFixedCastrate,sk,n;
//ShowWarning("pc_bonus2: Non-RENEWAL_CAST doesn't support this bonus %d.\n", type);
break;
case SP_VARCASTRATE: // bonus2 bVariableCastrate,sk,n;
case SP_CASTRATE: // bonus2 bCastrate,sk,n;
if(sd->state.lr_flag == 2)
break;
ARR_FIND(0, ARRAYLENGTH(sd->skillcastrate), i, sd->skillcastrate[i].id == 0 || sd->skillcastrate[i].id == type2);
if (i == ARRAYLENGTH(sd->skillcastrate))
{ //Better mention this so the array length can be updated. [Skotlex]
ShowError("pc_bonus2: %s: Reached max (%d) number of skills per character, bonus skill %d (%d%%) lost.\n",
(type == SP_CASTRATE) ? "SP_CASTRATE" : "SP_VARCASTRATE", ARRAYLENGTH(sd->skillcastrate), type2, val);
break;
}
if(sd->skillcastrate[i].id == type2)
sd->skillcastrate[i].val += val;
else {
sd->skillcastrate[i].id = type2;
sd->skillcastrate[i].val = val;
}
break;
#endif
@ -3593,7 +3596,7 @@ void pc_bonus2(struct map_session_data *sd,int type,int type2,int val)
break;
ARR_FIND(0, ARRAYLENGTH(sd->skillusesp), i, sd->skillusesp[i].id == 0 || sd->skillusesp[i].id == type2);
if (i == ARRAYLENGTH(sd->skillusesp)) {
ShowError("pc_bonus2: SP_SKILL_USE_SP: Reached max (%d) number of skills per character, bonus skill %d (+%d%%) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val);
ShowError("pc_bonus2: SP_SKILL_USE_SP: Reached max (%d) number of skills per character, bonus skill %d (%d) lost.\n", ARRAYLENGTH(sd->skillusesp), type2, val);
break;
}
if (sd->skillusesp[i].id == type2)
@ -7572,12 +7575,6 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_FLEE1: val = sd->battle_status.flee; break;
case SP_FLEE2: val = sd->battle_status.flee2; break;
case SP_DEFELE: val = sd->battle_status.def_ele; break;
#ifndef RENEWAL_CAST
case SP_VARCASTRATE:
#endif
case SP_CASTRATE:
val = sd->castrate+=val;
break;
case SP_MAXHPRATE: val = sd->hprate; break;
case SP_MAXSPRATE: val = sd->sprate; break;
case SP_SPRATE: val = sd->dsprate; break;
@ -7658,9 +7655,13 @@ int pc_readparam(struct map_session_data* sd,int type)
case SP_EMATK: val = sd->bonus.ematk; break;
case SP_FIXCASTRATE: val = sd->bonus.fixcastrate; break;
case SP_ADD_FIXEDCAST: val = sd->bonus.add_fixcast; break;
case SP_ADD_VARIABLECAST: val = sd->bonus.add_varcast; break;
case SP_CASTRATE:
case SP_VARCASTRATE:
#ifdef RENEWAL_CAST
case SP_VARCASTRATE: val = sd->bonus.varcastrate; break;
case SP_ADD_VARIABLECAST:val = sd->bonus.add_varcast; break;
val = sd->bonus.varcastrate; break;
#else
val = sd->castrate; break;
#endif
}

View File

@ -355,7 +355,7 @@ struct map_session_data {
struct s_skill_bonus { //skillatk raises bonus dmg% of skills, skillheal increases heal%, skillblown increases bonus blewcount for some skills.
unsigned short id;
short val;
} skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[MAX_PC_BONUS], skillheal2[MAX_PC_BONUS], skillblown[MAX_PC_BONUS], skillcast[MAX_PC_BONUS], skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS], skillfixcastrate[MAX_PC_BONUS];
} skillatk[MAX_PC_BONUS], skillusesprate[MAX_PC_BONUS], skillusesp[MAX_PC_BONUS], skillheal[MAX_PC_BONUS], skillheal2[MAX_PC_BONUS], skillblown[MAX_PC_BONUS], skillcastrate[MAX_PC_BONUS], skillcooldown[MAX_PC_BONUS], skillfixcast[MAX_PC_BONUS], skillvarcast[MAX_PC_BONUS], skillfixcastrate[MAX_PC_BONUS];
struct s_regen {
short value;
int rate;
@ -419,8 +419,8 @@ struct map_session_data {
unsigned short unbreakable; // chance to prevent ANY equipment breaking [celest]
unsigned short unbreakable_equip; //100% break resistance on certain equipment
unsigned short unstripable_equip;
int fixcastrate,varcastrate;
int add_fixcast,add_varcast;
int fixcastrate, varcastrate; // n/100
int add_fixcast, add_varcast; // in milliseconds
int ematk; // matk bonus from equipment
int eatk; // atk bonus from equipment
} bonus;

View File

@ -15449,11 +15449,11 @@ int skill_castfix(struct block_list *bl, uint16 skill_id, uint16 skill_lv) {
int i;
if( sd->castrate != 100 )
time = time * sd->castrate / 100;
for( i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++ )
for( i = 0; i < ARRAYLENGTH(sd->skillcastrate) && sd->skillcastrate[i].id; i++ )
{
if( sd->skillcast[i].id == skill_id )
if( sd->skillcastrate[i].id == skill_id )
{
time+= time * sd->skillcast[i].val / 100;
time += time * sd->skillcastrate[i].val / 100;
break;
}
}
@ -15488,8 +15488,8 @@ int skill_castfix_sc(struct block_list *bl, int time)
if (sc && sc->count) {
if (sc->data[SC_SLOWCAST])
time += time * sc->data[SC_SLOWCAST]->val2 / 100;
if (sc->data[SC_PARALYSIS])
time += sc->data[SC_PARALYSIS]->val3;
if (sc->data[SC_PARALYSIS])
time += sc->data[SC_PARALYSIS]->val3;
if (sc->data[SC_SUFFRAGIUM]) {
time -= time * sc->data[SC_SUFFRAGIUM]->val2 / 100;
status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER);
@ -15511,7 +15511,14 @@ int skill_castfix_sc(struct block_list *bl, int time)
}
#else
/**
* Get the skill cast time for RENEWAL_CAST
* Get the skill cast time for RENEWAL_CAST.
* FixedRate reduction never be stacked, always get the HIGHEST VALUE TO REDUCE (-20% vs 10%, -20% wins!)
* Additive value:
* Variable CastTime : time += value
* Fixed CastTime : fixed += value
* Multipicative value
* Variable CastTime : VARCAST_REDUCTION(value)
* Fixed CastTime : FIXEDCASTRATE2(value)
* @param bl: The caster
* @param time: Cast time without reduction
* @param skill_id: Skill ID of the casted skill
@ -15522,7 +15529,13 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
{
struct status_change *sc = status_get_sc(bl);
struct map_session_data *sd = BL_CAST(BL_PC,bl);
int fixed = skill_get_fixed_cast(skill_id, skill_lv), fixcast_r = 0, varcast_r = 0, i = 0;
int fixed = skill_get_fixed_cast(skill_id, skill_lv);
short fixcast_r = 0;
uint8 i = 0, flag = skill_get_castnodex(skill_id, skill_lv);
#define FIXEDCASTRATE2(val) ( FIXEDCASTRATE(fixcast_r,(val)) )
nullpo_ret(bl);
if( time < 0 )
return 0;
@ -15530,97 +15543,116 @@ int skill_vfcastfix(struct block_list *bl, double time, uint16 skill_id, uint16
if( bl->type == BL_MOB )
return (int)time;
if( fixed == 0 ){
fixed = (int)time * 20 / 100; // fixed time
time = time * 80 / 100; // variable time
}else if( fixed < 0 ) // no fixed cast time
if( fixed < 0 || battle_config.default_fixed_castrate == 0 ) // no fixed cast time
fixed = 0;
else if( fixed == 0 ) {
fixed = (int)time * battle_config.default_fixed_castrate / 100; // fixed time
time = time * (100 - battle_config.default_fixed_castrate) / 100; // variable time
}
// Additive Variable Cast bonus first
if (sd && !(flag&4)) { // item bonus
time += sd->bonus.add_varcast; // bonus bVariableCast
for (i = 0; i < ARRAYLENGTH(sd->skillvarcast) && sd->skillvarcast[i].id; i++)
if( sd->skillvarcast[i].id == skill_id ){ // bonus2 bSkillVariableCast
time += sd->skillvarcast[i].val;
break;
}
}
/*if (sc && sc->count && !(flag&2)) { // status change
// -NONE YET-
// if (sc->data[????])
// bonus += sc->data[????]->val?;
}*/
// Adjusted by item bonuses
if (sd && !(flag&4)) {
// Additive values
fixed += sd->bonus.add_fixcast; // bonus bFixedCast
if(sd && !(skill_get_castnodex(skill_id, skill_lv)&4) ){ // Increases/Decreases fixed/variable cast time of a skill by item/card bonuses.
if( sd->bonus.varcastrate < 0 )
VARCAST_REDUCTION(sd->bonus.varcastrate);
if( sd->bonus.add_varcast != 0 ) // bonus bVariableCast
time += sd->bonus.add_varcast;
if( sd->bonus.add_fixcast != 0 ) // bonus bFixedCast
fixed += sd->bonus.add_fixcast;
for (i = 0; i < ARRAYLENGTH(sd->skillfixcast) && sd->skillfixcast[i].id; i++)
if (sd->skillfixcast[i].id == skill_id){ // bonus2 bSkillFixedCast
fixed += sd->skillfixcast[i].val;
break;
}
for( i = 0; i < ARRAYLENGTH(sd->skillvarcast) && sd->skillvarcast[i].id; i++ )
if( sd->skillvarcast[i].id == skill_id ){ // bonus2 bSkillVariableCast
time += sd->skillvarcast[i].val;
break;
}
for( i = 0; i < ARRAYLENGTH(sd->skillcast) && sd->skillcast[i].id; i++ )
if( sd->skillcast[i].id == skill_id ){ // bonus2 bVariableCastrate
VARCAST_REDUCTION(sd->skillcast[i].val);
// Multipicative values
if (sd->bonus.varcastrate != 0)
VARCAST_REDUCTION(sd->bonus.varcastrate); // bonus bVariableCastrate
if (sd->bonus.fixcastrate != 0)
FIXEDCASTRATE2(sd->bonus.fixcastrate); // bonus bFixedCastrate
for( i = 0; i < ARRAYLENGTH(sd->skillcastrate) && sd->skillcastrate[i].id; i++ )
if( sd->skillcastrate[i].id == skill_id ){ // bonus2 bVariableCastrate
VARCAST_REDUCTION(sd->skillcastrate[i].val);
break;
}
for( i = 0; i < ARRAYLENGTH(sd->skillfixcastrate) && sd->skillfixcastrate[i].id; i++ )
if( sd->skillfixcastrate[i].id == skill_id ){ // bonus2 bFixedCastrate
fixcast_r = sd->skillfixcastrate[i].val;
FIXEDCASTRATE2(sd->skillfixcastrate[i].val);
break;
}
}
if (sc && sc->count && !(skill_get_castnodex(skill_id, skill_lv)&2) ) {
// All variable cast additive bonuses must come first
// Adjusted by active statuses
if (sc && sc->count && !(flag&2) ) {
// Multiplicative Variable CastTime values
if (sc->data[SC_SLOWCAST])
VARCAST_REDUCTION(-sc->data[SC_SLOWCAST]->val2);
if( sc->data[SC__LAZINESS] )
VARCAST_REDUCTION(-sc->data[SC__LAZINESS]->val2);
VARCAST_REDUCTION(sc->data[SC_SLOWCAST]->val2);
if (sc->data[SC__LAZINESS])
VARCAST_REDUCTION(sc->data[SC__LAZINESS]->val2);
// Variable cast reduction bonuses
if (sc->data[SC_SUFFRAGIUM]) {
VARCAST_REDUCTION(sc->data[SC_SUFFRAGIUM]->val2);
VARCAST_REDUCTION(-sc->data[SC_SUFFRAGIUM]->val2);
status_change_end(bl, SC_SUFFRAGIUM, INVALID_TIMER);
}
if (sc->data[SC_MEMORIZE]) {
VARCAST_REDUCTION(50);
VARCAST_REDUCTION(-50);
if ((--sc->data[SC_MEMORIZE]->val2) <= 0)
status_change_end(bl, SC_MEMORIZE, INVALID_TIMER);
}
if (sc->data[SC_POEMBRAGI])
VARCAST_REDUCTION(sc->data[SC_POEMBRAGI]->val2);
VARCAST_REDUCTION(-sc->data[SC_POEMBRAGI]->val2);
if (sc->data[SC_IZAYOI])
VARCAST_REDUCTION(50);
VARCAST_REDUCTION(-50);
if (sc->data[SC_WATER_INSIGNIA] && sc->data[SC_WATER_INSIGNIA]->val1 == 3 && (skill_get_ele(skill_id, skill_lv) == ELE_WATER))
VARCAST_REDUCTION(30); //Reduces 30% Variable Cast Time of Water spells.
if( sc->data[SC_TELEKINESIS_INTENSE] )
VARCAST_REDUCTION(sc->data[SC_TELEKINESIS_INTENSE]->val2);
// Fixed cast reduction bonuses
if( sc->data[SC_SECRAMENT] )
fixcast_r = max(fixcast_r, sc->data[SC_SECRAMENT]->val2);
if( sd && ( skill_lv = pc_checkskill(sd, WL_RADIUS) ) && skill_id >= WL_WHITEIMPRISON && skill_id <= WL_FREEZE_SP )
fixcast_r = max(fixcast_r, 5 + skill_lv * 5);
// Fixed cast non percentage bonuses
if( sc->data[SC_MANDRAGORA] )
fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2;
if( sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_WILD_STORM_OPTION] )
fixed -= 1000;
VARCAST_REDUCTION(-30); //Reduces 30% Variable Cast Time of Water spells.
if (sc->data[SC_TELEKINESIS_INTENSE])
VARCAST_REDUCTION(-sc->data[SC_TELEKINESIS_INTENSE]->val2);
// Multiplicative Fixed CastTime values
if (sc->data[SC_SECRAMENT])
FIXEDCASTRATE2(-sc->data[SC_SECRAMENT]->val2);
if (sd && (skill_lv = pc_checkskill(sd, WL_RADIUS) ) && skill_id >= WL_WHITEIMPRISON && skill_id <= WL_FREEZE_SP)
FIXEDCASTRATE2(-(5 + skill_lv * 5));
if (sc->data[SC_DANCEWITHWUG])
fixed -= fixed * sc->data[SC_DANCEWITHWUG]->val4 / 100;
if( sc->data[SC_HEAT_BARREL] )
fixcast_r = max(fixcast_r, sc->data[SC_HEAT_BARREL]->val2);
FIXEDCASTRATE2(-sc->data[SC_DANCEWITHWUG]->val4);
if (sc->data[SC_HEAT_BARREL])
FIXEDCASTRATE2(-sc->data[SC_HEAT_BARREL]->val2);
// Additive Fixed CastTime values
if (sc->data[SC_MANDRAGORA])
fixed += sc->data[SC_MANDRAGORA]->val1 * 1000 / 2;
if (sc->data[SC_GUST_OPTION] || sc->data[SC_BLAST_OPTION] || sc->data[SC_WILD_STORM_OPTION])
fixed -= 1000;
if (sc->data[SC_IZAYOI])
fixed = 0;
}
if( sd && !(skill_get_castnodex(skill_id, skill_lv)&4) ){
VARCAST_REDUCTION( max(sd->bonus.varcastrate, 0) + max(i, 0) );
fixcast_r = max(fixcast_r, sd->bonus.fixcastrate) + min(sd->bonus.fixcastrate,0);
}
// Apply Variable CastTime calculation by INT & DEX
if (!(flag&1))
time = time * (1 - sqrt(((float)(status_get_dex(bl)*2 + status_get_int(bl)) / battle_config.vcast_stat_scale)));
if( varcast_r < 0 ) // now compute overall factors
time = time * (1 - (float)varcast_r / 100);
if( !(skill_get_castnodex(skill_id, skill_lv)&1) )// reduction from status point
time = (1 - sqrt( ((float)(status_get_dex(bl)*2 + status_get_int(bl)) / battle_config.vcast_stat_scale) )) * time;
// underflow checking/capping
time = max(time, 0) + (1 - (float)min(fixcast_r, 100) / 100) * max(fixed,0);
// Apply Fixed CastTime rate
if (fixed != 0 && fixcast_r != 0)
fixed = (int)(fixed * (1 + fixcast_r * 0.01));
return (int)time;
#undef FIXEDCASTRATE2
return (int)max(time + fixed, 0);
}
#endif

View File

@ -2939,7 +2939,7 @@ int status_calc_pc_(struct map_session_data* sd, enum e_status_calc_opt opt)
+ sizeof(sd->skillheal)
+ sizeof(sd->skillheal2)
+ sizeof(sd->skillblown)
+ sizeof(sd->skillcast)
+ sizeof(sd->skillcastrate)
+ sizeof(sd->skillcooldown)
+ sizeof(sd->skillfixcast)
+ sizeof(sd->skillvarcast)