From c09b285a4ed34188ae0f4d13a9f235352e12009e Mon Sep 17 00:00:00 2001 From: skotlex Date: Thu, 30 Mar 2006 15:50:54 +0000 Subject: - the auth function in login.c won't jstrescapecpy passwords that were encrypted. - Moved the Endure and Gravitation sc ends to battle_damage from pc_damage. - Endure level 11 and above are now considered infinite-endure. - Set the minimum pet hungry delay to 10 - modified function skill_delayfix to only receive skill/lv, actual time is now always acquired from skill_get_delay. It also now will never return a value below min_skill_delay_limit. - Modified brandish spear so you won't see the skill-animation for every targetted mob. Also cleaned it up to use map_foreachincell calls. - splitted skill_cast_fix into skill_cast_fix and skill_cast_fix_sc, the first does cast adjustments based on dex and server settings, the later only based on sc changes. Mobs use the later while everyone else use the former (which invokes the later when appropiate) - Added the Steel Body icon to auto-berserk. - Now you can't cast auto-counter while the previous one is active. - For the duration of Berserk, infinite-endure is activated. - Added Veider's suggestion to do a hack-report when players request the name of an invisible/cloaked character. git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5813 54d463be-8e91-2dee-dedb-b68131a5f0ec --- Changelog-Trunk.txt | 17 ++++++ src/login_sql/login.c | 7 ++- src/map/battle.c | 45 +++++++++----- src/map/clif.c | 18 +++++- src/map/mob.c | 8 +-- src/map/pc.c | 18 +----- src/map/skill.c | 159 ++++++++++++++++++++++++-------------------------- src/map/skill.h | 5 +- src/map/status.c | 22 ++++--- src/map/unit.c | 6 +- 10 files changed, 173 insertions(+), 132 deletions(-) diff --git a/Changelog-Trunk.txt b/Changelog-Trunk.txt index 8ee47f81e..39755fcd4 100644 --- a/Changelog-Trunk.txt +++ b/Changelog-Trunk.txt @@ -4,6 +4,23 @@ 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. 2006/03/30 + * the auth function in login.c won't jstrescapecpy passwords that were + encrypted. Thanks to foobar. (but are still more cases to check for? Dunno, + the code is kinda long...) [Skotlex] + * Endure level 11 and above are now considered infinite-endure, and invoked + when Berserk is active. [Skotlex] + * Set the minimum pet hungry delay to 10 [Skotlex] + * modified functions skill_delayfix and skill_castfix to reduce number of + arguments. Added function skill_castfix_sc for mobs (who only get status + change cast reductions, not dex based ones). Also, skill_delayfix will + never return a value below min_skill_delay_limit. [Skotlex] + * Modified brandish spear so you won't see the skill-animation for every + targetted mob. [Skotlex] + * Added the Steel Body icon to auto-berserk. [Skotlex] + * Now you can't cast auto-counter while the previous one is active. + [Skotlex] + * Added Veider's suggestion to do a hack-report when players request the + name of an invisible/cloaked character. [Skotlex] * Added execution of OnInterIfInit, OnCharIfInit and OnInterIfInitOnce on script reload. [Lance] * Cleaned up mistakes in irc.c [Lance] diff --git a/src/login_sql/login.c b/src/login_sql/login.c index edc78d48f..1fad6f4dc 100644 --- a/src/login_sql/login.c +++ b/src/login_sql/login.c @@ -598,7 +598,12 @@ int mmo_auth( struct mmo_account* account , int fd){ strftime(tmpstr, 24, "%Y-%m-%d %H:%M:%S",localtime(&raw_time)); jstrescapecpy(t_uid,account->userid); - jstrescapecpy(t_pass, account->passwd); + + if (account.passwdenc==PASSWORDENC) { + memset(t_pass, 0, sizeof(t_pass)); + memcpy(t_pass, account->passwd, strlen(account->passwd)); + } else + jstrescapecpy(t_pass, account->passwd); // make query diff --git a/src/map/battle.c b/src/map/battle.c index dbd706e07..479a2c0e1 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -160,12 +160,12 @@ int battle_delay_damage (unsigned int tick, struct block_list *src, struct block } // Žΐ?Ϋ‚ΙHP‚π‘€?μ -int battle_damage(struct block_list *bl,struct block_list *target,int damage, int flag) +int battle_damage(struct block_list *src,struct block_list *target,int damage, int flag) { struct map_session_data *sd = NULL; struct status_change *sc; - nullpo_retr(0, target); //bl‚ΝNULL‚ΕŒΔ‚Ξ‚κ‚ι‚±‚Ζ‚ͺ‚ ‚ι‚Μ‚Ε‘Ό‚Εƒ`ƒFƒbƒN + nullpo_retr(0, target); //stc‚ΝNULL‚ΕŒΔ‚Ξ‚κ‚ι‚±‚Ζ‚ͺ‚ ‚ι‚Μ‚Ε‘Ό‚Εƒ`ƒFƒbƒN sc = status_get_sc(target); @@ -174,16 +174,14 @@ int battle_damage(struct block_list *bl,struct block_list *target,int damage, in target->type == BL_PET) return 0; - if (bl) { - if (bl->prev == NULL) + if (src) { + if (src->prev == NULL) return 0; - if (bl->type == BL_PC) { - nullpo_retr(0, sd = (struct map_session_data *)bl); - } + BL_CAST(BL_PC, src, sd); } if (damage < 0) - return battle_heal(bl,target,-damage,0,flag); + return battle_heal(src,target,-damage,0,flag); if (!flag && sc && sc->count) { // “€Œ‹?A?Ξ‰»?A?‡–°‚π?Α‹Ž @@ -205,14 +203,30 @@ int battle_damage(struct block_list *bl,struct block_list *target,int damage, in status_change_end(target, SC_CLOAKING, -1); if (sc->data[SC_CHASEWALK].timer != -1) status_change_end(target, SC_CHASEWALK, -1); + if (sc->data[SC_ENDURE].timer != -1 && sc->data[SC_ENDURE].val1 <= 10) { + //Endure count is only reduced by non-players on non-gvg maps. + //if val1 is greater than 10, this is infinite endure. [Skotlex] + if (src && src->type != BL_PC && !map_flag_gvg(target->m) + && --(sc->data[SC_ENDURE].val2) < 0) + status_change_end(target, SC_ENDURE, -1); + } + if (sc->data[SC_GRAVITATION].timer != -1 && + sc->data[SC_GRAVITATION].val3 == BCT_SELF) { + struct skill_unit_group *sg = (struct skill_unit_group *)sc->data[SC_GRAVITATION].val4; + if (sg) { + skill_delunitgroup(sg); + sc->data[SC_GRAVITATION].val4 = 0; + status_change_end(target, SC_GRAVITATION, -1); + } + } } - - if (sc && sc->count && sc->data[SC_DEVOTION].val1 && bl && battle_getcurrentskill(bl) != PA_PRESSURE) + + if (sc && sc->count && sc->data[SC_DEVOTION].val1 && src && battle_getcurrentskill(src) != PA_PRESSURE) { //Devotion only works on attacks from a source (to prevent it from absorbing coma) [Skotlex] struct map_session_data *sd2 = map_id2sd(sc->data[SC_DEVOTION].val1); if (sd2 && sd2->devotion[sc->data[SC_DEVOTION].val2] == target->id) { - clif_damage(bl, &sd2->bl, gettick(), 0, 0, damage, 0, 0, 0); + clif_damage(src, &sd2->bl, gettick(), 0, 0, damage, 0, 0, 0); pc_damage(&sd2->bl, sd2, damage); return 0; } else @@ -220,11 +234,11 @@ int battle_damage(struct block_list *bl,struct block_list *target,int damage, in } unit_skillcastcancel(target, 2); if (target->type == BL_MOB) { - return mob_damage(bl,(TBL_MOB*)target, damage,0); + return mob_damage(src,(TBL_MOB*)target, damage,0); } else if (target->type == BL_PC) { - return pc_damage(bl,(TBL_PC*)target,damage); + return pc_damage(src,(TBL_PC*)target,damage); } else if (target->type == BL_SKILL) - return skill_unit_ondamaged((struct skill_unit *)target, bl, damage, gettick()); + return skill_unit_ondamaged((struct skill_unit *)target, src, damage, gettick()); return 0; } @@ -4305,6 +4319,9 @@ void battle_validate_conf() { if(battle_config.pet_support_min_friendly > 950) //Capped to 950/1000 [Skotlex] battle_config.pet_support_min_friendly = 950; + if(battle_config.pet_hungry_delay_rate < 10) + battle_config.pet_hungry_delay_rate=10; + if(battle_config.pet_max_atk1 > battle_config.pet_max_atk2) //Skotlex battle_config.pet_max_atk1 = battle_config.pet_max_atk2; diff --git a/src/map/clif.c b/src/map/clif.c index 7722c70ca..38a4ec530 100644 --- a/src/map/clif.c +++ b/src/map/clif.c @@ -9109,6 +9109,7 @@ void check_fake_id(int fd, struct map_session_data *sd, int target_id) { void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { int account_id; struct block_list* bl; + struct status_change *sc; RFIFOHEAD(fd); account_id = RFIFOL(fd,packet_db[sd->packet_ver][RFIFOW(fd,0)].pos[0]); @@ -9116,8 +9117,23 @@ void clif_parse_GetCharNameRequest(int fd, struct map_session_data *sd) { account_id-=account_id*2; //Is this possible? Lagged clients could request names of already gone mobs/players. [Skotlex] - if ((bl = map_id2bl(account_id)) != NULL) + if ((bl = map_id2bl(account_id)) != NULL) { + sc = status_get_sc(bl); + if (sc && ( + (sc->option&(OPTION_HIDE|OPTION_CLOAK|OPTION_CHASEWALK) && !sd->special_state.intravision) || + sc->option&OPTION_INVISIBLE) + ) { + //Asked name of invisible player, this shouldn't be possible! + //Possible bot? Thanks to veider and qspirit + unsigned char gm_msg[256]; + sprintf(gm_msg, "Hack on NameRequest: character '%s' (account: %d) requests name of invisible chars.", sd->status.name, sd->status.account_id); + ShowWarning(gm_msg); + // information is sended to all online GM + intif_wis_message_to_gm(wisp_server_name, battle_config.hack_info_GM_level, gm_msg); + return; + } clif_charnameack(fd, bl); + } } /*========================================== diff --git a/src/map/mob.c b/src/map/mob.c index ffbbfbd43..30021c345 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -2836,7 +2836,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) } md->skillidx = i; flag = unit_skilluse_pos2(&md->bl, x, y, ms[i].skill_id, ms[i].skill_lv, - skill_castfix(&md->bl,ms[i].skill_id, ms[i].skill_lv, ms[i].casttime), ms[i].cancel); + skill_castfix_sc(&md->bl, ms[i].casttime), ms[i].cancel); if (!flag) md->skillidx = -1; //Skill failed. return flag; } else { @@ -2867,7 +2867,7 @@ int mobskill_use(struct mob_data *md, unsigned int tick, int event) } md->skillidx = i; flag = (bl && unit_skilluse_id2(&md->bl, bl->id, ms[i].skill_id, ms[i].skill_lv, - skill_castfix(&md->bl,ms[i].skill_id, ms[i].skill_lv, ms[i].casttime), ms[i].cancel)); + skill_castfix_sc(&md->bl,ms[i].casttime), ms[i].cancel)); if (!flag) md->skillidx = -1; return flag; } else { @@ -3016,8 +3016,8 @@ int mob_clone_spawn(struct map_session_data *sd, char *map, int x, int y, const ms[i].permillage = 500; //Default chance for moving/idle skills. ms[i].emotion = -1; ms[i].cancel = 0; - ms[i].delay = 5000+skill_delayfix(&sd->bl,skill_id, ms[i].skill_lv, 0); - ms[i].casttime = skill_castfix(&sd->bl,skill_id, ms[i].skill_lv, 0); + ms[i].delay = 5000+skill_delayfix(&sd->bl,skill_id, ms[i].skill_lv); + ms[i].casttime = skill_castfix(&sd->bl,skill_id, ms[i].skill_lv); inf = skill_get_inf(skill_id); if (inf&INF_ATTACK_SKILL) { diff --git a/src/map/pc.c b/src/map/pc.c index 57f4b8d50..815a03391 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -1475,7 +1475,7 @@ int pc_bonus(struct map_session_data *sd,int type,int val) if(sd->state.lr_flag != 2) { sd->special_state.infinite_endure = 1; if (sd->sc.data[SC_ENDURE].timer == -1) - sc_start(&sd->bl, SC_ENDURE,100,1,0); + sc_start(&sd->bl,SC_ENDURE,100,11,600000); } break; case SP_INTRAVISION: // Maya Purple Card effect allowing to see Hiding/Cloaking people [DracoRPG] @@ -4608,22 +4608,6 @@ int pc_damage(struct block_list *src,struct map_session_data *sd,int damage) skill_rest(sd,0); } - // ? ‚’‚Δ‚’‚½‚η‘«‚πŽ~‚ί‚ι - if (sd->sc.count) { - if (sd->sc.data[SC_ENDURE].timer != -1 && (src != NULL && src->type == BL_MOB) && !map_flag_gvg(sd->bl.m)) { - if (!sd->special_state.infinite_endure && (--sd->sc.data[SC_ENDURE].val2) < 0) - status_change_end(&sd->bl, SC_ENDURE, -1); - } - if (sd->sc.data[SC_GRAVITATION].timer != -1 && - sd->sc.data[SC_GRAVITATION].val3 == BCT_SELF) { - struct skill_unit_group *sg = (struct skill_unit_group *)sd->sc.data[SC_GRAVITATION].val4; - if (sg) { - skill_delunitgroup(sg); - status_change_end(&sd->bl, SC_GRAVITATION, -1); - } - } - } - // ‰‰‘t/ƒ_ƒ“ƒX‚Μ’†? if(damage > sd->status.max_hp>>2) skill_stop_dancing(&sd->bl); diff --git a/src/map/skill.c b/src/map/skill.c index dbeee7879..6ccb90b2e 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1779,7 +1779,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds else //‰ρ•œSP+Œ»έ‚ΜSP‚ͺMSP‚ζ‚菬‚³‚’κ‡‚Ν‰ρ•œSP‚π‰ΑŽZ tsd->status.sp += sp; clif_heal(tsd->fd,SP_SP,sp); //SP‰ρ•œƒGƒtƒFƒNƒg‚Μ•\Ž¦ - tsd->ud.canact_tick = tick + skill_delayfix(bl, SA_MAGICROD, sc->data[SC_MAGICROD].val1, skill_get_delay(SA_MAGICROD, sc->data[SC_MAGICROD].val1)); + tsd->ud.canact_tick = tick + skill_delayfix(bl, SA_MAGICROD, sc->data[SC_MAGICROD].val1); } clif_skill_nodamage(bl,bl,SA_MAGICROD,sc->data[SC_MAGICROD].val1,1); //ƒ}ƒWƒbƒNƒƒbƒhƒGƒtƒFƒNƒg‚π•\Ž¦ } @@ -1911,6 +1911,7 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds switch(skillid){ //Skills who's damage should't show any skill-animation. case SM_MAGNUM: + case KN_BRANDISHSPEAR: case AS_SPLASHER: case ASC_METEORASSAULT: case SG_SUN_WARM: @@ -3978,11 +3979,12 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in ar=skilllv/3; skill_brandishspear_first(&tc,dir,x,y); skill_brandishspear_dir(&tc,dir,4); + clif_skill_nodamage(src,bl,skillid,skilllv,1); /* ”Ν?‡C */ if(skilllv == 10){ for(c=1;c<4;c++){ - map_foreachinarea(skill_area_sub, - bl->m,tc.val1[c],tc.val2[c],tc.val1[c],tc.val2[c],BL_CHAR, + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c],tc.val2[c],BL_CHAR, src,skillid,skilllv,tick, flag|BCT_ENEMY|n, skill_castend_damage_id); } @@ -3998,8 +4000,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in if(skilllv > 3){ for(c=0;c<5;c++){ - map_foreachinarea(skill_area_sub, - bl->m,tc.val1[c],tc.val2[c],tc.val1[c],tc.val2[c],BL_CHAR, + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c],tc.val2[c],BL_CHAR, src,skillid,skilllv,tick, flag|BCT_ENEMY|n, skill_castend_damage_id); if(skilllv > 6 && n==3 && c==4){ @@ -4011,8 +4013,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in /* ”Ν?‡@ */ for(c=0;c<10;c++){ if(c==0||c==5) skill_brandishspear_dir(&tc,dir,-1); - map_foreachinarea(skill_area_sub, - bl->m,tc.val1[c%5],tc.val2[c%5],tc.val1[c%5],tc.val2[c%5],BL_CHAR, + map_foreachincell(skill_area_sub, + bl->m,tc.val1[c%5],tc.val2[c%5],BL_CHAR, src,skillid,skilllv,tick, flag|BCT_ENEMY|1, skill_castend_damage_id); } @@ -5723,7 +5725,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) if (ud->skillid == SA_MAGICROD) ud->canact_tick = tick; else - ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv, skill_get_delay(ud->skillid, ud->skilllv)); + ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); unit_set_walkdelay(src, tick, skill_get_walkdelay(ud->skillid, ud->skilllv), 1); if(battle_config.skill_log && battle_config.skill_log&src->type) @@ -5831,7 +5833,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) ShowInfo("Type %d, ID %d skill castend pos [id =%d, lv=%d, (%d,%d)]\n", src->type, src->id, ud->skillid, ud->skilllv, ud->skillx, ud->skilly); unit_stop_walking(src,0); - ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv, skill_get_delay(ud->skillid, ud->skilllv)); + ud->canact_tick = tick + skill_delayfix(src, ud->skillid, ud->skilllv); unit_set_walkdelay(src, tick, skill_get_walkdelay(ud->skillid, ud->skilllv), 1); skill_castend_pos2(src,ud->skillx,ud->skilly,ud->skillid,ud->skilllv,tick,0); @@ -8264,105 +8266,97 @@ int skill_check_condition(struct map_session_data *sd,int skill, int lv, int typ * ‰r?₯ŽžŠΤŒvŽZ *------------------------------------------ */ -int skill_castfix( struct block_list *bl, int skill_id, int skill_lv, int time) +int skill_castfix( struct block_list *bl, int skill_id, int skill_lv) { struct status_change *sc; int castnodex = skill_get_castnodex(skill_id, skill_lv); - + int time = skill_get_cast(skill_id, skill_lv); + struct map_session_data *sd; + nullpo_retr(0, bl); + BL_CAST(BL_PC, bl, sd); + + // calculate base cast time (reduced by dex) + if (!(castnodex&1)) { // castnodex&~1? wtf. [blackhole89] + int scale = battle_config.castrate_dex_scale - status_get_dex(bl); + if (scale > 0) // not instant cast + time = time * scale / battle_config.castrate_dex_scale; + else return 0; // instant cast + } - if (bl->type == BL_PC){ - struct map_session_data *sd = (struct map_session_data*)bl; - nullpo_retr(0, sd); + // calculate cast time reduced by card bonuses + if (sd && sd->castrate != 100) + time = time * sd->castrate / 100; - // calculate base cast time (reduced by dex) - if (!(castnodex&1)) { // castnodex&~1? wtf. [blackhole89] - int scale = battle_config.castrate_dex_scale - status_get_dex(bl); - if (scale > 0) // not instant cast - time = time * scale / battle_config.castrate_dex_scale; - else return 0; // instant cast - } + // config cast time multiplier + if (battle_config.cast_rate != 100) + time = time * battle_config.cast_rate / 100; - // config cast time multiplier - if (battle_config.cast_rate != 100) - time = time * battle_config.cast_rate / 100; + // calculate cast time reduced by skill bonuses + if (!(castnodex&2)) + time = skill_castfix_sc(bl, time); - // calculate cast time reduced by card bonuses - if (sd->castrate != 100) - time -= time * (100 - sd->castrate) / 100; - } else if (bl->type == BL_PET) { //Skotlex: Simple scaling - if (!(castnodex&1)) { - int scale = battle_config.castrate_dex_scale - status_get_dex(bl); - if (scale > 0) // not instant cast - time = time * scale / battle_config.castrate_dex_scale; - else return 0; // instant cast - } - if (battle_config.cast_rate != 100) - time = time * battle_config.cast_rate / 100; - } + // return final cast time + return (time > 0) ? time : 0; +} - if (!(castnodex&2)) - { // calculate cast time reduced by skill bonuses - sc = status_get_sc(bl); - /* ƒTƒtƒ‰ƒMƒEƒ€ */ - if (sc && sc->count) { - if (sc->data[SC_SUFFRAGIUM].timer != -1) { - time -= time * (sc->data[SC_SUFFRAGIUM].val1 * 15) / 100; - status_change_end(bl, SC_SUFFRAGIUM, -1); - } - /* ƒuƒ‰ƒM‚ΜŽ? */ - if (sc->data[SC_POEMBRAGI].timer != -1) - time -= time * sc->data[SC_POEMBRAGI].val2 / 100; +/*========================================== + * Does cast-time reductions based on sc data. + *------------------------------------------ + */ +int skill_castfix_sc(struct block_list *bl, int time) +{ + struct status_change *sc = status_get_sc(bl); + + if (time <= 0) return 0; + + if (sc && sc->count) { + if (sc->data[SC_SUFFRAGIUM].timer != -1) { + time -= time * (sc->data[SC_SUFFRAGIUM].val1 * 15) / 100; + status_change_end(bl, SC_SUFFRAGIUM, -1); } + if (sc->data[SC_POEMBRAGI].timer != -1) + time -= time * sc->data[SC_POEMBRAGI].val2 / 100; } - // return final cast time return (time > 0) ? time : 0; } + /*========================================== * ƒfƒBƒŒƒCŒvŽZ *------------------------------------------ */ -int skill_delayfix( struct block_list *bl, int skill_id, int skill_lv, int time ) +int skill_delayfix(struct block_list *bl, int skill_id, int skill_lv) { - struct status_change *sc; int delaynodex = skill_get_delaynodex(skill_id, skill_lv); - + int time = skill_get_delay(skill_id, skill_lv); + nullpo_retr(0, bl); - if (bl->type == BL_PC){ - struct map_session_data *sd = (struct map_session_data*)bl; - nullpo_retr(0, sd); - - // instant cast attack skills depend on aspd as delay [celest] - if (time == 0) { - if (skill_get_type(skill_id) == BF_WEAPON && !(skill_get_nk(skill_id)&NK_NO_DAMAGE)) - time = status_get_amotion(bl); //Use attack animation as default delay. - else - time = 300; // default delay, according to official servers - } else if (time < 0) - time = -time + status_get_amotion(bl); // if set to <0, the attack motion is added. - - if (battle_config.delay_dependon_dex && !(delaynodex&1)) - { // if skill casttime is allowed to be reduced by dex - int scale = battle_config.castrate_dex_scale - status_get_dex(bl); - if (scale > 0) - time = time * scale / battle_config.castrate_dex_scale; - else - time = battle_config.min_skill_delay_limit; - } + // instant cast attack skills depend on aspd as delay [celest] + if (time == 0) { + if (skill_get_type(skill_id) == BF_WEAPON && !(skill_get_nk(skill_id)&NK_NO_DAMAGE)) + time = status_get_amotion(bl); //Use attack animation as default delay. + else + time = 300; // default delay, according to official servers + } else if (time < 0) + time = -time + status_get_amotion(bl); // if set to <0, the attack motion is added. - if (battle_config.delay_rate != 100) - time = time * battle_config.delay_rate / 100; + if (battle_config.delay_dependon_dex && !(delaynodex&1)) + { // if skill casttime is allowed to be reduced by dex + int scale = battle_config.castrate_dex_scale - status_get_dex(bl); + if (scale > 0) + time = time * scale / battle_config.castrate_dex_scale; + } - if (sd->delayrate != 100) - time = time * sd->delayrate / 100; + if (bl->type == BL_PC && ((TBL_PC*)bl)->delayrate != 100) + time = time * ((TBL_PC*)bl)->delayrate / 100; - if (time < battle_config.min_skill_delay_limit) // check minimum skill delay - time = battle_config.min_skill_delay_limit; - } + if (battle_config.delay_rate != 100) + time = time * battle_config.delay_rate / 100; if (!(delaynodex&2)) { /* ƒuƒ‰ƒM‚ΜŽ? */ + struct status_change *sc; sc= status_get_sc(bl); if (sc && sc->count) { if (sc->data[SC_POEMBRAGI].timer != -1) @@ -8381,7 +8375,8 @@ int skill_delayfix( struct block_list *bl, int skill_id, int skill_lv, int time } } - return (time > 0) ? time : 0; + return (time < battle_config.min_skill_delay_limit)? + battle_config.min_skill_delay_limit:time; } /*========================================= diff --git a/src/map/skill.h b/src/map/skill.h index 4624e66b9..174a224b4 100644 --- a/src/map/skill.h +++ b/src/map/skill.h @@ -188,8 +188,9 @@ int skill_clear_element_field(struct block_list *bl); int skill_unit_ondamaged(struct skill_unit *src,struct block_list *bl, int damage,unsigned int tick); -int skill_castfix( struct block_list *bl, int skill_id, int skill_lv, int time); -int skill_delayfix( struct block_list *bl, int skill_id, int skill_lv, int time); +int skill_castfix( struct block_list *bl, int skill_id, int skill_lv); +int skill_castfix_sc( struct block_list *bl, int time); +int skill_delayfix( struct block_list *bl, int skill_id, int skill_lv); int skill_check_condition( struct map_session_data *sd,int skill, int lv, int type); int skill_check_pc_partner(struct map_session_data *sd, int skill_id, int* skill_lv, int range, int cast_flag); int skill_check_unit_range(int m,int x,int y,int skillid, int skilllv); diff --git a/src/map/status.c b/src/map/status.c index 72934420c..9c7cfdaa0 100644 --- a/src/map/status.c +++ b/src/map/status.c @@ -128,7 +128,7 @@ void initChangeTables(void) { set_sc(AS_VENOMDUST, SC_POISON, SI_BLANK); set_sc(AS_SPLASHER, SC_SPLASHER, SI_BLANK); set_sc(NV_TRICKDEAD, SC_TRICKDEAD, SI_TRICKDEAD); - set_sc(SM_AUTOBERSERK, SC_AUTOBERSERK, SI_BLANK); + set_sc(SM_AUTOBERSERK, SC_AUTOBERSERK, SI_STEELBODY); set_sc(TF_SPRINKLESAND, SC_BLIND, SI_BLANK); set_sc(TF_THROWSTONE, SC_STUN, SI_BLANK); set_sc(MC_LOUD, SC_LOUD, SI_LOUD); @@ -404,7 +404,7 @@ int status_check_skilluse(struct block_list *src, struct block_list *target, int { if ( (sc->data[SC_TRICKDEAD].timer != -1 && skill_num != NV_TRICKDEAD) - || (sc->data[SC_AUTOCOUNTER].timer != -1 && skill_num != KN_AUTOCOUNTER) + || sc->data[SC_AUTOCOUNTER].timer != -1 || (sc->data[SC_GOSPEL].timer != -1 && sc->data[SC_GOSPEL].val4 == BCT_SELF && skill_num != PA_GOSPEL) || (sc->data[SC_GRAVITATION].timer != -1 && sc->data[SC_GRAVITATION].val3 == BCT_SELF && skill_num != HW_GRAVITATION) ) @@ -3081,9 +3081,11 @@ int status_get_dmotion(struct block_list *bl) else return 2000; - if(sc && sc->count && (sc->data[SC_ENDURE].timer!=-1 || sc->data[SC_CONCENTRATION].timer!=-1 || sc->data[SC_BERSERK].timer!=-1)) - if (!map_flag_gvg(bl->m)) //Only works on non-gvg grounds. [Skotlex] - return 0; + if(sc && sc->count + && (sc->data[SC_ENDURE].timer!=-1 || sc->data[SC_CONCENTRATION].timer!=-1) + && !map_flag_gvg(bl->m) //Only works on non-gvg grounds. [Skotlex] + ) + return 0; return ret; } @@ -4176,6 +4178,8 @@ int status_change_start(struct block_list *bl,int type,int rate,int val1,int val } if (!(flag&4)) tick = 10000; + if (sc->data[SC_ENDURE].timer == -1 || sc->data[SC_ENDURE].val1 <= 10) + sc_start(bl, SC_ENDURE, 100, 11, tick); calc_flag = 1; break; @@ -5014,9 +5018,10 @@ int status_change_end( struct block_list* bl , int type,int tid ) sd->status.hp = 100; clif_updatestatus(sd,SP_HP); } + if(sc->data[SC_ENDURE].timer != -1) + status_change_end(bl, SC_ENDURE, -1); calc_flag = 1; break; - case SC_GRAVITATION: if (sc->data[type].val3 == BCT_SELF) { struct unit_data *ud = unit_bl2ud(bl); @@ -5310,8 +5315,9 @@ int status_change_timer(int tid, unsigned int tick, int id, int data) break; case SC_ENDURE: /* ƒCƒ“ƒfƒ…ƒA */ - if(sd && sd->special_state.infinite_endure) { - sc->data[type].timer=add_timer( 1000*60+tick,status_change_timer, bl->id, data ); + if(sc->data[type].val1 > 10 || (sd && sd->special_state.infinite_endure)) + { + sc->data[type].timer=add_timer(1000*60+tick,status_change_timer, bl->id, data); return 0; } break; diff --git a/src/map/unit.c b/src/map/unit.c index fee09279c..e441bc693 100644 --- a/src/map/unit.c +++ b/src/map/unit.c @@ -524,7 +524,7 @@ int unit_skilluse_id(struct block_list *src, int target_id, int skill_num, int s return unit_skilluse_id2( src, target_id, skill_num, skill_lv, - skill_castfix(src, skill_num, skill_lv, skill_get_cast(skill_num, skill_lv)), + skill_castfix(src, skill_num, skill_lv), skill_get_castcancel(skill_num) ); } @@ -803,7 +803,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, int skill_num, int case ALL_RESURRECTION: /* ƒŠƒUƒŒƒNƒVƒ‡ƒ“ */ if(battle_check_undead(status_get_race(target),status_get_elem_type(target))){ /* “G‚ͺƒAƒ“ƒfƒbƒh‚Θ‚η */ temp=1; /* ƒ^[ƒ“ƒAƒ“ƒfƒbƒg‚Ζ“―‚Ά‰r₯ŽžŠΤ */ - casttime = skill_castfix(src, PR_TURNUNDEAD, skill_lv, skill_get_cast(PR_TURNUNDEAD, skill_lv)); + casttime = skill_castfix(src, PR_TURNUNDEAD, skill_lv); } break; case MO_FINGEROFFENSIVE: /* Žw’e */ @@ -906,7 +906,7 @@ int unit_skilluse_pos(struct block_list *src, int skill_x, int skill_y, int skil return 0; return unit_skilluse_pos2( src, skill_x, skill_y, skill_num, skill_lv, - skill_castfix(src, skill_num, skill_lv, skill_get_cast(skill_num, skill_lv)), + skill_castfix(src, skill_num, skill_lv), skill_get_castcancel(skill_num) ); } -- cgit v1.2.3-70-g09d2