From e27cd1c1b31aa3cecf2006de64f2b95f90bcd7cb Mon Sep 17 00:00:00 2001 From: skotlex Date: Sat, 4 Mar 2006 04:48:30 +0000 Subject: - Fixed missing baby-dancer job in exp2.txt - Added function battle_set_walkdelay in charge of updating walkdelays of characters based on two criterias: when the delay is induced by damage, if the current walk delay isn't over yet, do not update it. If the delay is instead caused by a skill, then the current walk delay cannot be decreased, only increased. - Removed the canmove tick reset on skill cast cancel; likewise it isn't updated on begin casting. pc_can_move uses a skilltimer check to know whether you can move or not. - Added GrandCross's can't move delay of 900ms to skill_cast_db - Added Finger Offensive's can't move delay of 200ms/lv to skill_cast_db git-svn-id: https://rathena.svn.sourceforge.net/svnroot/rathena/trunk@5457 54d463be-8e91-2dee-dedb-b68131a5f0ec --- src/map/battle.c | 84 ++++++++++++++++++++++++++------------------------------ src/map/battle.h | 1 + src/map/mob.c | 2 +- src/map/npc.c | 8 ++---- src/map/pc.c | 3 ++ src/map/skill.c | 52 +++++++++++++++++------------------ 6 files changed, 71 insertions(+), 79 deletions(-) (limited to 'src/map') diff --git a/src/map/battle.c b/src/map/battle.c index d205034d4..79ec8bc68 100644 --- a/src/map/battle.c +++ b/src/map/battle.c @@ -439,34 +439,52 @@ int battle_attr_fix(struct block_list *src, struct block_list *target, int damag return damage*ratio/100; } -static int battle_walkdelay_sub(int tid, unsigned int tick, int id, int data) +/*========================================== + * Applies walk delay to character, considering that + * if type is 0, this is a damage induced delay: if previous delay is active, do not change it. + * if type is 1, this is a skill induced delay: walk-delay may only be increased, not decreased. + *------------------------------------------ + */ +int battle_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type) { - struct block_list *bl = map_id2bl(id); - if (!bl || status_isdead(bl)) - return 0; + unsigned int *canmove_tick=NULL; + if (delay <= 0) return 0; switch (bl->type) { case BL_PC: - { - struct map_session_data *sd = (struct map_session_data*)bl; - if (sd->walktimer != -1) - pc_stop_walking (sd,3); - if (sd->canmove_tick < tick) - sd->canmove_tick = tick + data; - } + canmove_tick = &((TBL_PC*)bl)->canmove_tick; break; case BL_MOB: - { - struct mob_data *md = (struct mob_data*)bl; - if (md->state.state == MS_WALK) - mob_stop_walking(md,3); - if (md->canmove_tick < tick) - md->canmove_tick = tick + data; - } + canmove_tick = &((TBL_MOB*)bl)->canmove_tick; break; + case BL_NPC: + canmove_tick = &((TBL_NPC*)bl)->canmove_tick; + break; + } + if (!canmove_tick) + return 0; + if (type) { + if (DIFF_TICK(*canmove_tick, tick+delay) > 0) + return 0; + } else { + if (DIFF_TICK(*canmove_tick, tick) > 0) + return 0; } + *canmove_tick = tick + delay; + return 1; +} + +static int battle_walkdelay_sub(int tid, unsigned int tick, int id, int data) +{ + struct block_list *bl = map_id2bl(id); + if (!bl || status_isdead(bl)) + return 0; + + if (battle_set_walkdelay(bl, tick, data, 0)) + battle_stopwalking(bl,3); return 0; } + /*========================================== * Applies walk delay based on attack type. [Skotlex] *------------------------------------------ @@ -489,31 +507,10 @@ int battle_walkdelay(struct block_list *bl, unsigned int tick, int adelay, int d if (delay <= 0) return 0; - //See if it makes sense to set this trigger. - switch (bl->type) { - case BL_PC: - { - struct map_session_data *sd = (struct map_session_data*)bl; - if (DIFF_TICK(sd->canmove_tick, tick+adelay) > 0) - return 0; - if (!adelay) //No need of timer. - sd->canmove_tick = tick + delay; - break; - } - case BL_MOB: - { - struct mob_data *md = (struct mob_data*)bl; - if (DIFF_TICK(md->canmove_tick, tick+adelay) > 0) - return 0; - if (!adelay) //No need of timer. - md->canmove_tick = tick + delay; - break; - } - default: - return 0; - } if (adelay > 0) add_timer(tick+adelay, battle_walkdelay_sub, bl->id, delay); + else + battle_set_walkdelay(bl, tick, delay, 0); return 1; } @@ -580,10 +577,7 @@ int battle_calc_damage(struct block_list *src,struct block_list *bl,int damage,i delay = 200; else delay = 100; - if(sd) - sd->canmove_tick = gettick() + delay; - else if(md) - md->canmove_tick = gettick() + delay; + battle_set_walkdelay(bl, gettick(), delay, 1); if(sc->data[SC_SHRINK].timer != -1 && rand()%100<5*sc->data[SC_AUTOGUARD].val1) skill_blown(bl,src,skill_get_blewcount(CR_SHRINK,1)); diff --git a/src/map/battle.h b/src/map/battle.h index 512179482..786db1d66 100644 --- a/src/map/battle.h +++ b/src/map/battle.h @@ -54,6 +54,7 @@ int battle_heal(struct block_list *bl,struct block_list *target,int hp,int sp,in int battle_stopattack(struct block_list *bl); int battle_iswalking(struct block_list *bl); int battle_stopwalking(struct block_list *bl,int type); +int battle_set_walkdelay(struct block_list *bl, unsigned int tick, int delay, int type); // 通常攻撃処理まとめ int battle_weapon_attack( struct block_list *bl,struct block_list *target, diff --git a/src/map/mob.c b/src/map/mob.c index 13df3a67c..529b75cea 100644 --- a/src/map/mob.c +++ b/src/map/mob.c @@ -741,7 +741,7 @@ static int mob_attack(struct mob_data *md,unsigned int tick,int data) //Use the attack delay for next can attack try //But use the attack motion to know when it can start moving. [Skotlex] md->attackabletime = tick + status_get_adelay(&md->bl); - md->canmove_tick = tick + status_get_amotion(&md->bl); + battle_set_walkdelay(&md->bl, tick, status_get_amotion(&md->bl), 1); md->timer=add_timer(md->attackabletime,mob_timer,md->bl.id,0); md->state.state=MS_ATTACK; diff --git a/src/map/npc.c b/src/map/npc.c index 3c3967762..a8765995e 100644 --- a/src/map/npc.c +++ b/src/map/npc.c @@ -1472,12 +1472,8 @@ int npc_stop_walking(struct npc_data *nd,int type) } if(type&0x01) clif_fixnpcpos(nd); - if(type&0x02) { - int delay=status_get_dmotion(&nd->bl); - unsigned int tick = gettick(); - if(nd->canmove_tick < tick) - nd->canmove_tick = tick + delay; - } + if(type&0x02) + battle_set_walkdelay(&nd->bl, gettick(), status_get_dmotion(&nd->bl), 1); return 0; } diff --git a/src/map/pc.c b/src/map/pc.c index 04bd8a6d1..afe638f1b 100644 --- a/src/map/pc.c +++ b/src/map/pc.c @@ -360,6 +360,9 @@ int pc_can_move(struct map_session_data *sd) if ((sd->sc.option & OPTION_HIDE) && pc_checkskill(sd, RG_TUNNELDRIVE) <= 0) return 0; + if (sd->skilltimer != -1 && pc_checkskill(sd, SA_FREECAST) <= 0) + return 0; + if (pc_issit(sd)) return 0; //Can't move while sitting... diff --git a/src/map/skill.c b/src/map/skill.c index 217d9d3ec..a5a9242e5 100644 --- a/src/map/skill.c +++ b/src/map/skill.c @@ -1688,7 +1688,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds pc_checkskill(sd, MO_CHAINCOMBO) > 0) delay += 300 * battle_config.combo_delay_rate / 100; sc_start4(src,SC_COMBO,100,MO_TRIPLEATTACK,skilllv,0,0,delay); - sd->attackabletime = sd->canmove_tick = tick + delay; + sd->attackabletime = tick + delay; + battle_set_walkdelay(src, tick, delay, 1); clif_combo_delay(src, delay); if (sd->status.party_id>0) //bonus from SG_FRIEND [Komurka] @@ -1702,7 +1703,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds (pc_checkskill(sd, MO_COMBOFINISH) > 0 && sd->spiritball > 0)) delay += 300 * battle_config.combo_delay_rate /100; sc_start4(src,SC_COMBO,100,MO_CHAINCOMBO,skilllv,0,0,delay); - sd->attackabletime = sd->canmove_tick = tick + delay; + sd->attackabletime = tick + delay; + battle_set_walkdelay(src, tick, delay, 1); clif_combo_delay(src,delay); break; } @@ -1717,7 +1719,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds )) delay += 300 * battle_config.combo_delay_rate /100; sc_start4(src,SC_COMBO,100,MO_COMBOFINISH,skilllv,0,0,delay); - sd->attackabletime = sd->canmove_tick = tick + delay; + sd->attackabletime = tick + delay; + battle_set_walkdelay(src, tick, delay, 1); clif_combo_delay(src,delay); break; } @@ -1731,7 +1734,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds )) delay += 300 * battle_config.combo_delay_rate /100; sc_start4(src,SC_COMBO,100,CH_TIGERFIST,skilllv,0,0,delay); - sd->attackabletime = sd->canmove_tick = tick + delay; + sd->attackabletime = tick + delay; + battle_set_walkdelay(src, tick, delay, 1); clif_combo_delay(src,delay); break; } @@ -1741,7 +1745,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds if(damage < status_get_hp(bl)) delay += 300 * battle_config.combo_delay_rate /100; sc_start4(src,SC_COMBO,100,CH_CHAINCRUSH,skilllv,0,0,delay); - sd->attackabletime = sd->canmove_tick = tick + delay; + sd->attackabletime = tick + delay; + battle_set_walkdelay(src, tick, delay, 1); clif_combo_delay(src,delay); break; } @@ -1765,7 +1770,8 @@ int skill_attack( int attack_type, struct block_list* src, struct block_list *ds case TK_DOWNKICK: case TK_TURNKICK: // Delay normal attack table until skill's delay has passed. Let's make it skip one attack motion. [Skotlex] - sd->attackabletime = sd->canmove_tick = tick + status_get_amotion(&sd->bl); + sd->attackabletime = tick + status_get_amotion(&sd->bl); + battle_set_walkdelay(src, tick, status_get_amotion(&sd->bl), 1); break; case SL_STIN: case SL_STUN: @@ -2610,7 +2616,7 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int s int i; for (i = 1; i < sd->spiritball_old; i++) skill_addtimerskill(src, tick + i * 200, bl->id, 0, 0, skillid, skilllv, BF_WEAPON, flag); - sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200; +// sd->canmove_tick = tick + (sd->spiritball_old - 1) * 200; Should be handled by the canmove delay on skill_cast_db [Skotlex] } if (sc && sc->data[SC_BLADESTOP].timer != -1) status_change_end(src,SC_BLADESTOP,-1); @@ -2666,7 +2672,8 @@ int skill_castend_damage_id (struct block_list* src, struct block_list *bl,int s clif_movechar(sd); if(dx < 0) dx = -dx; if(dy < 0) dy = -dy; - sd->attackabletime = sd->canmove_tick = tick + 100 + sd->speed * ((dx > dy)? dx:dy); + sd->attackabletime = tick + 100 + sd->speed * ((dx > dy)? dx:dy); + battle_set_walkdelay(src, tick, 100 + sd->speed * ((dx > dy)? dx:dy), 1); if(sd->canact_tick < sd->canmove_tick) sd->canact_tick = sd->canmove_tick; sd->speed = speed; @@ -3113,10 +3120,6 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in case CR_GRANDCROSS: case NPC_GRANDDARKNESS: //These two are actually ground placed. - if(sd) - sd->canmove_tick = tick + 900; - else if(md) - mob_changestate(md,MS_DELAY,900); return skill_castend_pos2(src,src->x,src->y,skillid,skilllv,tick,0); } tsc = status_get_sc(bl); @@ -4755,8 +4758,8 @@ int skill_castend_nodamage_id (struct block_list *src, struct block_list *bl, in sc_start(bl,type,100,skilllv,skill_time)); if (md) mob_changestate(md,MS_DELAY,skill_time); - else if (sd) - sd->attackabletime = sd->canmove_tick = tick + skill_time; + else + battle_set_walkdelay(bl, tick, skill_time, 1); } break; @@ -5547,7 +5550,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) nullpo_retr(0, sd); //Code cleanup. -#define skill_failed(sd) { sd->skillid = sd->skilllv = sd->skillitem = sd->skillitemlv = -1; sd->canact_tick = sd->canmove_tick = tick; sd->skilltarget = 0; } +#define skill_failed(sd) { sd->skillid = sd->skilllv = sd->skillitem = sd->skillitemlv = -1; sd->canact_tick = tick; sd->skilltarget = 0; } if(sd->skillid != SA_CASTCANCEL && sd->skilltimer != tid ) { /* タイマIDの確認 */ @@ -5654,7 +5657,7 @@ int skill_castend_id( int tid, unsigned int tick, int id,int data ) sd->canact_tick = tick; else sd->canact_tick = tick + skill_delayfix(&sd->bl, sd->skillid, sd->skilllv, 0); - sd->canmove_tick = tick + skill_get_walkdelay(sd->skillid, sd->skilllv); + battle_set_walkdelay(&sd->bl, tick, skill_get_walkdelay(sd->skillid, sd->skilllv), 1); if (skill_get_casttype(sd->skillid) == CAST_NODAMAGE) skill_castend_nodamage_id(&sd->bl,bl,sd->skillid,sd->skilllv,tick,0); else @@ -5686,7 +5689,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) nullpo_retr(0, sd); //Code cleanup. -#define skill_failed(sd) { sd->skillid = sd->skilllv = sd->skillitem = sd->skillitemlv = -1; sd->canact_tick = sd->canmove_tick = tick; } +#define skill_failed(sd) { sd->skillid = sd->skilllv = sd->skillitem = sd->skillitemlv = -1; sd->canact_tick = tick; } if( sd->skilltimer != tid ) { /* タイマIDの確認 */ @@ -5761,7 +5764,7 @@ int skill_castend_pos( int tid, unsigned int tick, int id,int data ) pc_stop_walking(sd,0); sd->canact_tick = tick + skill_delayfix(&sd->bl, sd->skillid, sd->skilllv, 0); - sd->canmove_tick = tick + skill_get_walkdelay(sd->skillid, sd->skilllv); + battle_set_walkdelay(&sd->bl, tick, skill_get_walkdelay(sd->skillid, sd->skilllv), 1); skill_castend_pos2(&sd->bl,sd->skillx,sd->skilly,sd->skillid,sd->skilllv,tick,0); @@ -7289,7 +7292,6 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) struct map_session_data *sd; struct map_session_data *tsd; int *p_sd; //Contains the list of characters found. - unsigned int tick = gettick(); nullpo_retr(0, bl); nullpo_retr(0, ap); @@ -7327,7 +7329,7 @@ static int skill_check_condition_char_sub (struct block_list *bl, va_list ap) default: //Warning: Assuming Ensemble Dance/Songs for code speed. [Skotlex] { int skilllv; - if(pc_issit(tsd) || tsd->skilltimer!=-1 || tsd->canmove_tick > tick) + if(pc_issit(tsd) || !pc_can_move(tsd)) return 0; if (sd->status.sex != tsd->status.sex && (tsd->class_&MAPID_UPPERMASK) == MAPID_BARDDANCER && @@ -8561,12 +8563,10 @@ int skill_use_id (struct map_session_data *sd, int target_id, int skill_num, int sd->skillx = 0; sd->skilly = 0; sd->canact_tick = tick + casttime + 100; - //Recycling forcecast to store the skill's level. [Skotlex] - sd->canmove_tick = tick + (casttime>0 && (forcecast = pc_checkskill(sd,SA_FREECAST)) > 0?0:casttime); if (casttime > 0) { sd->skilltimer = add_timer (tick + casttime, skill_castend_id, sd->bl.id, 0); - if (forcecast > 0) + if ((forcecast = pc_checkskill(sd,SA_FREECAST)) > 0) status_quick_recalc_speed (sd, SA_FREECAST, forcecast, 1); else pc_stop_walking(sd,0); @@ -8678,11 +8678,10 @@ int skill_use_pos (struct map_session_data *sd, int skill_x, int skill_y, int sk sd->skilltarget = 0; sd->canact_tick = tick + casttime + 100; - sd->canmove_tick = tick + (casttime>0 && (skill = pc_checkskill(sd,SA_FREECAST))>0?0:casttime); if (casttime > 0) { sd->skilltimer = add_timer(tick + casttime, skill_castend_pos, sd->bl.id, 0); - if (skill > 0) + if ((skill = pc_checkskill(sd,SA_FREECAST))>0) status_quick_recalc_speed (sd, SA_FREECAST, skill, 1); else pc_stop_walking(sd,0); @@ -8709,12 +8708,11 @@ int skill_castcancel (struct block_list *bl, int type) struct map_session_data *sd = (struct map_session_data *)bl; unsigned long tick = gettick(); nullpo_retr(0, sd); - sd->canact_tick = tick; - sd->canmove_tick = tick; if (sd->skilltimer != -1) { if ((ret = pc_checkskill(sd,SA_FREECAST)) > 0) { status_quick_recalc_speed(sd, SA_FREECAST, ret, 0); //Updated to use calc_speed [Skotlex] } + sd->canact_tick = tick; if (!type) { if (skill_get_inf( sd->skillid ) & INF_GROUND_SKILL) ret = delete_timer( sd->skilltimer, skill_castend_pos ); -- cgit v1.2.3-70-g09d2