summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Changelog-Trunk.txt17
-rw-r--r--src/login_sql/login.c7
-rw-r--r--src/map/battle.c45
-rw-r--r--src/map/clif.c18
-rw-r--r--src/map/mob.c8
-rw-r--r--src/map/pc.c18
-rw-r--r--src/map/skill.c159
-rw-r--r--src/map/skill.h5
-rw-r--r--src/map/status.c22
-rw-r--r--src/map/unit.c6
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)
);
}