- Made the warm skills BF_WEAPON type so that they may trigger effect cards.

- Also changed their pl to -1 so they carry the elemeso they carry the element.
- Warm skills now damage other players for 60sp per hit.
- Warm skill damage interval decreased to 100ms instead of 1000ms.
- TK_DODGE  now only dodges ranged weapon attacks, while under Spurt mode it dodges everything.
- Cleaned up and expanded the sc_def_rate battle config. The new battle flags are mob_sc_def_rate, pc_sc_def_rate, mob_max_sc_def, pc_max_sc_def
- Modified Marionette Control so that the max bonus stats you get is capped to your server's defined max stats instead of 99.
- Mobs are no longer affected by the vs_traps_bctall switch.
- Added function pc_damage_sp to damage the SP of players.
- Modified Warm skills so that it only hurts SP of players while attacking/knocking back mobs.
- Autospell loop breaks after one skill is successful.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@5288 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
skotlex 2006-02-15 18:56:54 +00:00
parent e3b57bb929
commit 00bbc7673b
10 changed files with 248 additions and 162 deletions

View File

@ -4,6 +4,27 @@ AS OF SVN REV. 5091, WE ARE NOW USING TRUNK. ALL UNTESTED BUGFIXES/FEATURES GO
IF YOU HAVE A WORKING AND TESTED BUGFIX PUT IT INTO STABLE AS WELL AS TRUNK. EVERYTHING ELSE
GOES INTO TRUNK AND WILL BE MERGED INTO STABLE BY VALARIS AND WIZPUTER. -- VALARIS
2006/02/15
* The autospell loop now cancels after one successful cast. This means if
you have 10 autospells with 100% casting rate, only one will come off with
each hit instead of all of them. [Skotlex]
* Warm skill update: [Skotlex]
- they are type BF_WEAPON, so that they may trigger effect/spell cards.
- Changed their element to -1 to carry on weapon's element.
- Against player it only damages 60SP per "hit"
- Against non-players it is a knockback skill as it was before.
- Hit frequency increased to once every 100ms.
* TK_DODGE now only dodges ranged weapon attacks, while under Spurt mode
it dodges everything (provide better information if this is not how it
should behave as the current info given is conflicting itself >.<)
[Skotlex]
* Cleaned up and expanded the sc_def_rate battle config. The new battle
flags are mob_sc_def_rate, pc_sc_def_rate, mob_max_sc_def, pc_max_sc_def
[Skotlex]
* Modified Marionette Control so that the max bonus stats you get is capped
to your server's defined max stats instead of 99. [Skotlex]
* Mobs are no longer affected by the vs_traps_bctall switch. [Skotlex]
* Added function pc_damage_sp to damage the SP of players, updated code as
necessary. [Skotlex]
* Fixed @lvup command adding levels instead of substracting when you
specify a negative quantity. [Skotlex]
2006/02/14

View File

@ -154,5 +154,12 @@ gtb_pvp_only: no
// Adjustment for the natural rate of resistance from status changes.
// If 50, status defense is halved, and you need twice as much stats to block
// poison/silence/etc (eg: 200 vit to block poison/stun)
status_def_rate: 100
// them (eg: 200 vit to completely block stun)
pc_status_def_rate: 100
mob_status_def_rate: 100
// Maximum resistance to status changes. (10000 = 100%)
// NOTE: This is applied after cards and equipment.
// So inmunity cards will be capped to this value.
pc_max_status_def: 10000
mob_max_status_def: 10000

View File

@ -444,9 +444,9 @@
425,0,6,4,2:4:1:3:8:7:6,1,7,1,no,0,0,0,weapon,0 //TK_SEVENWIND#Mild Wind#
426,0,6,4,0,1,5,1,no,0,0,0,weapon,0 //TK_HIGHJUMP#Taekwon Jump#
427,0,6,4,0,1,3,1,yes,0,0,0,magic,0 //SG_FEEL#Feeling the Sun, Moon and Stars#
428,1,6,4,0,1,3,1,yes,0,0,0,magic,2 //SG_SUN_WARM#Warmth of the Sun#
429,1,6,4,0,1,3,1,yes,0,0,0,magic,2 //SG_MOON_WARM#Warmth of the Moon#
430,1,6,4,0,1,3,1,yes,0,0,0,magic,2 //SG_STAR_WARM#Warmth of the Star#
428,1,6,4,-1,1,3,1,yes,0,0,0,weapon,2 //SG_SUN_WARM#Warmth of the Sun#
429,1,6,4,-1,1,3,1,yes,0,0,0,weapon,2 //SG_MOON_WARM#Warmth of the Moon#
430,1,6,4,-1,1,3,1,yes,0,0,0,weapon,2 //SG_STAR_WARM#Warmth of the Star#
431,0,0,4,0,1,4,1,yes,0,0,0,magic,0 //SG_SUN_COMFORT#Comfort of the Sun#
432,0,0,4,0,1,4,1,yes,0,0,0,magic,0 //SG_MOON_COMFORT#Comfort of the Moon#
433,0,0,4,0,1,4,1,yes,0,0,0,magic,0 //SG_STAR_COMFORT#Comfort of the Star#

View File

@ -609,7 +609,8 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
return 0;
}
if(sc->data[SC_DODGE].timer != -1 && !sc->opt1 && (flag&BF_LONG || (sc->data[SC_SPURT].timer != -1 && flag&BF_WEAPON))
if(sc->data[SC_DODGE].timer != -1 && !sc->opt1 &&
((flag&BF_LONG && flag&BF_WEAPON) || sc->data[SC_SPURT].timer != -1)
&& rand()%100 < 20) {
if (sd && pc_issit(sd)) pc_setstand(sd); //Stand it to dodge.
clif_skill_nodamage(bl,bl,TK_DODGE,1,1);
@ -651,16 +652,16 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i
damage >>=1;
if(sc->data[SC_ENERGYCOAT].timer!=-1 && flag&BF_WEAPON){
if(sd){
if(sd && sd->status.max_sp){
if(sd->status.sp>0){
int per = sd->status.sp * 5 / (sd->status.max_sp + 1);
sd->status.sp -= sd->status.sp * (per * 5 + 10) / 1000;
if( sd->status.sp < 0 ) sd->status.sp = 0;
damage -= damage * ((per+1) * 6) / 100;
clif_updatestatus(sd,SP_SP);
int per = 100*sd->status.sp / sd->status.max_sp;
per /=20; //Uses 20% SP intervals.
//SP Cost: 1% + 0.5% per every 20% SP
if (pc_damage_sp(sd, (10+5*per)*sd->status.max_sp/10000, 0) <= 0)
status_change_end( bl,SC_ENERGYCOAT,-1 );
//Reduction: 6% + 6% every 20%
damage -= damage * 6 * (1+per) / 100;
}
if(sd->status.sp<=0)
status_change_end( bl,SC_ENERGYCOAT,-1 );
}
else
damage -= damage * (sc->data[SC_ENERGYCOAT].val1 * 6) / 100;
@ -3824,11 +3825,14 @@ static const struct battle_data_short {
{ "duel_autoleave_when_die", &battle_config.duel_autoleave_when_die}, //[LuzZza]
{ "duel_time_interval", &battle_config.duel_time_interval}, // [LuzZza]
{ "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu}, // [LuzZza]
{ "allow_skill_without_day", &battle_config.allow_skill_without_day}, // [Komurka]
{ "skip_teleport_lv1_menu", &battle_config.skip_teleport_lv1_menu}, // [LuzZza]
{ "allow_skill_without_day", &battle_config.allow_skill_without_day}, // [Komurka]
{ "skill_caster_check", &battle_config.skill_caster_check },
{ "status_cast_cancel", &battle_config.sc_castcancel },
{ "status_def_rate", &battle_config.sc_def_rate },
{ "pc_status_def_rate", &battle_config.pc_sc_def_rate },
{ "mob_status_def_rate", &battle_config.mob_sc_def_rate },
{ "pc_max_status_def", &battle_config.pc_max_sc_def },
{ "mob_max_status_def", &battle_config.mob_max_sc_def },
};
static const struct battle_data_int {
@ -4218,7 +4222,10 @@ void battle_set_defaults() {
battle_config.skill_caster_check = 1;
battle_config.sc_castcancel = 0;
battle_config.sc_def_rate = 100;
battle_config.pc_sc_def_rate = 100;
battle_config.mob_sc_def_rate = 100;
battle_config.pc_max_sc_def = 10000;
battle_config.mob_max_sc_def = 5000;
}
void battle_validate_conf() {
@ -4407,6 +4414,10 @@ void battle_validate_conf() {
if (battle_config.mobs_level_up_exp_rate < 1) // [Valaris]
battle_config.mobs_level_up_exp_rate = 1;
if (battle_config.pc_max_sc_def > 10000)
battle_config.pc_max_sc_def = 10000;
if (battle_config.mob_max_sc_def > 10000)
battle_config.mob_max_sc_def = 10000;
#ifdef CELL_NOSTACK
if (battle_config.cell_stack_limit < 1)
battle_config.cell_stack_limit = 1;

View File

@ -419,7 +419,11 @@ extern struct Battle_Config {
unsigned short cell_stack_limit; // [Skotlex]
unsigned short skill_caster_check; // [Skotlex]
unsigned short sc_castcancel; // [Skotlex]
unsigned short sc_def_rate; // [Skotlex]
unsigned short pc_sc_def_rate; // [Skotlex]
unsigned short mob_sc_def_rate;
unsigned short pc_max_sc_def;
unsigned short mob_max_sc_def;
} battle_config;
void do_init_battle(void);

View File

@ -1267,7 +1267,7 @@ int charcommand_baselevel(
level = pc_maxbaselv(pl_sd) - pl_sd->status.base_level;
for (i = 1; i <= level; i++)
pl_sd->status.status_point += (pl_sd->status.base_level + i + 14) / 5;
pl_sd->status.base_level += level;
pl_sd->status.base_level += (unsigned int)level;
clif_updatestatus(pl_sd, SP_BASELEVEL);
clif_updatestatus(pl_sd, SP_NEXTBASEEXP);
clif_updatestatus(pl_sd, SP_STATUSPOINT);
@ -1290,7 +1290,7 @@ int charcommand_baselevel(
pl_sd->status.status_point = 0;
clif_updatestatus(pl_sd, SP_STATUSPOINT);
} // to add: remove status points from stats
pl_sd->status.base_level -= level;
pl_sd->status.base_level -= (unsigned int)level;
clif_updatestatus(pl_sd, SP_BASELEVEL);
clif_updatestatus(pl_sd, SP_NEXTBASEEXP);
status_calc_pc(pl_sd, 0);
@ -1338,7 +1338,7 @@ int charcommand_joblevel(
if ((unsigned int)level > pc_maxjoblv(pl_sd) ||
pl_sd->status.job_level > pc_maxjoblv(pl_sd) -level)
level = pc_maxjoblv(pl_sd) - pl_sd->status.job_level;
pl_sd->status.job_level += level;
pl_sd->status.job_level += (unsigned int)level;
clif_updatestatus(pl_sd, SP_JOBLEVEL);
clif_updatestatus(pl_sd, SP_NEXTJOBEXP);
pl_sd->status.skill_point += level;
@ -1354,7 +1354,7 @@ int charcommand_joblevel(
level*=-1;
if ((unsigned int)level >= pl_sd->status.job_level)
level = pl_sd->status.job_level-1;
pl_sd->status.job_level -= level;
pl_sd->status.job_level -= (unsigned int)level;
clif_updatestatus(pl_sd, SP_JOBLEVEL);
clif_updatestatus(pl_sd, SP_NEXTJOBEXP);
if (pl_sd->status.skill_point < level)

View File

@ -5272,6 +5272,33 @@ static int pc_respawn(int tid,unsigned int tick,int id,int data)
}
return 0;
}
/*==========================================
* Damages a player's SP, returns remaining SP. [Skotlex]
* damage is absolute damage, rate is % damage (100 = 100%)
* Returns remaining SP, or -1 if the player did not have enough SP to substract from.
*------------------------------------------
*/
int pc_damage_sp(struct map_session_data *sd, int damage, int rate)
{
if (!sd->status.sp)
return 0;
if (rate)
damage += (rate*(sd->status.sp-damage)/sd->status.max_sp)/100;
if (sd->status.sp >= damage){
sd->status.sp -= damage;
clif_updatestatus(sd,SP_SP);
return sd->status.sp;
}
if (sd->status.sp) {
sd->status.sp = 0;
clif_updatestatus(sd,SP_SP);
return -1;
}
return 0;
}
/*==========================================
* pcにダメ??
*------------------------------------------
@ -5918,14 +5945,11 @@ int pc_heal(struct map_session_data *sd,int hp,int sp)
nullpo_retr(0, sd);
if(pc_checkoverhp(sd)) {
if(hp > 0)
hp = 0;
}
if(pc_checkoversp(sd)) {
if(sp > 0)
sp = 0;
}
if(hp > 0 && pc_checkoverhp(sd))
hp = 0;
if(sp > 0 && pc_checkoversp(sd))
sp = 0;
if(sd->sc.count && sd->sc.data[SC_BERSERK].timer!=-1) //バ?サ?ク中は回復させないらしい
return 0;

View File

@ -138,6 +138,7 @@ int pc_unequipitem(struct map_session_data*,int,int);
int pc_checkitem(struct map_session_data*);
int pc_useitem(struct map_session_data*,int);
int pc_damage_sp(struct map_session_data *, int, int);
int pc_damage(struct block_list *,struct map_session_data*,int);
int pc_heal(struct map_session_data *,int,int);
int pc_itemheal(struct map_session_data *sd,int hp,int sp);

View File

@ -970,11 +970,9 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
skilllv,0,0,0,skill_get_time2(skillid,skilllv),0);
break;
case HT_SHOCKWAVE: //it can't affect mobs, because they have no SP...
if(dstsd){
dstsd->status.sp -= dstsd->status.sp*(15*skilllv+5)/100;
clif_updatestatus(dstsd,SP_SP);
}
case HT_SHOCKWAVE: //it can't affect mobs, because they have no SP...
if(dstsd)
pc_damage_sp(dstsd, 0, 15*skilllv+5);
break;
case HT_SANDMAN: /* サンドマン */
@ -1025,10 +1023,8 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
break;
case PA_PRESSURE: /* プレッシャ? */
if (dstsd) {
dstsd->status.sp -= dstsd->status.sp * (15 + 5 * skilllv) / 100;
clif_updatestatus(dstsd,SP_SP);
}
if (dstsd)
pc_damage_sp(dstsd, 0, 15 +5*skilllv);
break;
case RG_RAID: /* サプライズアタック */
@ -1054,29 +1050,16 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
case DC_UGLYDANCE:
if (dstsd) {
int skill, sp = 5+5*skilllv;
if(sd && (skill=pc_checkskill(sd,DC_DANCINGLESSON)))
sp += 5+skill;
dstsd->status.sp -= sp;
if(dstsd->status.sp<0)
dstsd->status.sp=0;
clif_updatestatus(dstsd,SP_SP);
int skill, sp = 5+5*skilllv;
if(sd && (skill=pc_checkskill(sd,DC_DANCINGLESSON)))
sp += 5+skill;
pc_damage_sp(dstsd, sp, 0);
}
break;
case SL_STUN:
if (status_get_size(bl)==1) //Only stuns mid-sized mobs.
status_change_start(bl,SC_STUN,(30+10*skilllv),skilllv,0,0,0,skill_get_time(skillid,skilllv),0);
break;
case SG_SUN_WARM:
case SG_MOON_WARM:
case SG_STAR_WARM:
if (dstsd) {
dstsd->status.sp -= 5;
if(dstsd->status.sp < 0)
dstsd->status.sp = 0;
clif_updatestatus(dstsd,SP_SP);
}
break;
/* MOBの追加?果付きスキル */
case NPC_PETRIFYATTACK:
@ -1245,46 +1228,56 @@ int skill_additional_effect (struct block_list* src, struct block_list *bl, int
//Reports say that autospell effects get triggered on skills and pretty much everything including splash attacks. [Skotlex]
//Here we use the nk value to trigger spells only on damage causing skills (otherwise stuff like AL_HEAL will trigger them)
if(sd && !status_isdead(bl) && src != bl &&
(!skillid || skillid == KN_AUTOCOUNTER || skillid == CR_REFLECTSHIELD || skill_get_nk(skillid)!=NK_NO_DAMAGE))
{
struct block_list *tbl;
int i, auto_skillid, auto_skilllv, rate;
for (i = 0; i < MAX_PC_BONUS; i++) {
if (sd->autospell[i].id == 0)
if(sd && !status_isdead(bl) && src != bl) {
switch (skillid) {
case KN_AUTOCOUNTER:
case CR_REFLECTSHIELD:
case SG_SUN_WARM:
case SG_MOON_WARM:
case SG_STAR_WARM:
rate = 1;
break;
default:
rate = (!skillid || skill_get_nk(skillid)!=NK_NO_DAMAGE);
}
if (rate) {
struct block_list *tbl;
int i;
for (i = 0; i < MAX_PC_BONUS && sd->autospell[i].id; i++) {
auto_skillid = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id;
skill = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id;
//Prevents skill from retriggering themselves. [Skotlex]
if (skill == skillid)
continue;
if (auto_skillid == skillid) //Prevents skill from retriggering themselves. [Skotlex]
continue;
//skill2 reused to store skilllv.
skill2 = (sd->autospell[i].lv > 0) ? sd->autospell[i].lv : 1;
rate = (!sd->state.arrow_atk) ? sd->autospell[i].rate : sd->autospell[i].rate / 2;
auto_skilllv = (sd->autospell[i].lv > 0) ? sd->autospell[i].lv : 1;
rate = (!sd->state.arrow_atk) ? sd->autospell[i].rate : sd->autospell[i].rate / 2;
if (rand()%1000 > rate)
continue;
if (sd->autospell[i].id < 0)
tbl = src;
else
tbl = bl;
if (tbl != src && !battle_check_range(src, tbl, skill_get_range2(src, auto_skillid, auto_skilllv)))
continue; //Autoskills DO check for target-src range. [Skotlex]
if (skill_get_inf(auto_skillid) & INF_GROUND_SKILL)
skill_castend_pos2(src, tbl->x, tbl->y, auto_skillid, auto_skilllv, tick, 0);
else {
switch (skill_get_nk(auto_skillid)) {
case NK_NO_DAMAGE:
skill_castend_nodamage_id(src, tbl, auto_skillid, auto_skilllv, tick, 0);
break;
case NK_SPLASH_DAMAGE:
default:
skill_castend_damage_id(src, tbl, auto_skillid, auto_skilllv, tick, 0);
break;
if (rand()%1000 > rate)
continue;
if (sd->autospell[i].id < 0)
tbl = src;
else
tbl = bl;
if (tbl != src && !battle_check_range(src, tbl, skill_get_range2(src, skill, skill2)))
continue; //Autoskills DO check for target-src range. [Skotlex]
if (skill_get_inf(skill) & INF_GROUND_SKILL)
skill_castend_pos2(src, tbl->x, tbl->y, skill, skill2, tick, 0);
else {
switch (skill_get_nk(skill)) {
case NK_NO_DAMAGE:
skill_castend_nodamage_id(src, tbl, skill, skill2, tick, 0);
break;
case NK_SPLASH_DAMAGE:
default:
skill_castend_damage_id(src, tbl, skill, skill2, tick, 0);
break;
}
}
break; //Only one auto skill comes off at a time.
}
}
}
@ -6434,8 +6427,10 @@ struct skill_unit_group *skill_unitsetting( struct block_list *src, int skillid,
val3 = BD_INTOABYSS; //Store into abyss state, to know it shouldn't give traps back. [Skotlex]
if (map_flag_gvg(src->m))
limit *= 4; // longer trap times in WOE [celest]
if (battle_config.vs_traps_bctall && map_flag_vs(src->m))
target = BCT_ALL; //Change target to all [Skotlex]
if (battle_config.vs_traps_bctall && map_flag_vs(src->m)
&& src->type != BL_MOB)
//Change target to all with the exception of mob traps [Skotlex]
target = BCT_ALL;
break;
case SA_LANDPROTECTOR: /* グランドク<E38389>?ス */
@ -7510,12 +7505,7 @@ static int skill_check_pc_partner(struct map_session_data *sd, int skill_id, int
for (i = 0; i < c; i++)
{
if ((tsd = map_id2sd(p_sd[i])) != NULL)
{
tsd->status.sp -= 10;
if (tsd->status.sp < 0)
tsd->status.sp = 0;
clif_updatestatus(tsd,SP_SP);
}
pc_damage_sp(tsd, 10, 0);
}
return c;
case CG_MOONLIT:

View File

@ -1009,12 +1009,25 @@ int status_calc_pc(struct map_session_data* sd,int first)
else if(sd->sc.data[SC_MARIONETTE2].timer!=-1){
struct map_session_data *psd = map_id2sd(sd->sc.data[SC_MARIONETTE2].val3);
if (psd) { // if partner is found
sd->paramb[0] += sd->status.str+psd->status.str/2 > 99 ? 99-sd->status.str : psd->status.str/2;
sd->paramb[1] += sd->status.agi+psd->status.agi/2 > 99 ? 99-sd->status.agi : psd->status.agi/2;
sd->paramb[2] += sd->status.vit+psd->status.vit/2 > 99 ? 99-sd->status.vit : psd->status.vit/2;
sd->paramb[3] += sd->status.int_+psd->status.int_/2 > 99 ? 99-sd->status.int_ : psd->status.int_/2;
sd->paramb[4] += sd->status.dex+psd->status.dex/2 > 99 ? 99-sd->status.dex : psd->status.dex/2;
sd->paramb[5] += sd->status.luk+psd->status.luk/2 > 99 ? 99-sd->status.luk : psd->status.luk/2;
bl = pc_maxparameter(sd); //Cap to max parameter. [Skotlex]
if (sd->status.str < bl)
sd->paramb[0] += sd->status.str+psd->status.str/2 > bl ?
bl-sd->status.str : psd->status.str/2;
if (sd->status.agi < bl)
sd->paramb[1] += sd->status.agi+psd->status.agi/2 > bl ?
bl-sd->status.agi : psd->status.agi/2;
if (sd->status.vit < bl)
sd->paramb[2] += sd->status.vit+psd->status.vit/2 > bl ?
bl-sd->status.vit : psd->status.vit/2;
if (sd->status.int_ < bl)
sd->paramb[3] += sd->status.int_+psd->status.int_/2 > bl ?
bl-sd->status.int_ : psd->status.int_/2;
if (sd->status.dex < bl)
sd->paramb[4] += sd->status.dex+psd->status.dex/2 > bl ?
bl-sd->status.dex : psd->status.dex/2;
if (sd->status.luk < bl)
sd->paramb[5] += sd->status.luk+psd->status.luk/2 > bl ?
bl-sd->status.luk : psd->status.luk/2;
}
}
}
@ -3286,46 +3299,48 @@ int status_get_sc_def(struct block_list *bl, int type)
switch (type)
{
//Note that stats that are *100/3 were simplified to *33
case SP_MDEF1: // mdef
case SC_STONE:
case SC_FREEZE:
case SC_DECREASEAGI:
sc_def = 3 + status_get_mdef(bl) + status_get_luk(bl)/3;
case SC_COMA:
sc_def = 300 +100*status_get_mdef(bl) +33*status_get_luk(bl);
break;
case SP_MDEF2: // int
case SC_SLEEP:
case SC_CONFUSION:
sc_def = 3 + status_get_int(bl) + status_get_luk(bl)/3;
sc_def = 300 +100*status_get_int(bl) +33*status_get_luk(bl);
break;
case SP_DEF1: // def
sc_def = 3 + status_get_def(bl) + status_get_luk(bl)/3;
sc_def = 300 +100*status_get_def(bl) +33*status_get_luk(bl);
break;
case SP_DEF2: // vit
case SC_STUN:
case SC_POISON:
case SC_SILENCE:
case SC_STOP:
sc_def = 3 + status_get_vit(bl) + status_get_luk(bl)/3;
sc_def = 300 +100*status_get_vit(bl) +33*status_get_luk(bl);
break;
case SP_LUK: // luck
sc_def = 3 + status_get_luk(bl);
sc_def = 300 +100*status_get_luk(bl);
break;
case SC_BLIND:
sc_def = 3 + status_get_int(bl) + status_get_vit(bl)/3;
sc_def = 300 +100*status_get_int(bl) +33*status_get_vit(bl);
break;
case SC_CURSE:
sc_def = 3 + status_get_luk(bl) + status_get_vit(bl)/3;
break;
case SC_COMA:
sc_def = 3 + status_get_mdef(bl);
sc_def = 300 +100*status_get_luk(bl) +33*status_get_vit(bl);
break;
default:
return 0; //Effect that cannot be reduced? Likely a buff.
}
sc_def*=100; //Send it on the interval 0->10000
if (battle_config.sc_def_rate != 100)
sc_def = sc_def*battle_config.sc_def_rate/100;
if (bl->type == BL_PC) {
if (battle_config.pc_sc_def_rate != 100)
sc_def = sc_def*battle_config.pc_sc_def_rate/100;
} else
if (battle_config.mob_sc_def_rate != 100)
sc_def = sc_def*battle_config.mob_sc_def_rate/100;
sc = status_get_sc(bl);
if (sc && sc->count)
@ -3336,15 +3351,18 @@ int status_get_sc_def(struct block_list *bl, int type)
sc_def += 100*sc->data[SC_SIEGFRIED].val2; //Status resistance.
}
if(bl->type == BL_MOB && sc_def > 5000)
sc_def = 5000; //Are mobs really capped to 50% defense?
sd = bl->type==BL_PC?(struct map_session_data*)bl:NULL;
if(sd && SC_COMMON_MIN<=type && type<=SC_COMMON_MAX &&
sd->reseff[type-SC_COMMON_MIN] > 0)
sc_def += sd->reseff[type-SC_COMMON_MIN];
if(bl->type == BL_PC) {
if (sc_def > battle_config.pc_max_sc_def)
sc_def = battle_config.pc_max_sc_def;
} else if (sc_def > battle_config.mob_max_sc_def)
sc_def = battle_config.mob_max_sc_def;
return sc_def;
}
@ -3352,6 +3370,9 @@ int status_get_sc_def(struct block_list *bl, int type)
int status_get_sc_tick(struct block_list *bl, int type, int tick)
{
struct map_session_data *sd;
int rate=0, min=0;
//If rate is positive, it is a % reduction (10000 -> 100%)
//if it is negative, it is an absolute reduction in ms.
sd = bl->type == BL_PC?(struct map_session_data *)bl:NULL;
switch (type) {
case SC_DECREASEAGI: /* 速度減少 */
@ -3366,55 +3387,68 @@ int status_get_sc_tick(struct block_list *bl, int type, int tick)
tick += tick / 10;
break;
case SC_STONE: /* 石化 */
tick = tick-status_get_mdef(bl)*200;
rate = -200*status_get_mdef(bl);
break;
case SC_FREEZE: /* 凍結 */
tick -= tick*status_get_mdef(bl)/100;
rate = 100*status_get_mdef(bl);
break;
case SC_STUN: /* スタンval2にミリ秒セット */
tick -= tick*status_get_sc_def_vit(bl)/10000;
rate = status_get_sc_def_vit(bl);
break;
case SC_DPOISON: /* 猛毒 */
case SC_POISON: /* 毒 */
tick -= tick*(status_get_vit(bl) + status_get_luk(bl)/5)/100;
rate = 100*status_get_vit(bl) + 20*status_get_luk(bl);
break;
case SC_SILENCE: /* 沈?(レックスデビ?ナ) */
case SC_CONFUSION:
case SC_CURSE:
tick -= tick * status_get_vit(bl)/100;
rate = 100*status_get_vit(bl);
break;
case SC_BLIND: /* 暗? */
if(tick < 1000)
tick = 30000;
tick -= tick*(status_get_lv(bl)/10 + status_get_int(bl)/15)/100;
if (tick < 5000) //Minimum 5 secs?
tick = 5000;
rate = 10*status_get_lv(bl) + 7*status_get_int(bl);
min = 5000; //Minimum 5 secs?
break;
case SC_BLEEDING:
tick -= tick*(status_get_lv(bl)/5 +status_get_vit(bl))/100;
if(tick < 10000) //Minimum bleed time is 10 secs or this sc does nothing! [Skotlex]
tick = 10000;
rate = 20*status_get_lv(bl) +100*status_get_vit(bl);
min = 10000; //Need a min of 10 secs for it to hurt at least once.
break;
case SC_SWOO:
if (status_get_mode(bl)&MD_BOSS)
tick /= 5; //Reduce skill's duration. But for how long?
tick /= 5; //TODO: Reduce skill's duration. But for how long?
break;
case SC_ANKLE:
tick -= status_get_agi(bl)*100;
if(status_get_mode(bl)&MD_BOSS) // Lasts 5 times less on bosses
tick /= 5;
rate = -100*status_get_agi(bl);
// Minimum trap time of 3+0.03*skilllv seconds [celest]
// Changed to 3 secs and moved from skill.c [Skotlex]
if (tick < 3000)
tick = 3000;
min = 3000;
break;
case SC_STOP:
// Unsure of this... but I get a feeling that agi reduces this
// (it was on Tiger Fist Code, but at -1 ms per 10 agi....
tick -= 100*status_get_agi(bl);
rate = -100*status_get_agi(bl);
break;
}
return tick;
if (rate) {
if (bl->type == BL_PC) {
if (battle_config.pc_sc_def_rate != 100)
rate = rate*battle_config.pc_sc_def_rate/100;
if (battle_config.pc_max_sc_def != 10000)
min = tick*(10000-battle_config.pc_max_sc_def)/10000;
} else {
if (battle_config.mob_sc_def_rate != 100)
rate = rate*battle_config.mob_sc_def_rate/100;
if (battle_config.mob_max_sc_def != 10000)
min = tick*(10000-battle_config.mob_max_sc_def)/10000;
}
if (rate >0)
tick -= tick*rate/10000;
else
tick -= rate;
}
return tick<min?min:tick;
}
/*==========================================
* Starts a status change.
@ -4089,8 +4123,8 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val
case SC_WARM: //SG skills [Komurka]
if (!(flag&4)) {
val2 = tick/1000;
tick = 1000;
val2 = tick/100;
tick = 100;
}
break;
@ -5099,9 +5133,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
if(sd){
int sp = 10+sc->data[SC_CHASEWALK].val1*2;
if (map_flag_gvg(sd->bl.m)) sp *= 5;
if (sd->status.sp > sp){
sd->status.sp -= sp; // update sp cost [Celest]
clif_updatestatus(sd,SP_SP);
if (pc_damage_sp(sd, sp, 0) > 0) {
if ((++sc->data[SC_CHASEWALK].val4) == 1) {
status_change_start(bl, SC_INCSTR,10000,
1<<(sc->data[SC_CHASEWALK].val1-1), 0, 0, 0,
@ -5163,7 +5195,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
map_foreachinarea( status_change_timer_sub,
bl->m, bl->x-sc->data[type].val4, bl->y-sc->data[type].val4, bl->x+sc->data[type].val4,bl->y+sc->data[type].val4,BL_CHAR,
bl,sc,type,tick);
sc->data[type].timer=add_timer(tick+1000, status_change_timer,bl->id, data);
sc->data[type].timer=add_timer(tick+100, status_change_timer,bl->id, data);
return 0;
}
break;
@ -5339,11 +5371,7 @@ int status_change_timer(int tid, unsigned int tick, int id, int data)
if (s && ((sc->data[type].val3 % s) == 0)) {
if (sc->data[SC_LONGING].timer != -1)
sp = s;
if (sp > sd->status.sp)
sp = sd->status.sp;
sd->status.sp -= sp;
clif_updatestatus(sd,SP_SP);
if (sd->status.sp <= 0)
if (pc_damage_sp(sd, sp, 0) <= 0)
break;
}
}
@ -5521,18 +5549,18 @@ int status_change_timer_sub(struct block_list *bl, va_list ap )
}
break;
case SC_WARM: //SG skills [Komurka]
if(battle_check_target( src,bl, BCT_ENEMY ) > 0) {
if(sd){
if(sd->status.sp<2) {
if(sc && sc->data[type].val2 &&
battle_check_target( src,bl, BCT_ENEMY ) > 0)
{
if(tsd)
//Only damage SP [Skotlex]
// case SG_SUN_WARM:
pc_damage_sp(tsd, 60, 0);
else { //Otherwise, Knockback attack.
if(sd && pc_damage_sp(sd, 2, 0) <= 0)
sd->sc.data[type].val2 = 0; //Makes it end on the next tick.
break;
}
sd->status.sp -= 2;
clif_updatestatus(sd,SP_SP);
skill_attack(BF_WEAPON,src,src,bl,sc->data[type].val3,sc->data[type].val1,tick,0);
}
skill_attack(BF_WEAPON,src,src,bl,
sc?sc->data[type].val3:SG_SUN_WARM,sc?sc->data[type].val1:1,
tick,0);
}
break;
case SC_CLOSECONFINE: