From ea2ae867ed32cdea9107b446ee7cdfe3a2be6d95 Mon Sep 17 00:00:00 2001 From: skotlex Date: Wed, 15 Feb 2006 18:56:54 +0000 Subject: - 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://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5288 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 37 +++++++----- src/map/battle.h | 6 +- src/map/charcommand.c | 8 +-- src/map/pc.c | 40 ++++++++++--- src/map/pc.h | 1 + src/map/skill.c | 128 ++++++++++++++++++++---------------------- src/map/status.c | 152 ++++++++++++++++++++++++++++++-------------------- 7 files changed, 215 insertions(+), 157 deletions(-) (limited to 'src') diff --git a/src/map/battle.c b/src/map/battle.c index 244cbe960..a0a6d932d 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -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; diff --git a/src/map/battle.h b/src/map/battle.h index fc4af0788..ba631bdca 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -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); diff --git a/src/map/charcommand.c b/src/map/charcommand.c index 69a5a9ac4..4e2f3f2c3 100644 --- a/src/map/charcommand.c +++ b/src/map/charcommand.c @@ -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) diff --git a/src/map/pc.c b/src/map/pc.c index fe435d73f..7604c8dd7 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -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; diff --git a/src/map/pc.h b/src/map/pc.h index 8e695cafc..4701f781e 100644 --- a/src/map/pc.h +++ b/src/map/pc.h @@ -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); diff --git a/src/map/skill.c b/src/map/skill.c index 24298fb82..fd7f676a2 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -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; - - if (auto_skillid == skillid) //Prevents skill from retriggering themselves. [Skotlex] - continue; + skill = (sd->autospell[i].id > 0) ? sd->autospell[i].id : -sd->autospell[i].id; + //Prevents skill from retriggering themselves. [Skotlex] + if (skill == skillid) + continue; - 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; + //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; - 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: /* グランドク?ス */ @@ -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: diff --git a/src/map/status.c b/src/map/status.c index f7f88aaa9..bb7fd47a0 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -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 tickdata[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: -- cgit v1.2.3-70-g09d2