- Rewrote/updated the SC_COMBO logic. Got rid of state.combo and added usage of packet 0x7e1 (PACKET_ZC_SKILLINFO_UPDATE2) to report skill inf changes.

- Cleaned up a bit the function clif_setlevel (these functions should be as lightweight as possible...)
- Fixed the server sending twice the skill tree during login.


git-svn-id: https://svn.code.sf.net/p/rathena/svn/trunk@14939 54d463be-8e91-2dee-dedb-b68131a5f0ec
This commit is contained in:
Skotlex 2011-08-23 17:30:08 +00:00
parent 7662f1e897
commit 5b4c84d286
7 changed files with 106 additions and 107 deletions

View File

@ -1,5 +1,7 @@
Date Added Date Added
2011/08/23
* Rewrote the combo logic. Now it uses packet 0x7e1 to signal skill state changes rather than resending the whole skill list. [Skotlex]
2011/08/21 2011/08/21
* Fixed monsters above Lv99 displaying a Lv99 aura (bugreport:3986). [Ai4rei] * Fixed monsters above Lv99 displaying a Lv99 aura (bugreport:3986). [Ai4rei]
- The server no longer caps the level sent to the client by default. - The server no longer caps the level sent to the client by default.

View File

@ -777,32 +777,15 @@ static int clif_setlevel_sub(int lv)
static int clif_setlevel(struct block_list* bl) static int clif_setlevel(struct block_list* bl)
{ {
int lv = status_get_lv(bl); int lv = status_get_lv(bl);
if( battle_config.client_limit_unit_lv&bl->type )
return clif_setlevel_sub(lv);
switch( bl->type ) switch( bl->type )
{ {
case BL_PC:
case BL_HOM:
case BL_MOB:
case BL_MER:
if( battle_config.client_limit_unit_lv&bl->type )
{
lv = clif_setlevel_sub(lv);
}
break;
case BL_NPC: case BL_NPC:
case BL_PET: case BL_PET:
if( battle_config.client_limit_unit_lv&bl->type )
{
lv = clif_setlevel_sub(lv);
break;
}
// npcs and pets do not have level // npcs and pets do not have level
return 0; return 0;
default:
ShowWarning("clif_setlevel: Unhandled bl type %d.\n", bl->type);
break;
} }
return lv; return lv;
} }
@ -4231,10 +4214,7 @@ int clif_skillinfoblock(struct map_session_data *sd)
if( (id = sd->status.skill[i].id) != 0 ) if( (id = sd->status.skill[i].id) != 0 )
{ {
WFIFOW(fd,len) = id; WFIFOW(fd,len) = id;
if( (id == MO_EXTREMITYFIST && sd->state.combo&1) || (id == TK_JUMPKICK && sd->state.combo&2) ) WFIFOW(fd,len+2) = skill_get_inf(id);
WFIFOW(fd,len+2) = INF_SELF_SKILL;
else
WFIFOW(fd,len+2) = skill_get_inf(id);
WFIFOW(fd,len+4) = 0; WFIFOW(fd,len+4) = 0;
WFIFOW(fd,len+6) = sd->status.skill[i].lv; WFIFOW(fd,len+6) = sd->status.skill[i].lv;
WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv); WFIFOW(fd,len+8) = skill_get_sp(id,sd->status.skill[i].lv);
@ -4268,10 +4248,7 @@ int clif_addskill(struct map_session_data *sd, int id )
WFIFOHEAD(fd, packet_len(0x111)); WFIFOHEAD(fd, packet_len(0x111));
WFIFOW(fd,0) = 0x111; WFIFOW(fd,0) = 0x111;
WFIFOW(fd,2) = id; WFIFOW(fd,2) = id;
if( (id == MO_EXTREMITYFIST && sd->state.combo&1) || (id == TK_JUMPKICK && sd->state.combo&2) ) WFIFOW(fd,4) = skill_get_inf(id);
WFIFOW(fd,4) = INF_SELF_SKILL;
else
WFIFOW(fd,4) = skill_get_inf(id);
WFIFOW(fd,6) = 0; WFIFOW(fd,6) = 0;
WFIFOW(fd,8) = sd->status.skill[id].lv; WFIFOW(fd,8) = sd->status.skill[id].lv;
WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv); WFIFOW(fd,10) = skill_get_sp(id,sd->status.skill[id].lv);
@ -4327,6 +4304,24 @@ int clif_skillup(struct map_session_data *sd,int skill_num)
return 0; return 0;
} }
//PACKET_ZC_SKILLINFO_UPDATE2
//Like packet 0x0x10e, but also contains inf information
void clif_skillinfo(struct map_session_data *sd,int skill, int inf)
{
const int fd = sd->fd;
WFIFOHEAD(fd,packet_len(0x7e1));
WFIFOW(fd,0) = 0x7e1;
WFIFOW(fd,2) = skill;
WFIFOL(fd,4) = inf?inf:skill_get_inf(skill);
WFIFOW(fd,8) = sd->status.skill[skill].lv;
WFIFOW(fd,10) = skill_get_sp(skill,sd->status.skill[skill].lv);
WFIFOW(fd,12) = skill_get_range2(&sd->bl,skill,sd->status.skill[skill].lv);
if( sd->status.skill[skill].flag == SKILL_FLAG_PERMANENT )
WFIFOB(fd,14) = (sd->status.skill[skill].lv < skill_tree_get_max(skill, sd->status.class_))? 1:0;
else
WFIFOB(fd,14) = 0;
WFIFOSET(fd,packet_len(0x7e1));
}
/// Notifies clients, that an object is about to use a skill (ZC_USESKILL_ACK/ZC_USESKILL_ACK2) /// Notifies clients, that an object is about to use a skill (ZC_USESKILL_ACK/ZC_USESKILL_ACK2)
/// 013e <src id>.L <dst id>.L <x pos>.W <y pos>.W <skill id>.W <property>.L <delaytime>.L /// 013e <src id>.L <dst id>.L <x pos>.W <y pos>.W <skill id>.W <property>.L <delaytime>.L
@ -10040,7 +10035,7 @@ void clif_parse_UseSkillToId(int fd, struct map_session_data *sd)
if( skillnotok(skillnum, sd) ) if( skillnotok(skillnum, sd) )
return; return;
if( sd->bl.id != target_id && (tmp&INF_SELF_SKILL || sd->state.combo) ) if( sd->bl.id != target_id && tmp&INF_SELF_SKILL )
target_id = sd->bl.id; // never trust the client target_id = sd->bl.id; // never trust the client
if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris] if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris]
@ -15155,7 +15150,7 @@ static int packetdb_readdb(void)
#else // 0x7d9 changed #else // 0x7d9 changed
6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54, 6, 2, -1, 4, 4, 4, 4, 8, 8,268, 6, 8, 6, 54, 30, 54,
#endif #endif
0, 0, 0, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0, 0, 15, 0, 0, 0, 8, 8, 32, -1, 5, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0, 0, 0, 0, 0, 0, 0, 14, -1, -1, -1, 8, 25, 0, 0, 26, 0,
//#0x0800 //#0x0800
#if PACKETVER < 20091229 #if PACKETVER < 20091229

View File

@ -323,6 +323,7 @@ int clif_mob_equip(struct mob_data *md,int nameid); // [Valaris]
int clif_skillinfoblock(struct map_session_data *sd); int clif_skillinfoblock(struct map_session_data *sd);
int clif_skillup(struct map_session_data *sd,int skill_num); int clif_skillup(struct map_session_data *sd,int skill_num);
void clif_skillinfo(struct map_session_data *sd,int skill, int inf);
int clif_addskill(struct map_session_data *sd, int skill); int clif_addskill(struct map_session_data *sd, int skill);
int clif_deleteskill(struct map_session_data *sd, int skill); int clif_deleteskill(struct map_session_data *sd, int skill);

View File

@ -101,7 +101,6 @@ struct map_session_data {
unsigned int lr_flag : 2; unsigned int lr_flag : 2;
unsigned int connect_new : 1; unsigned int connect_new : 1;
unsigned int arrow_atk : 1; unsigned int arrow_atk : 1;
unsigned int combo : 2; // 1:Asura, 2:Kick [Inkfish]
unsigned int gangsterparadise : 1; unsigned int gangsterparadise : 1;
unsigned int rest : 1; unsigned int rest : 1;
unsigned int storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex] unsigned int storage_flag : 2; //0: closed, 1: Normal Storage open, 2: guild storage open [Skotlex]

View File

@ -1697,7 +1697,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
if(sd) { if(sd) {
int flag = 0; //Used to signal if this skill can be combo'ed later on. int flag = 0; //Used to signal if this skill can be combo'ed later on.
if (sd->sc.data[SC_COMBO]) struct status_change_entry *sce;
if ((sce = sd->sc.data[SC_COMBO]))
{ //End combo state after skill is invoked. [Skotlex] { //End combo state after skill is invoked. [Skotlex]
switch (skillid) { switch (skillid) {
case TK_TURNKICK: case TK_TURNKICK:
@ -1706,13 +1707,10 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
case TK_COUNTER: case TK_COUNTER:
if (pc_famerank(sd->status.char_id,MAPID_TAEKWON)) if (pc_famerank(sd->status.char_id,MAPID_TAEKWON))
{ //Extend combo time. { //Extend combo time.
sd->skillid_old = skillid; //Set as previous so you can't repeat sce->val1 = skillid; //Update combo-skill
sd->skilllv_old = skilllv; sce->val3 = skillid;
sd->sc.data[SC_COMBO]->val1 = skillid; //Update combo-skill delete_timer(sce->timer, status_change_timer);
delete_timer(sd->sc.data[SC_COMBO]->timer, status_change_timer); sce->timer = add_timer(tick+sce->val4, status_change_timer, src->id, SC_COMBO);
sd->sc.data[SC_COMBO]->timer = add_timer(
tick+sd->sc.data[SC_COMBO]->val4,
status_change_timer, src->id, SC_COMBO);
break; break;
} }
unit_cancel_combo(src); // Cancel combo wait unit_cancel_combo(src); // Cancel combo wait
@ -1748,7 +1746,7 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
if( (tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc_checkskill(sd, HT_POWER)) if( (tstatus->race == RC_BRUTE || tstatus->race == RC_INSECT) && pc_checkskill(sd, HT_POWER))
{ {
//TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex] //TODO: This code was taken from Triple Blows, is this even how it should be? [Skotlex]
sc_start4(src,SC_COMBO,100,HT_POWER,bl->id,0,0,2000); sc_start2(src,SC_COMBO,100,HT_POWER,bl->id,2000);
clif_combo_delay(src,2000); clif_combo_delay(src,2000);
} }
break; break;
@ -1771,9 +1769,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
} //Switch End } //Switch End
if (flag) { //Possible to chain if (flag) { //Possible to chain
flag = DIFF_TICK(sd->ud.canact_tick, tick); flag = DIFF_TICK(sd->ud.canact_tick, tick);
if (flag < 0) flag = 0; if (flag < 1) flag = 1;
flag += 300 * battle_config.combo_delay_rate/100; sc_start2(src,SC_COMBO,100,skillid,bl->id,flag);
sc_start(src,SC_COMBO,100,skillid,flag);
clif_combo_delay(src, flag); clif_combo_delay(src, flag);
} }
} }
@ -8302,14 +8299,14 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
return 0; //Anti-Soul Linker check in case you job-changed with Stances active. return 0; //Anti-Soul Linker check in case you job-changed with Stances active.
if(!(sc && sc->data[SC_COMBO])) if(!(sc && sc->data[SC_COMBO]))
return 0; //Combo needs to be ready return 0; //Combo needs to be ready
if (pc_famerank(sd->status.char_id,MAPID_TAEKWON))
{ //Unlimited Combo if (sc->data[SC_COMBO]->val3)
if (skill == sd->skillid_old) { { //Kick chain
status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER); //Do not repeat a kick.
sd->skillid_old = sd->skilllv_old = 0; if (sc->data[SC_COMBO]->val3 != skill)
return 0; //Can't repeat previous combo skill. break;
} status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER);
break; return 0;
} }
if(sc->data[SC_COMBO]->val1 != skill) if(sc->data[SC_COMBO]->val1 != skill)
{ //Cancel combo wait. { //Cancel combo wait.
@ -8329,7 +8326,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
if (skill_get_time( if (skill_get_time(
(sc->data[SC_DANCING]->val1&0xFFFF), //Dance Skill ID (sc->data[SC_DANCING]->val1&0xFFFF), //Dance Skill ID
(sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV (sc->data[SC_DANCING]->val1>>16)) //Dance Skill LV
- time <= skill_get_time2(skill,lv)) - time < skill_get_time2(skill,lv))
{ {
clif_skill_fail(sd,skill,0,0); clif_skill_fail(sd,skill,0,0);
return 0; return 0;

View File

@ -2411,6 +2411,11 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
status_cpy(&sd->battle_status, status); status_cpy(&sd->battle_status, status);
// ----- CLIENT-SIDE REFRESH ----- // ----- CLIENT-SIDE REFRESH -----
if(!sd->bl.prev) {
//Will update on LoadEndAck
calculating = 0;
return 0;
}
if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill))) if(memcmp(b_skill,sd->status.skill,sizeof(sd->status.skill)))
clif_skillinfoblock(sd); clif_skillinfoblock(sd);
if(b_weight != sd->weight) if(b_weight != sd->weight)
@ -5766,44 +5771,17 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
//val1: Skill ID //val1: Skill ID
//val2: When given, target (for autotargetting skills) //val2: When given, target (for autotargetting skills)
//val3: When set, this combo time should NOT delay attack/movement //val3: When set, this combo time should NOT delay attack/movement
//val4: Combo time //val3: TK: Last used kick
//val4: TK: Combo time
struct unit_data *ud = unit_bl2ud(bl); struct unit_data *ud = unit_bl2ud(bl);
switch (val1) {
case TK_STORMKICK:
clif_skill_nodamage(bl,bl,TK_READYSTORM,1,1);
break;
case TK_DOWNKICK:
clif_skill_nodamage(bl,bl,TK_READYDOWN,1,1);
break;
case TK_TURNKICK:
clif_skill_nodamage(bl,bl,TK_READYTURN,1,1);
break;
case TK_COUNTER:
clif_skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
break;
case MO_COMBOFINISH:
case CH_TIGERFIST:
case CH_CHAINCRUSH:
if( sd )
{
sd->state.combo = 1;
clif_skillinfoblock(sd);
}
break;
case TK_JUMPKICK:
if( sd )
{
sd->state.combo = 2;
clif_skillinfoblock(sd);
}
break;
}
if (ud && !val3) if (ud && !val3)
{ {
tick += 300 * battle_config.combo_delay_rate/100;
ud->attackabletime = gettick()+tick; ud->attackabletime = gettick()+tick;
unit_set_walkdelay(bl, gettick(), tick, 1); unit_set_walkdelay(bl, gettick(), tick, 1);
} }
val4 = tick; //Store combo-time in val4. val3 = 0;
val4 = tick;
} }
break; break;
case SC_EARTHSCROLL: case SC_EARTHSCROLL:
@ -6337,6 +6315,31 @@ int status_change_start(struct block_list* bl,enum sc_type type,int rate,int val
case SC_MERC_SPUP: case SC_MERC_SPUP:
status_percent_heal(bl, 0, 100); // Recover Full SP status_percent_heal(bl, 0, 100); // Recover Full SP
break; break;
case SC_COMBO:
switch (sce->val1) {
case TK_STORMKICK:
clif_skill_nodamage(bl,bl,TK_READYSTORM,1,1);
break;
case TK_DOWNKICK:
clif_skill_nodamage(bl,bl,TK_READYDOWN,1,1);
break;
case TK_TURNKICK:
clif_skill_nodamage(bl,bl,TK_READYTURN,1,1);
break;
case TK_COUNTER:
clif_skill_nodamage(bl,bl,TK_READYCOUNTER,1,1);
break;
case MO_COMBOFINISH:
case CH_TIGERFIST:
case CH_CHAINCRUSH:
if (sd)
clif_skillinfo(sd,MO_EXTREMITYFIST, INF_SELF_SKILL);
break;
case TK_JUMPKICK:
if (sd)
clif_skillinfo(sd,TK_JUMPKICK, INF_SELF_SKILL);
break;
}
} }
if( opt_flag&2 && sd && sd->touching_id ) if( opt_flag&2 && sd && sd->touching_id )
@ -6675,16 +6678,17 @@ int status_change_end_(struct block_list* bl, enum sc_type type, int tid, const
bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,gettick()); bl->m, bl->x-range, bl->y-range, bl->x+range,bl->y+range,BL_CHAR,bl,sce,type,gettick());
} }
break; break;
case SC_COMBO: //Clear last used skill when it is part of a combo. case SC_COMBO:
if( sd ) if( sd )
{ switch (sce->val1) {
if( sd->state.combo ) case MO_COMBOFINISH:
{ case CH_TIGERFIST:
sd->state.combo = 0; case CH_CHAINCRUSH:
clif_skillinfoblock(sd); clif_skillinfo(sd, MO_EXTREMITYFIST, 0);
} break;
if( sd->skillid_old == sce->val1 ) case TK_JUMPKICK:
sd->skillid_old = sd->skilllv_old = 0; clif_skillinfo(sd, TK_JUMPKICK, 0);
break;
} }
break; break;

View File

@ -912,7 +912,7 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
struct map_session_data *sd = NULL; struct map_session_data *sd = NULL;
struct block_list * target = NULL; struct block_list * target = NULL;
unsigned int tick = gettick(); unsigned int tick = gettick();
int temp; int temp = 0;
nullpo_ret(src); nullpo_ret(src);
if(status_isdead(src)) if(status_isdead(src))
@ -927,14 +927,21 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
sc = NULL; //Unneeded sc = NULL; //Unneeded
//temp: used to signal combo-skills right now. //temp: used to signal combo-skills right now.
temp = ( target_id == src->id && if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num)
( {
( !(skill_get_inf(skill_num)&INF_SELF_SKILL) && sd && sd->state.combo ) || if (sc->data[SC_COMBO]->val2)
( skill_get_inf(skill_num)&INF_SELF_SKILL && skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF ) target_id = sc->data[SC_COMBO]->val2;
) else
); target_id = ud->target;
if (temp) temp = 1;
target_id = ud->target; //Auto-select skills. [Skotlex] } else
if ( target_id == src->id &&
skill_get_inf(skill_num)&INF_SELF_SKILL &&
skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF )
{
target_id = ud->target; //Auto-select target. [Skotlex]
temp = 1;
}
if (sd) { if (sd) {
//Target_id checking. //Target_id checking.
@ -949,12 +956,6 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
return 0; return 0;
} }
break; break;
case TK_JUMPKICK:
case TK_COUNTER:
case HT_POWER:
if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num)
target_id = sc->data[SC_COMBO]->val2;
break;
case WE_MALE: case WE_MALE:
case WE_FEMALE: case WE_FEMALE:
if (!sd->status.partner_id) if (!sd->status.partner_id)