Ver código fonte

- 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

Skotlex 13 anos atrás
pai
commit
5b4c84d286
7 arquivos alterados com 106 adições e 107 exclusões
  1. 2 0
      Changelog-Trunk.txt
  2. 24 29
      src/map/clif.c
  3. 1 0
      src/map/clif.h
  4. 0 1
      src/map/pc.h
  5. 18 21
      src/map/skill.c
  6. 45 41
      src/map/status.c
  7. 16 15
      src/map/unit.c

+ 2 - 0
Changelog-Trunk.txt

@@ -1,5 +1,7 @@
 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
 	* Fixed monsters above Lv99 displaying a Lv99 aura (bugreport:3986). [Ai4rei]
 	- The server no longer caps the level sent to the client by default.

+ 24 - 29
src/map/clif.c

@@ -777,32 +777,15 @@ static int clif_setlevel_sub(int lv)
 static int clif_setlevel(struct block_list* bl)
 {
 	int lv = status_get_lv(bl);
-
+	if( battle_config.client_limit_unit_lv&bl->type )
+		return clif_setlevel_sub(lv);
 	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_PET:
-			if( battle_config.client_limit_unit_lv&bl->type )
-			{
-				lv = clif_setlevel_sub(lv);
-				break;
-			}
 			// npcs and pets do not have level
 			return 0;
-		default:
-			ShowWarning("clif_setlevel: Unhandled bl type %d.\n", bl->type);
-			break;
 	}
-
 	return lv;
 }
 
@@ -4231,10 +4214,7 @@ int clif_skillinfoblock(struct map_session_data *sd)
 		if( (id = sd->status.skill[i].id) != 0 )
 		{
 			WFIFOW(fd,len)   = id;
-			if( (id == MO_EXTREMITYFIST && sd->state.combo&1) || (id == TK_JUMPKICK && sd->state.combo&2) )
-				WFIFOW(fd,len+2) = INF_SELF_SKILL;
-			else
-				WFIFOW(fd,len+2) = skill_get_inf(id);
+			WFIFOW(fd,len+2) = skill_get_inf(id);
 			WFIFOW(fd,len+4) = 0;
 			WFIFOW(fd,len+6) = 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));
 	WFIFOW(fd,0) = 0x111;
 	WFIFOW(fd,2) = id;
-	if( (id == MO_EXTREMITYFIST && sd->state.combo&1) || (id == TK_JUMPKICK && sd->state.combo&2) )
-		WFIFOW(fd,4) = INF_SELF_SKILL;
-	else
-		WFIFOW(fd,4) = skill_get_inf(id);
+	WFIFOW(fd,4) = skill_get_inf(id);
  	WFIFOW(fd,6) = 0;
 	WFIFOW(fd,8) = 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;
 }
 
+//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)
 /// 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) )
 		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
 	
 	if( target_id < 0 && -target_id == sd->bl.id ) // for disguises [Valaris]
@@ -15155,7 +15150,7 @@ static int packetdb_readdb(void)
 #else // 0x7d9 changed
 	    6,  2, -1,  4,  4,  4,  4,  8,  8,268,  6,  8,  6, 54, 30, 54,
 #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,
 	//#0x0800
 #if PACKETVER < 20091229

+ 1 - 0
src/map/clif.h

@@ -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_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_deleteskill(struct map_session_data *sd, int skill);
 

+ 0 - 1
src/map/pc.h

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

+ 18 - 21
src/map/skill.c

@@ -1697,7 +1697,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 
 	if(sd) {
 		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]
 			switch (skillid) {
 			case TK_TURNKICK:
@@ -1706,13 +1707,10 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 			case TK_COUNTER:
 				if (pc_famerank(sd->status.char_id,MAPID_TAEKWON))
 			  	{	//Extend combo time.
-					sd->skillid_old = skillid; //Set as previous so you can't repeat
-					sd->skilllv_old = skilllv;
-					sd->sc.data[SC_COMBO]->val1 = skillid; //Update combo-skill
-					delete_timer(sd->sc.data[SC_COMBO]->timer, status_change_timer);
-					sd->sc.data[SC_COMBO]->timer = add_timer(
-						tick+sd->sc.data[SC_COMBO]->val4,
-					  	status_change_timer, src->id, SC_COMBO);
+					sce->val1 = skillid; //Update combo-skill
+					sce->val3 = skillid;
+					delete_timer(sce->timer, status_change_timer);
+					sce->timer = add_timer(tick+sce->val4, status_change_timer, src->id, SC_COMBO);
 					break;
 				}
 				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))
 				{
 					//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);
 				}
 				break;
@@ -1771,9 +1769,8 @@ int skill_attack (int attack_type, struct block_list* src, struct block_list *ds
 		}	//Switch End
 		if (flag) { //Possible to chain
 			flag = DIFF_TICK(sd->ud.canact_tick, tick);
-			if (flag < 0) flag = 0;
-			flag += 300 * battle_config.combo_delay_rate/100;
-			sc_start(src,SC_COMBO,100,skillid,flag);
+			if (flag < 1) flag = 1;
+			sc_start2(src,SC_COMBO,100,skillid,bl->id,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.
 		if(!(sc && sc->data[SC_COMBO]))
 			return 0; //Combo needs to be ready
-		if (pc_famerank(sd->status.char_id,MAPID_TAEKWON))
-		{	//Unlimited Combo
-			if (skill == sd->skillid_old) {
-				status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER);
-				sd->skillid_old = sd->skilllv_old = 0;
-				return 0; //Can't repeat previous combo skill.
-			}
-			break;
+
+		if (sc->data[SC_COMBO]->val3)
+		{	//Kick chain
+			//Do not repeat a kick.
+			if (sc->data[SC_COMBO]->val3 != skill)
+				break;
+			status_change_end(&sd->bl, SC_COMBO, INVALID_TIMER);
+			return 0;
 		}
 		if(sc->data[SC_COMBO]->val1 != skill)
 		{	//Cancel combo wait.
@@ -8329,7 +8326,7 @@ int skill_check_condition_castbegin(struct map_session_data* sd, short skill, sh
 			if (skill_get_time(
 				(sc->data[SC_DANCING]->val1&0xFFFF), //Dance Skill ID
 				(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);
 				return 0;

+ 45 - 41
src/map/status.c

@@ -2411,6 +2411,11 @@ int status_calc_pc_(struct map_session_data* sd, bool first)
 	status_cpy(&sd->battle_status, status);
 
 // ----- 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)))
 		clif_skillinfoblock(sd);
 	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
 			//val2: When given, target (for autotargetting skills)
 			//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);
-			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) 
 			{
+				tick += 300 * battle_config.combo_delay_rate/100;
 				ud->attackabletime = gettick()+tick;
 				unit_set_walkdelay(bl, gettick(), tick, 1);
 			}
-			val4 = tick; //Store combo-time in val4.
+			val3 = 0;
+			val4 = tick;
 		}
 			break;
 		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:
 			status_percent_heal(bl, 0, 100); // Recover Full SP
 			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 )
@@ -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());
 			}
 			break;
-		case SC_COMBO: //Clear last used skill when it is part of a combo.
+		case SC_COMBO:
 			if( sd )
-			{
-				if( sd->state.combo )
-				{
-					sd->state.combo = 0;
-					clif_skillinfoblock(sd);
-				}
-				if( sd->skillid_old == sce->val1 )
-					sd->skillid_old = sd->skilllv_old = 0;
+			switch (sce->val1) {
+				case MO_COMBOFINISH:
+				case CH_TIGERFIST:
+				case CH_CHAINCRUSH:
+					clif_skillinfo(sd, MO_EXTREMITYFIST, 0);
+					break;
+				case TK_JUMPKICK:
+					clif_skillinfo(sd, TK_JUMPKICK, 0);
+					break;
 			}
 			break;
 

+ 16 - 15
src/map/unit.c

@@ -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 block_list * target = NULL;
 	unsigned int tick = gettick();
-	int temp;
+	int temp = 0;
 
 	nullpo_ret(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
 
 	//temp: used to signal combo-skills right now.
-	temp =	( target_id == src->id && 
-				( 
-					( !(skill_get_inf(skill_num)&INF_SELF_SKILL) && sd && sd->state.combo ) || 
-					( skill_get_inf(skill_num)&INF_SELF_SKILL && skill_get_inf2(skill_num)&INF2_NO_TARGET_SELF ) 
-				) 
-			);
-	if (temp)
-		target_id = ud->target; //Auto-select skills. [Skotlex]
+	if (sc && sc->data[SC_COMBO] && sc->data[SC_COMBO]->val1 == skill_num)
+	{
+		if (sc->data[SC_COMBO]->val2)
+			target_id = sc->data[SC_COMBO]->val2;
+		else
+			target_id = ud->target;
+		temp = 1;
+	} 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) {
 		//Target_id checking.
@@ -949,12 +956,6 @@ int unit_skilluse_id2(struct block_list *src, int target_id, short skill_num, sh
 					return 0;
 			}
 			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_FEMALE:
 			if (!sd->status.partner_id)